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
Port()79 port_id Port() const { return fPort; }
Token()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*&
Link()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
Lock()135 inline bool Lock()
136 { return recursive_lock_lock(&fLock)
137 == B_OK; }
Unlock()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
HasListeners()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
Name()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
HashKeyHashDefinition237 size_t HashKey(const char* key) const
238 { return hash_hash_string(key); }
HashHashDefinition239 size_t Hash(NotificationService *service) const
240 { return hash_hash_string(service->Name()); }
CompareHashDefinition241 bool Compare(const char* key, NotificationService* service) const
242 { return !strcmp(key, service->Name()); }
GetLinkHashDefinition243 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
Notify(const KMessage & event,uint32 eventMask)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