155076Sache//------------------------------------------------------------------------------ 255076Sache// Copyright (c) 2001-2002, OpenBeOS 355076Sache// 455076Sache// Permission is hereby granted, free of charge, to any person obtaining a 555076Sache// copy of this software and associated documentation files (the "Software"), 655076Sache// to deal in the Software without restriction, including without limitation 755076Sache// the rights to use, copy, modify, merge, publish, distribute, sublicense, 855076Sache// and/or sell copies of the Software, and to permit persons to whom the 955076Sache// Software is furnished to do so, subject to the following conditions: 1055076Sache// 1155076Sache// The above copyright notice and this permission notice shall be included in 1255076Sache// all copies or substantial portions of the Software. 1355076Sache// 1455076Sache// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1555076Sache// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1655076Sache// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1755076Sache// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1855076Sache// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1955076Sache// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2055076Sache// DEALINGS IN THE SOFTWARE. 2155076Sache// 2255076Sache// File Name: WatchingService.cpp 2355076Sache// Author: Ingo Weinhold (bonefish@users.sf.net) 2455076Sache// Description: Features everything needed to provide a watching service. 2555076Sache//------------------------------------------------------------------------------ 2655076Sache 2755076Sache#include <List.h> 2855076Sache 2955076Sache#include "Watcher.h" 3055076Sache#include "WatchingService.h" 3155076Sache 3255076Sacheusing namespace std; 3355076Sache 3455076Sache/*! \class WatchingService 3555076Sache \brief Features everything needed to provide a watching service. 3655076Sache 3755076Sache A watcher is represented by an object of the Watcher or a derived class. 3855076Sache It is identified by its target BMessenger. The service can't contain 3955076Sache more than one watcher with the same target BMessenger at a time. 4055076Sache 4155076Sache New watchers can be registered with AddWatcher(), registered ones 4255076Sache unregistered via RemoveRegister(). NotifyWatchers() sends a specified 4355076Sache message to all registered watchers, or, if an optional WatcherFilter is 4455076Sache supplied, only to those watchers it selects. 4555076Sache*/ 4655076Sache 4755076Sache/*! \var typedef map<BMessenger,Watcher*> WatchingService::watcher_map 4855076Sache \brief Watcher container type. 4955076Sache 5055076Sache Defined for convenience. 5155076Sache*/ 5255076Sache 5355076Sache/*! \var WatchingService::watcher_map WatchingService::fWatchers 5455076Sache \brief Container for the watchers registered to the service. 5555076Sache 5655076Sache For each registered watcher \code Watcher *watcher \endcode, the map 5755076Sache contains an entry \code (watcher->Target(), watcher) \endcode. 5855076Sache*/ 5955076Sache 6055076Sache 6155076Sache// constructor 6255076Sache/*! \brief Creates a new watching service. 6355076Sache 6455076Sache The list of watchers is initially empty. 6555076Sache*/ 6655076SacheWatchingService::WatchingService() 6755076Sache : fWatchers() 6855076Sache{ 6955076Sache} 7055076Sache 7155076Sache// destructor 7255076Sache/*! \brief Frees all resources associated with the object. 7355076Sache 7455076Sache All registered watchers are deleted. 7555076Sache*/ 7655076SacheWatchingService::~WatchingService() 7755076Sache{ 7855076Sache // delete the watchers 7955076Sache for (watcher_map::iterator it = fWatchers.begin(); 8055076Sache it != fWatchers.end(); 8155076Sache ++it) { 8255076Sache delete it->second; 8355076Sache } 8455076Sache} 8555076Sache 8655076Sache// AddWatcher 8755076Sache/*! \brief Registers a new watcher to the watching service. 8855076Sache 8955076Sache The ownership of \a watcher is transfered to the watching service, that 9055076Sache is the caller must not delete it after the method returns. 9155076Sache 9255076Sache If the service already contains a Watcher with the same target BMessenger 9355076Sache (Watcher::Target()), the old watcher is removed and deleted before the 9455076Sache new one is added.. 9555076Sache 9655076Sache \param watcher The watcher to be registered. 9755076Sache \return \c true, if \a watcher is not \c NULL and adding was successfully, 9855076Sache \c false otherwise. 9955076Sache*/ 10055076Sachebool 10155076SacheWatchingService::AddWatcher(Watcher *watcher) 10255076Sache{ 10355076Sache bool result = (watcher); 10455076Sache if (result) { 10555076Sache RemoveWatcher(watcher->Target(), true); 10655076Sache fWatchers[watcher->Target()] = watcher; 10755076Sache } 10855076Sache return result; 10955076Sache} 11055076Sache 11155076Sache// AddWatcher 11255076Sache/*! \brief Registers a new watcher to the watching service. 11355076Sache 11455076Sache A new \c Watcher is created with \a target as its target and added to 11555076Sache the watching service. The caller retains ownership of \a target, but the 11655076Sache newly created Watcher is owned by the watching service. 11755076Sache 11855076Sache If the service already contains a Watcher with the same target BMessenger 11955076Sache (Watcher::Target()), the old watcher is removed and deleted before the 12055076Sache new one is added.. 12155076Sache 12255076Sache \param target The target BMessenger a Watcher shall be registered for. 12355076Sache \return \c true, if a new Watcher could be created and added successfully, 12455076Sache \c false otherwise. 12555076Sache*/ 12655076Sachebool 12755076SacheWatchingService::AddWatcher(const BMessenger &target) 12855076Sache{ 12955076Sache return AddWatcher(new(nothrow) Watcher(target)); 13055076Sache} 13155076Sache 13255076Sache// RemoveWatcher 13355076Sache/*! \brief Unregisters a watcher from the watching service and optionally 13455076Sache deletes it. 13555076Sache 13655076Sache If \a deleteWatcher is \c false, the ownership of \a watcher is transfered 13755076Sache to the caller, otherwise it is deleted. 13855076Sache 13955076Sache \param watcher The watcher to be unregistered. 14055076Sache \param deleteWatcher If \c true, the watcher is deleted after being 14155076Sache removed. 14255076Sache \return \c true, if \a watcher was not \c NULL and registered to the 14355076Sache watching service before, \c false otherwise. 14455076Sache*/ 14555076Sachebool 14655076SacheWatchingService::RemoveWatcher(Watcher *watcher, bool deleteWatcher) 14755076Sache{ 14855076Sache watcher_map::iterator it = fWatchers.find(watcher->Target()); 14955076Sache bool result = (it != fWatchers.end() && it->second == watcher); 15055076Sache if (result) { 15155076Sache if (deleteWatcher) 15255076Sache delete it->second; 15355076Sache fWatchers.erase(it); 15455076Sache } 15555076Sache return result; 15655076Sache} 15755076Sache 15855076Sache// RemoveWatcher 15955076Sache/*! \brief Unregisters a watcher from the watching service and optionally 16055076Sache deletes it. 16155076Sache 16255076Sache The watcher is identified by its target BMessenger. 16355076Sache 16455076Sache If \a deleteWatcher is \c false, the ownership of the concerned watcher is 16555076Sache transfered to the caller, otherwise it is deleted. 16655076Sache 16755076Sache \param target The target BMessenger identifying the watcher to be 16855076Sache unregistered. 16955076Sache \param deleteWatcher If \c true, the watcher is deleted after being 17055076Sache removed. 17155076Sache \return \c true, if a watcher with the specified target was registered to 17255076Sache the watching service before, \c false otherwise. 17355076Sache*/ 17455076Sachebool 17555076SacheWatchingService::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*/ 203void 204WatchingService::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