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
30class NotificationService;
31
32class NotificationListener {
33public:
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
49class UserMessagingMessageSender {
50public:
51								UserMessagingMessageSender();
52
53			void				SendMessage(const KMessage* message,
54									port_id port, int32 token);
55			void				FlushMessage();
56
57private:
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
67class UserMessagingListener : public NotificationListener {
68public:
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
85private:
86	UserMessagingMessageSender&	fSender;
87	port_id						fPort;
88	int32						fToken;
89};
90
91inline bool
92UserMessagingListener::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
100class NotificationService : public BReferenceable {
101public:
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
115private:
116			NotificationService* fLink;
117};
118
119struct default_listener : public DoublyLinkedListLinkImpl<default_listener> {
120	~default_listener();
121
122	uint32	eventMask;
123	team_id	team;
124	NotificationListener* listener;
125};
126
127typedef DoublyLinkedList<default_listener> DefaultListenerList;
128
129
130class DefaultNotificationService : public NotificationService {
131public:
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
159protected:
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
170class DefaultUserNotificationService : public DefaultNotificationService,
171	NotificationListener {
172public:
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
188private:
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
199class NotificationManager {
200public:
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
226private:
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
256void
257DefaultNotificationService::Notify(const KMessage& event, uint32 eventMask)
258{
259	RecursiveLocker _(fLock);
260	NotifyLocked(event, eventMask);
261}
262
263
264extern "C" {
265
266#endif	// __cplusplus
267
268void notifications_init(void);
269
270#ifdef __cplusplus
271}
272#endif	// __cplusplus
273
274#endif	// _KERNEL_NOTIFICATIONS_H
275