xref: /haiku/src/servers/registrar/WatchingService.cpp (revision bc3955fea5b07e2e94a27fc05e4bb58fe6f0319b)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		WatchingService.cpp
23 //	Author:			Ingo Weinhold (bonefish@users.sf.net)
24 //	Description:	Features everything needed to provide a watching service.
25 //------------------------------------------------------------------------------
26 
27 #include <List.h>
28 
29 #include "Watcher.h"
30 #include "WatchingService.h"
31 
32 using namespace std;
33 
34 /*!	\class WatchingService
35 	\brief Features everything needed to provide a watching service.
36 
37 	A watcher is represented by an object of the Watcher or a derived class.
38 	It is identified by its target BMessenger. The service can't contain
39 	more than one watcher with the same target BMessenger at a time.
40 
41 	New watchers can be registered with AddWatcher(), registered ones
42 	unregistered via RemoveRegister(). NotifyWatchers() sends a specified
43 	message to all registered watchers, or, if an optional WatcherFilter is
44 	supplied, only to those watchers it selects.
45 */
46 
47 /*!	\var typedef map<BMessenger,Watcher*> WatchingService::watcher_map
48 	\brief Watcher container type.
49 
50 	Defined for convenience.
51 */
52 
53 /*!	\var WatchingService::watcher_map WatchingService::fWatchers
54 	\brief Container for the watchers registered to the service.
55 
56 	For each registered watcher \code Watcher *watcher \endcode, the map
57 	contains an entry \code (watcher->Target(), watcher) \endcode.
58 */
59 
60 
61 // constructor
62 /*!	\brief Creates a new watching service.
63 
64 	The list of watchers is initially empty.
65 */
66 WatchingService::WatchingService()
67 	: fWatchers()
68 {
69 }
70 
71 // destructor
72 /*!	\brief Frees all resources associated with the object.
73 
74 	All registered watchers are deleted.
75 */
76 WatchingService::~WatchingService()
77 {
78 	// delete the watchers
79 	for (watcher_map::iterator it = fWatchers.begin();
80 		 it != fWatchers.end();
81 		 ++it) {
82 		delete it->second;
83 	}
84 }
85 
86 // AddWatcher
87 /*!	\brief Registers a new watcher to the watching service.
88 
89 	The ownership of \a watcher is transfered to the watching service, that
90 	is the caller must not delete it after the method returns.
91 
92 	If the service already contains a Watcher with the same target BMessenger
93 	(Watcher::Target()), the old watcher is removed and deleted before the
94 	new one is added..
95 
96 	\param watcher The watcher to be registered.
97 	\return \c true, if \a watcher is not \c NULL and adding was successfully,
98 			\c false otherwise.
99 */
100 bool
101 WatchingService::AddWatcher(Watcher *watcher)
102 {
103 	bool result = (watcher);
104 	if (result) {
105 		RemoveWatcher(watcher->Target(), true);
106 		fWatchers[watcher->Target()] = watcher;
107 	}
108 	return result;
109 }
110 
111 // AddWatcher
112 /*!	\brief Registers a new watcher to the watching service.
113 
114 	A new \c Watcher is created with \a target as its target and added to
115 	the watching service. The caller retains ownership of \a target, but the
116 	newly created Watcher is owned by the watching service.
117 
118 	If the service already contains a Watcher with the same target BMessenger
119 	(Watcher::Target()), the old watcher is removed and deleted before the
120 	new one is added..
121 
122 	\param target The target BMessenger a Watcher shall be registered for.
123 	\return \c true, if a new Watcher could be created and added successfully,
124 			\c false otherwise.
125 */
126 bool
127 WatchingService::AddWatcher(const BMessenger &target)
128 {
129 	return AddWatcher(new(nothrow) Watcher(target));
130 }
131 
132 // RemoveWatcher
133 /*!	\brief Unregisters a watcher from the watching service and optionally
134 		   deletes it.
135 
136 	If \a deleteWatcher is \c false, the ownership of \a watcher is transfered
137 	to the caller, otherwise it is deleted.
138 
139 	\param watcher The watcher to be unregistered.
140 	\param deleteWatcher If \c true, the watcher is deleted after being
141 		   removed.
142 	\return \c true, if \a watcher was not \c NULL and registered to the
143 			watching service before, \c false otherwise.
144 */
145 bool
146 WatchingService::RemoveWatcher(Watcher *watcher, bool deleteWatcher)
147 {
148 	watcher_map::iterator it = fWatchers.find(watcher->Target());
149 	bool result = (it != fWatchers.end() && it->second == watcher);
150 	if (result) {
151 		if (deleteWatcher)
152 			delete it->second;
153 		fWatchers.erase(it);
154 	}
155 	return result;
156 }
157 
158 // RemoveWatcher
159 /*!	\brief Unregisters a watcher from the watching service and optionally
160 		   deletes it.
161 
162 	The watcher is identified by its target BMessenger.
163 
164 	If \a deleteWatcher is \c false, the ownership of the concerned watcher is
165 	transfered to the caller, otherwise it is deleted.
166 
167 	\param target The target BMessenger identifying the watcher to be
168 		   unregistered.
169 	\param deleteWatcher If \c true, the watcher is deleted after being
170 		   removed.
171 	\return \c true, if a watcher with the specified target was registered to
172 			the watching service before, \c false otherwise.
173 */
174 bool
175 WatchingService::RemoveWatcher(const BMessenger &target, bool deleteWatcher)
176 {
177 	watcher_map::iterator it = fWatchers.find(target);
178 	bool result = (it != fWatchers.end());
179 	if (result) {
180 		if (deleteWatcher)
181 			delete it->second;
182 		fWatchers.erase(it);
183 	}
184 	return result;
185 }
186 
187 // NotifyWatchers
188 /*!	\brief Sends a notification message to all watcher targets selected by a
189 		   supplied filter.
190 
191 	If no filter is supplied the message is sent to all watchers. Otherwise
192 	each watcher (and the notification message) is passed to its
193 	WatcherFilter::Filter() method and the message is sent only to those
194 	watchers for which \c true is returned.
195 
196 	If a sending a message to a watcher's target failed, because it became
197 	invalid, the watcher is unregistered and deleted.
198 
199 	\param message The message to be sent to the watcher targets.
200 	\param filter The filter selecting the watchers to which the message
201 		   is be sent. May be \c NULL.
202 */
203 void
204 WatchingService::NotifyWatchers(BMessage *message, WatcherFilter *filter)
205 {
206 	if (message) {
207 		BList staleWatchers;
208 		// deliver the message
209 		for (watcher_map::iterator it = fWatchers.begin();
210 			 it != fWatchers.end();
211 			 ++it) {
212 			Watcher *watcher = it->second;
213 // TODO: If a watcher is invalid, but the filter never selects it, it will
214 // not be removed.
215 			if (!filter || filter->Filter(watcher, message)) {
216 				status_t error = watcher->SendMessage(message);
217 				if (error != B_OK && !watcher->Target().IsValid())
218 					staleWatchers.AddItem(watcher);
219 			}
220 		}
221 		// remove the stale watchers
222 		for (int32 i = 0;
223 			 Watcher *watcher = (Watcher*)staleWatchers.ItemAt(i);
224 			 i++) {
225 			RemoveWatcher(watcher, true);
226 		}
227 	}
228 }
229 
230