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