#include <List.h>
#include "Watcher.h"
#include "WatchingService.h"
using namespace std;
\brief Features everything needed to provide a watching service.
A watcher is represented by an object of the Watcher or a derived class.
It is identified by its target BMessenger. The service can't contain
more than one watcher with the same target BMessenger at a time.
New watchers can be registered with AddWatcher(), registered ones
unregistered via RemoveRegister(). NotifyWatchers() sends a specified
message to all registered watchers, or, if an optional WatcherFilter is
supplied, only to those watchers it selects.
*/
\brief Watcher container type.
Defined for convenience.
*/
\brief Container for the watchers registered to the service.
For each registered watcher \code Watcher *watcher \endcode, the map
contains an entry \code (watcher->Target(), watcher) \endcode.
*/
The list of watchers is initially empty.
*/
WatchingService::WatchingService()
: fWatchers()
{
}
All registered watchers are deleted.
*/
WatchingService::~WatchingService()
{
for (watcher_map::iterator it = fWatchers.begin();
it != fWatchers.end();
++it) {
delete it->second;
}
}
The ownership of \a watcher is transfered to the watching service, that
is the caller must not delete it after the method returns.
If the service already contains a Watcher with the same target BMessenger
(Watcher::Target()), the old watcher is removed and deleted before the
new one is added..
\param watcher The watcher to be registered.
\return \c true, if \a watcher is not \c NULL and adding was successfully,
\c false otherwise.
*/
bool
WatchingService::AddWatcher(Watcher *watcher)
{
bool result = (watcher);
if (result) {
RemoveWatcher(watcher->Target(), true);
fWatchers[watcher->Target()] = watcher;
}
return result;
}
A new \c Watcher is created with \a target as its target and added to
the watching service. The caller retains ownership of \a target, but the
newly created Watcher is owned by the watching service.
If the service already contains a Watcher with the same target BMessenger
(Watcher::Target()), the old watcher is removed and deleted before the
new one is added..
\param target The target BMessenger a Watcher shall be registered for.
\return \c true, if a new Watcher could be created and added successfully,
\c false otherwise.
*/
bool
WatchingService::AddWatcher(const BMessenger &target)
{
return AddWatcher(new(nothrow) Watcher(target));
}
deletes it.
If \a deleteWatcher is \c false, the ownership of \a watcher is transfered
to the caller, otherwise it is deleted.
\param watcher The watcher to be unregistered.
\param deleteWatcher If \c true, the watcher is deleted after being
removed.
\return \c true, if \a watcher was not \c NULL and registered to the
watching service before, \c false otherwise.
*/
bool
WatchingService::RemoveWatcher(Watcher *watcher, bool deleteWatcher)
{
watcher_map::iterator it = fWatchers.find(watcher->Target());
bool result = (it != fWatchers.end() && it->second == watcher);
if (result) {
if (deleteWatcher)
delete it->second;
fWatchers.erase(it);
}
return result;
}
deletes it.
The watcher is identified by its target BMessenger.
If \a deleteWatcher is \c false, the ownership of the concerned watcher is
transfered to the caller, otherwise it is deleted.
\param target The target BMessenger identifying the watcher to be
unregistered.
\param deleteWatcher If \c true, the watcher is deleted after being
removed.
\return \c true, if a watcher with the specified target was registered to
the watching service before, \c false otherwise.
*/
bool
WatchingService::RemoveWatcher(const BMessenger &target, bool deleteWatcher)
{
watcher_map::iterator it = fWatchers.find(target);
bool result = (it != fWatchers.end());
if (result) {
if (deleteWatcher)
delete it->second;
fWatchers.erase(it);
}
return result;
}
supplied filter.
If no filter is supplied the message is sent to all watchers. Otherwise
each watcher (and the notification message) is passed to its
WatcherFilter::Filter() method and the message is sent only to those
watchers for which \c true is returned.
If a sending a message to a watcher's target failed, because it became
invalid, the watcher is unregistered and deleted.
\param message The message to be sent to the watcher targets.
\param filter The filter selecting the watchers to which the message
is be sent. May be \c NULL.
*/
void
WatchingService::NotifyWatchers(BMessage *message, WatcherFilter *filter)
{
if (message) {
BList staleWatchers;
for (watcher_map::iterator it = fWatchers.begin();
it != fWatchers.end();
++it) {
Watcher *watcher = it->second;
if (!filter || filter->Filter(watcher, message)) {
status_t error = watcher->SendMessage(message);
if (error != B_OK && !watcher->Target().IsValid())
staleWatchers.AddItem(watcher);
}
}
for (int32 i = 0;
Watcher *watcher = (Watcher*)staleWatchers.ItemAt(i);
i++) {
RemoveWatcher(watcher, true);
}
}
}