1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef NOTIFICATION_CHAIN_H 17 #define NOTIFICATION_CHAIN_H 18 19 #include <map> 20 #include <set> 21 #include <thread> 22 #include <condition_variable> 23 24 #include "ref_object.h" 25 26 namespace DistributedDB { 27 using EventType = unsigned int; 28 29 class NotificationChain final : public RefObject { 30 private: 31 class ListenerChain; 32 33 public: 34 class Listener final : public RefObject { 35 public: 36 using OnEvent = std::function<void(void *)>; 37 using OnFinalize = std::function<void(void)>; 38 39 // Called by ListenerChain.callbackListeners, it will call the OnEvent 40 void NotifyListener(void *arg); 41 42 // Drop this listener. after call this function, the listener will be destroy 43 int Drop(bool wait = false); 44 45 // Enter kill-waiting state if 'onEvent()' is invoking when 'KillObj()'. 46 void KillWait(); 47 48 // Set the listener chain we belong to. 49 void SetOwner(ListenerChain *listenerChain); 50 51 Listener(const OnEvent &onEvent, const OnFinalize &onFinalize); 52 53 // Delete the copy and assign constructors 54 DISABLE_COPY_ASSIGN_MOVE(Listener); 55 56 protected: 57 ~Listener() override; 58 59 private: 60 // will be call when this listener destroy 61 void Finalize() const; 62 bool EnterEventAction(); 63 void LeaveEventAction(); 64 65 DECLARE_OBJECT_TAG(Listener); 66 67 constexpr static int KILL_WAIT_SECONDS = 5; // wait only 5 seconds when killing to avoid dead-lock. 68 OnEvent onEvent_; 69 OnFinalize onFinalize_; 70 ListenerChain *listenerChain_; 71 std::thread::id eventRunningThread_; 72 std::condition_variable safeKill_; 73 }; 74 75 // Add a listener from the NotificationChain. it will return a Listener handle 76 // The param type should match the RegisterEventsType 77 // The param onEvent will be call when events happened. 78 // The param onFinalize will be call when this listener destroy 79 Listener *RegisterListener(EventType type, const Listener::OnEvent &onEvent, 80 const Listener::OnFinalize &onFinalize, int &errCode); 81 82 // User to register an events type to the NotificationChain, needs to call at init 83 int RegisterEventType(EventType type); 84 85 // User to unregister an events type. 86 int UnRegisterEventType(EventType type); 87 88 // Should be call when events happened. 89 void NotifyEvent(EventType type, void *arg); 90 91 bool EmptyListener(EventType type) const; 92 93 NotificationChain() = default; 94 95 // Delete the copy and assign constructors 96 DISABLE_COPY_ASSIGN_MOVE(NotificationChain); 97 98 protected: 99 ~NotificationChain() override; 100 101 private: 102 class ListenerChain final : public RefObject { 103 public: 104 // Add a listener to the ListenerChain 105 int RegisterListener(Listener *listener); 106 107 // Remove a listener to the ListenerChain 108 int UnRegisterListener(Listener *listener, bool wait = false); 109 110 // Callback all the listeners 111 void NotifyListeners(void *arg); 112 113 // Clear all listeners 114 void ClearListeners(); 115 116 bool Empty() const; 117 118 ListenerChain(); 119 120 // Delete the copy and assign constructors 121 DISABLE_COPY_ASSIGN_MOVE(ListenerChain); 122 protected: 123 ~ListenerChain() override; 124 125 private: 126 // Used to back up listenerSet_, need to lock 127 void BackupListenerSet(std::set<Listener *> &backupSet) const; 128 129 DECLARE_OBJECT_TAG(ListenerChain); 130 131 std::set<Listener *> listenerSet_; 132 }; 133 134 // Find a ListenerChain from the eventChains_ with given type, 135 // this function needs to lock. 136 ListenerChain *FindAndGetListenerChainLocked(EventType type) const; 137 138 // Find a ListenerChain from the eventChains_ with given type, 139 ListenerChain *FindListenerChain(EventType type) const; 140 141 DECLARE_OBJECT_TAG(NotificationChain); 142 143 std::map<EventType, ListenerChain *> eventChains_; 144 }; 145 } // namespace DistributedDB 146 147 #endif // NOTIFICATION_CHAIN_H 148