2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // ObservableHandler.cpp
34 #include "ObservableHandler.h"
39 __USE_CORTEX_NAMESPACE
41 // ---------------------------------------------------------------- //
43 // ---------------------------------------------------------------- //
45 // clients must call release() rather than deleting,
46 // to ensure that all observers are notified of the
47 // object's demise. if the object has already been
48 // released, return an error.
50 status_t
ObservableHandler::release() {
55 // "ObservableHandler::release(): %ld targets\n", CountTargets()));
58 ASSERT(!"failed to lock looper");
77 // ---------------------------------------------------------------- //
79 // ---------------------------------------------------------------- //
81 ObservableHandler::~ObservableHandler() {
84 "*** ~ObservableHandler() '%s': %" B_PRId32
" observers remain\n",
85 Name(), CountTargets()));
89 ObservableHandler::ObservableHandler(
94 ObservableHandler::ObservableHandler(
99 // ---------------------------------------------------------------- //
101 // ---------------------------------------------------------------- //
103 // return true if release() has been called, false otherwise.
104 bool ObservableHandler::isReleased() const {
108 // ---------------------------------------------------------------- //
110 // ---------------------------------------------------------------- //
112 // sends M_OBSERVER_ADDED to the newly-added observer
113 void ObservableHandler::observerAdded(
114 const BMessenger
& observer
) {
116 BMessage
m(M_OBSERVER_ADDED
);
117 m
.AddMessenger("target", BMessenger(this));
118 observer
.SendMessage(&m
);
121 // sends M_OBSERVER_REMOVED to the newly-removed observer
122 void ObservableHandler::observerRemoved(
123 const BMessenger
& observer
) {
125 BMessage
m(M_OBSERVER_REMOVED
);
126 m
.AddMessenger("target", BMessenger(this));
127 observer
.SendMessage(&m
);
130 // ---------------------------------------------------------------- //
131 // *** internal operations
132 // ---------------------------------------------------------------- //
134 // call to send the given message to all observers.
135 // Responsibility for deletion of the message remains with
138 status_t
ObservableHandler::notify(
141 BLooper
* l
= Looper();
143 ASSERT(l
->IsLocked());
146 return Invoke(message
);
149 // sends M_RELEASE_OBSERVABLE
150 void ObservableHandler::notifyRelease() {
151 BMessage
m(M_RELEASE_OBSERVABLE
);
152 m
.AddMessenger("target", BMessenger(this));
156 // ---------------------------------------------------------------- //
158 // ---------------------------------------------------------------- //
160 void ObservableHandler::MessageReceived(
164 // "### ObservableHandler::MessageReceived()\n"));
165 // message->PrintToStream();
167 switch(message
->what
) {
169 _handleAddObserver(message
);
172 case M_REMOVE_OBSERVER
:
173 _handleRemoveObserver(message
);
176 case M_KILL_OBSERVABLE
:
177 // +++++ this should be an optional feature
179 delete this; // BOOM!
183 _inherited::MessageReceived(message
);
187 // ---------------------------------------------------------------- //
189 // ---------------------------------------------------------------- //
191 status_t
ObservableHandler::Archive(
196 BLooper
* l
= Looper();
198 ASSERT(l
->IsLocked());
201 return B_NOT_ALLOWED
; // can't archive a dead object
203 return _inherited::Archive(archive
, deep
);
206 // ---------------------------------------------------------------- //
208 // ---------------------------------------------------------------- //
210 void ObservableHandler::_handleAddObserver(
214 BLooper
* l
= Looper();
216 ASSERT(l
->IsLocked());
221 status_t err
= message
->FindMessenger(
222 "observer", &observer
);
225 "* ObservableHandler::_handleAddObserver(): no observer specified!\n"));
232 reply
.what
= M_BAD_TARGET
;
233 reply
.AddMessenger("target", BMessenger(this));
234 reply
.AddMessenger("observer", observer
);
235 message
->SendReply(&reply
);
239 else if(IndexOfTarget(observer
.Target(0)) != -1) {
240 // observer already added
241 reply
.what
= M_BAD_OBSERVER
;
242 reply
.AddMessenger("target", BMessenger(this));
243 reply
.AddMessenger("observer", observer
);
244 message
->SendReply(&reply
);
249 // valid observer given
252 err
= AddTarget(observer
.Target(0));
256 observerAdded(observer
);
259 void ObservableHandler::_handleRemoveObserver(
263 BLooper
* l
= Looper();
265 ASSERT(l
->IsLocked());
270 status_t err
= message
->FindMessenger(
271 "observer", &observer
);
274 "* ObservableHandler::_handleRemoveObserver(): no observer specified!\n"));
279 int32 index
= IndexOfTarget(observer
.Target(0));
281 reply
.what
= M_BAD_OBSERVER
;
283 reply
.AddMessenger("target", BMessenger(this));
284 reply
.AddMessenger("observer", observer
);
285 message
->SendReply(&reply
);
289 // valid observer given; remove it & call notification hook
291 observerRemoved(observer
);
293 // time to shut down?
294 if(m_released
&& !CountTargets()) {
296 delete this; // BOOM!
301 // END -- ObservableHandler.cpp --