1 /* 2 * Copyright 2007-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Ingo Weinhold, bonefish@cs.tu-berlin.de 8 */ 9 #ifndef _KERNEL_NOTIFICATIONS_H 10 #define _KERNEL_NOTIFICATIONS_H 11 12 13 #include <SupportDefs.h> 14 15 #include <lock.h> 16 #include <messaging.h> 17 #include <util/StringHash.h> 18 19 20 #ifdef __cplusplus 21 22 #include <Referenceable.h> 23 24 #include <util/AutoLock.h> 25 #include <util/DoublyLinkedList.h> 26 #include <util/KMessage.h> 27 #include <util/OpenHashTable.h> 28 29 30 class NotificationService; 31 32 class NotificationListener { 33 public: 34 virtual ~NotificationListener(); 35 36 virtual void EventOccurred(NotificationService& service, 37 const KMessage* event); 38 virtual void AllListenersNotified( 39 NotificationService& service); 40 41 virtual bool operator==( 42 const NotificationListener& other) const; 43 44 bool operator!=( 45 const NotificationListener& other) const 46 { return !(*this == other); } 47 }; 48 49 class UserMessagingMessageSender { 50 public: 51 UserMessagingMessageSender(); 52 53 void SendMessage(const KMessage* message, 54 port_id port, int32 token); 55 void FlushMessage(); 56 57 private: 58 enum { 59 MAX_MESSAGING_TARGET_COUNT = 16, 60 }; 61 62 const KMessage* fMessage; 63 messaging_target fTargets[MAX_MESSAGING_TARGET_COUNT]; 64 int32 fTargetCount; 65 }; 66 67 class UserMessagingListener : public NotificationListener { 68 public: 69 UserMessagingListener( 70 UserMessagingMessageSender& sender, 71 port_id port, int32 token); 72 virtual ~UserMessagingListener(); 73 74 virtual void EventOccurred(NotificationService& service, 75 const KMessage* event); 76 virtual void AllListenersNotified( 77 NotificationService& service); 78 79 port_id Port() const { return fPort; } 80 int32 Token() const { return fToken; } 81 82 bool operator==( 83 const NotificationListener& _other) const; 84 85 private: 86 UserMessagingMessageSender& fSender; 87 port_id fPort; 88 int32 fToken; 89 }; 90 91 inline bool 92 UserMessagingListener::operator==(const NotificationListener& _other) const 93 { 94 const UserMessagingListener* other 95 = dynamic_cast<const UserMessagingListener*>(&_other); 96 return other != NULL && other->Port() == Port() 97 && other->Token() == Token(); 98 } 99 100 class NotificationService : public BReferenceable { 101 public: 102 virtual ~NotificationService(); 103 104 virtual status_t AddListener(const KMessage* eventSpecifier, 105 NotificationListener& listener) = 0; 106 virtual status_t RemoveListener(const KMessage* eventSpecifier, 107 NotificationListener& listener) = 0; 108 virtual status_t UpdateListener(const KMessage* eventSpecifier, 109 NotificationListener& listener) = 0; 110 111 virtual const char* Name() = 0; 112 NotificationService*& 113 Link() { return fLink; } 114 115 private: 116 NotificationService* fLink; 117 }; 118 119 struct default_listener : public DoublyLinkedListLinkImpl<default_listener> { 120 ~default_listener(); 121 122 uint32 eventMask; 123 team_id team; 124 NotificationListener* listener; 125 }; 126 127 typedef DoublyLinkedList<default_listener> DefaultListenerList; 128 129 130 class DefaultNotificationService : public NotificationService { 131 public: 132 DefaultNotificationService(const char* name); 133 virtual ~DefaultNotificationService(); 134 135 inline bool Lock() 136 { return recursive_lock_lock(&fLock) 137 == B_OK; } 138 inline void Unlock() 139 { recursive_lock_unlock(&fLock); } 140 141 inline void Notify(const KMessage& event, uint32 eventMask); 142 void NotifyLocked(const KMessage& event, 143 uint32 eventMask); 144 145 inline bool HasListeners() const 146 { return !fListeners.IsEmpty(); } 147 virtual status_t AddListener(const KMessage* eventSpecifier, 148 NotificationListener& listener); 149 virtual status_t UpdateListener(const KMessage* eventSpecifier, 150 NotificationListener& listener); 151 virtual status_t RemoveListener(const KMessage* eventSpecifier, 152 NotificationListener& listener); 153 154 virtual const char* Name() { return fName; } 155 156 status_t Register(); 157 void Unregister(); 158 159 protected: 160 virtual status_t ToEventMask(const KMessage& eventSpecifier, 161 uint32& eventMask); 162 virtual void FirstAdded(); 163 virtual void LastRemoved(); 164 165 recursive_lock fLock; 166 DefaultListenerList fListeners; 167 const char* fName; 168 }; 169 170 class DefaultUserNotificationService : public DefaultNotificationService, 171 NotificationListener { 172 public: 173 DefaultUserNotificationService( 174 const char* name); 175 virtual ~DefaultUserNotificationService(); 176 177 virtual status_t AddListener(const KMessage* eventSpecifier, 178 NotificationListener& listener); 179 virtual status_t UpdateListener(const KMessage* eventSpecifier, 180 NotificationListener& listener); 181 virtual status_t RemoveListener(const KMessage* eventSpecifier, 182 NotificationListener& listener); 183 184 status_t RemoveUserListeners(port_id port, uint32 token); 185 status_t UpdateUserListener(uint32 eventMask, 186 port_id port, uint32 token); 187 188 private: 189 virtual void EventOccurred(NotificationService& service, 190 const KMessage* event); 191 virtual void AllListenersNotified( 192 NotificationService& service); 193 status_t _AddListener(uint32 eventMask, 194 NotificationListener& listener); 195 196 UserMessagingMessageSender fSender; 197 }; 198 199 class NotificationManager { 200 public: 201 static NotificationManager& Manager(); 202 static status_t CreateManager(); 203 204 status_t RegisterService(NotificationService& service); 205 void UnregisterService( 206 NotificationService& service); 207 208 status_t AddListener(const char* service, 209 uint32 eventMask, 210 NotificationListener& listener); 211 status_t AddListener(const char* service, 212 const KMessage* eventSpecifier, 213 NotificationListener& listener); 214 215 status_t UpdateListener(const char* service, 216 uint32 eventMask, 217 NotificationListener& listener); 218 status_t UpdateListener(const char* service, 219 const KMessage* eventSpecifier, 220 NotificationListener& listener); 221 222 status_t RemoveListener(const char* service, 223 const KMessage* eventSpecifier, 224 NotificationListener& listener); 225 226 private: 227 NotificationManager(); 228 ~NotificationManager(); 229 230 status_t _Init(); 231 NotificationService* _ServiceFor(const char* name); 232 233 struct HashDefinition { 234 typedef const char* KeyType; 235 typedef NotificationService ValueType; 236 237 size_t HashKey(const char* key) const 238 { return hash_hash_string(key); } 239 size_t Hash(NotificationService *service) const 240 { return hash_hash_string(service->Name()); } 241 bool Compare(const char* key, NotificationService* service) const 242 { return !strcmp(key, service->Name()); } 243 NotificationService*& GetLink( 244 NotificationService* service) const 245 { return service->Link(); } 246 }; 247 typedef BOpenHashTable<HashDefinition> ServiceHash; 248 249 static NotificationManager sManager; 250 251 mutex fLock; 252 ServiceHash fServiceHash; 253 }; 254 255 256 void 257 DefaultNotificationService::Notify(const KMessage& event, uint32 eventMask) 258 { 259 RecursiveLocker _(fLock); 260 NotifyLocked(event, eventMask); 261 } 262 263 264 extern "C" { 265 266 #endif // __cplusplus 267 268 void notifications_init(void); 269 270 #ifdef __cplusplus 271 } 272 #endif // __cplusplus 273 274 #endif // _KERNEL_NOTIFICATIONS_H 275