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/khash.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 Referenceable { 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 protected: 156 virtual status_t ToEventMask(const KMessage& eventSpecifier, 157 uint32& eventMask); 158 virtual void FirstAdded(); 159 virtual void LastRemoved(); 160 161 recursive_lock fLock; 162 DefaultListenerList fListeners; 163 const char* fName; 164 }; 165 166 class DefaultUserNotificationService : public DefaultNotificationService, 167 NotificationListener { 168 public: 169 DefaultUserNotificationService( 170 const char* name); 171 virtual ~DefaultUserNotificationService(); 172 173 virtual status_t AddListener(const KMessage* eventSpecifier, 174 NotificationListener& listener); 175 virtual status_t UpdateListener(const KMessage* eventSpecifier, 176 NotificationListener& listener); 177 virtual status_t RemoveListener(const KMessage* eventSpecifier, 178 NotificationListener& listener); 179 180 status_t RemoveUserListeners(port_id port, uint32 token); 181 status_t UpdateUserListener(uint32 eventMask, 182 port_id port, uint32 token); 183 184 private: 185 virtual void EventOccurred(NotificationService& service, 186 const KMessage* event); 187 virtual void AllListenersNotified( 188 NotificationService& service); 189 status_t _AddListener(uint32 eventMask, 190 NotificationListener& listener); 191 192 UserMessagingMessageSender fSender; 193 }; 194 195 class NotificationManager { 196 public: 197 static NotificationManager& Manager(); 198 static status_t CreateManager(); 199 200 status_t RegisterService(NotificationService& service); 201 void UnregisterService( 202 NotificationService& service); 203 204 status_t AddListener(const char* service, 205 uint32 eventMask, 206 NotificationListener& listener); 207 status_t AddListener(const char* service, 208 const KMessage* eventSpecifier, 209 NotificationListener& listener); 210 211 status_t UpdateListener(const char* service, 212 uint32 eventMask, 213 NotificationListener& listener); 214 status_t UpdateListener(const char* service, 215 const KMessage* eventSpecifier, 216 NotificationListener& listener); 217 218 status_t RemoveListener(const char* service, 219 const KMessage* eventSpecifier, 220 NotificationListener& listener); 221 222 private: 223 NotificationManager(); 224 ~NotificationManager(); 225 226 status_t _Init(); 227 NotificationService* _ServiceFor(const char* name); 228 229 struct HashDefinition { 230 typedef const char* KeyType; 231 typedef NotificationService ValueType; 232 233 size_t HashKey(const char* key) const 234 { return hash_hash_string(key); } 235 size_t Hash(NotificationService *service) const 236 { return hash_hash_string(service->Name()); } 237 bool Compare(const char* key, NotificationService* service) const 238 { return !strcmp(key, service->Name()); } 239 NotificationService*& GetLink( 240 NotificationService* service) const 241 { return service->Link(); } 242 }; 243 typedef BOpenHashTable<HashDefinition> ServiceHash; 244 245 static NotificationManager sManager; 246 247 mutex fLock; 248 ServiceHash fServiceHash; 249 }; 250 251 252 void 253 DefaultNotificationService::Notify(const KMessage& event, uint32 eventMask) 254 { 255 RecursiveLocker _(fLock); 256 NotifyLocked(event, eventMask); 257 } 258 259 260 extern "C" { 261 262 #endif // __cplusplus 263 264 void notifications_init(void); 265 266 #ifdef __cplusplus 267 } 268 #endif // __cplusplus 269 270 #endif // _KERNEL_NOTIFICATIONS_H 271