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