btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / cortex / support / ObservableHandler.cpp
blob3eda698e79a8f4117ffa16af4c680a5e72a49e06
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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"
36 #include <Debug.h>
37 #include <Looper.h>
39 __USE_CORTEX_NAMESPACE
41 // ---------------------------------------------------------------- //
42 // *** deletion
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() {
51 if(m_released)
52 return B_NOT_ALLOWED;
54 // PRINT((
55 // "ObservableHandler::release(): %ld targets\n", CountTargets()));
57 if(!LockLooper()) {
58 ASSERT(!"failed to lock looper");
61 m_released = true;
63 if(CountTargets()) {
64 // notify
65 notifyRelease();
66 UnlockLooper();
68 else {
69 releaseComplete();
70 UnlockLooper();
71 delete this;
74 return B_OK;
77 // ---------------------------------------------------------------- //
78 // *** ctor/dtor
79 // ---------------------------------------------------------------- //
81 ObservableHandler::~ObservableHandler() {
82 if(CountTargets()) {
83 PRINT((
84 "*** ~ObservableHandler() '%s': %" B_PRId32 " observers remain\n",
85 Name(), CountTargets()));
89 ObservableHandler::ObservableHandler(
90 const char* name) :
91 BHandler(name),
92 m_released(false) {}
94 ObservableHandler::ObservableHandler(
95 BMessage* archive) :
96 BHandler(archive),
97 m_released(false) {}
99 // ---------------------------------------------------------------- //
100 // *** accessors
101 // ---------------------------------------------------------------- //
103 // return true if release() has been called, false otherwise.
104 bool ObservableHandler::isReleased() const {
105 return m_released;
108 // ---------------------------------------------------------------- //
109 // *** hooks
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
136 // the caller.
138 status_t ObservableHandler::notify(
139 BMessage* message) {
140 #if DEBUG
141 BLooper* l = Looper();
142 ASSERT(l);
143 ASSERT(l->IsLocked());
144 #endif
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));
153 notify(&m);
156 // ---------------------------------------------------------------- //
157 // *** BHandler
158 // ---------------------------------------------------------------- //
160 void ObservableHandler::MessageReceived(
161 BMessage* message) {
163 // PRINT((
164 // "### ObservableHandler::MessageReceived()\n"));
165 // message->PrintToStream();
167 switch(message->what) {
168 case M_ADD_OBSERVER:
169 _handleAddObserver(message);
170 break;
172 case M_REMOVE_OBSERVER:
173 _handleRemoveObserver(message);
174 break;
176 case M_KILL_OBSERVABLE:
177 // +++++ this should be an optional feature
178 releaseComplete();
179 delete this; // BOOM!
180 break;
182 default:
183 _inherited::MessageReceived(message);
187 // ---------------------------------------------------------------- //
188 // *** BArchivable
189 // ---------------------------------------------------------------- //
191 status_t ObservableHandler::Archive(
192 BMessage* archive,
193 bool deep) const {
195 #if DEBUG
196 BLooper* l = Looper();
197 ASSERT(l);
198 ASSERT(l->IsLocked());
199 #endif
200 if(m_released)
201 return B_NOT_ALLOWED; // can't archive a dead object
203 return _inherited::Archive(archive, deep);
206 // ---------------------------------------------------------------- //
207 // implementation
208 // ---------------------------------------------------------------- //
210 void ObservableHandler::_handleAddObserver(
211 BMessage* message) {
213 #if DEBUG
214 BLooper* l = Looper();
215 ASSERT(l);
216 ASSERT(l->IsLocked());
217 #endif
218 BMessage reply;
220 BMessenger observer;
221 status_t err = message->FindMessenger(
222 "observer", &observer);
223 if(err < B_OK) {
224 PRINT((
225 "* ObservableHandler::_handleAddObserver(): no observer specified!\n"));
226 // send reply? +++++
227 return;
230 if(m_released) {
231 // already quitting
232 reply.what = M_BAD_TARGET;
233 reply.AddMessenger("target", BMessenger(this));
234 reply.AddMessenger("observer", observer);
235 message->SendReply(&reply);
237 return;
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);
246 return;
249 // valid observer given
251 // add it
252 err = AddTarget(observer.Target(0));
253 ASSERT(err == B_OK);
255 // call hook
256 observerAdded(observer);
259 void ObservableHandler::_handleRemoveObserver(
260 BMessage* message) {
262 #if DEBUG
263 BLooper* l = Looper();
264 ASSERT(l);
265 ASSERT(l->IsLocked());
266 #endif
267 BMessage reply;
269 BMessenger observer;
270 status_t err = message->FindMessenger(
271 "observer", &observer);
272 if(err < B_OK) {
273 PRINT((
274 "* ObservableHandler::_handleRemoveObserver(): no observer specified!\n"));
275 // send reply? +++++
276 return;
279 int32 index = IndexOfTarget(observer.Target(0));
280 if(index == -1) {
281 reply.what = M_BAD_OBSERVER;
283 reply.AddMessenger("target", BMessenger(this));
284 reply.AddMessenger("observer", observer);
285 message->SendReply(&reply);
286 return;
289 // valid observer given; remove it & call notification hook
290 RemoveTarget(index);
291 observerRemoved(observer);
293 // time to shut down?
294 if(m_released && !CountTargets()) {
295 releaseComplete();
296 delete this; // BOOM!
301 // END -- ObservableHandler.cpp --