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 // ObservableLooper.cpp
34 #include "ObservableLooper.h"
37 #include <MessageRunner.h>
39 __USE_CORTEX_NAMESPACE
42 // ---------------------------------------------------------------- //
44 // ---------------------------------------------------------------- //
46 // clients must call release() rather than deleting,
47 // to ensure that all observers are notified of the
48 // object's demise. if the object has already been
49 // released, return an error.
51 status_t
ObservableLooper::release() {
53 // +++++ what if I'm not running?
54 // +++++ is a lock necessary?
59 // send request through proper channels
60 BMessenger(this).SendMessage(B_QUIT_REQUESTED
);
65 // ---------------------------------------------------------------- //
67 // ---------------------------------------------------------------- //
69 ObservableLooper::~ObservableLooper() {
72 "*** ~ObservableLooper() '%s': %" B_PRId32
" observers remain\n",
73 Name(), CountTargets()));
79 ObservableLooper::ObservableLooper(
83 bigtime_t quitTimeout
) :
84 BLooper(name
, priority
, portCapacity
),
85 m_quitTimeout(quitTimeout
),
89 ObservableLooper::ObservableLooper(
92 m_quitTimeout(B_INFINITE_TIMEOUT
),
96 archive
->FindInt64("quitTimeout", (int64
*)&m_quitTimeout
);
99 // ---------------------------------------------------------------- //
101 // ---------------------------------------------------------------- //
103 bool ObservableLooper::isReleased() const {
107 // ---------------------------------------------------------------- //
109 // ---------------------------------------------------------------- //
111 // sends M_OBSERVER_ADDED to the newly-added observer
112 void ObservableLooper::observerAdded(
113 const BMessenger
& observer
) {
115 BMessage
m(M_OBSERVER_ADDED
);
116 m
.AddMessenger("target", BMessenger(this));
117 observer
.SendMessage(&m
);
120 // sends M_OBSERVER_REMOVED to the newly-removed observer
121 void ObservableLooper::observerRemoved(
122 const BMessenger
& observer
) {
124 BMessage
m(M_OBSERVER_REMOVED
);
125 m
.AddMessenger("target", BMessenger(this));
126 observer
.SendMessage(&m
);
129 // ---------------------------------------------------------------- //
130 // *** internal operations
131 // ---------------------------------------------------------------- //
133 status_t
ObservableLooper::notify(
137 return Invoke(message
);
140 // sends M_RELEASE_OBSERVABLE
141 void ObservableLooper::notifyRelease() {
142 BMessage
m(M_RELEASE_OBSERVABLE
);
143 m
.AddMessenger("target", BMessenger(this));
147 // ---------------------------------------------------------------- //
149 // ---------------------------------------------------------------- //
151 void ObservableLooper::Quit() {
154 if(QuitRequested()) {
162 bool ObservableLooper::QuitRequested() {
168 // no release request yet sent
171 if(m_quitTimeout
!= B_INFINITE_TIMEOUT
) {
172 // Initiate a timer to force quit -- if an observer
173 // has died, it shouldn't take me down with it.
174 ASSERT(!m_executioner
);
175 m_executioner
= new BMessageRunner(
177 new BMessage(M_KILL_OBSERVABLE
),
183 // targets remain, so don't quit.
191 // ---------------------------------------------------------------- //
193 // ---------------------------------------------------------------- //
195 void ObservableLooper::MessageReceived(
199 // "### ObservableLooper::MessageReceived()\n"));
200 // message->PrintToStream();
202 switch(message
->what
) {
204 _handleAddObserver(message
);
207 case M_REMOVE_OBSERVER
:
208 _handleRemoveObserver(message
);
211 case M_KILL_OBSERVABLE
:
217 _inherited::MessageReceived(message
);
221 // ---------------------------------------------------------------- //
223 // ---------------------------------------------------------------- //
225 status_t
ObservableLooper::Archive(
231 // can't archive an object in limbo
233 return B_NOT_ALLOWED
;
235 status_t err
= _inherited::Archive(archive
, deep
);
239 archive
->AddInt64("quitTimeout", m_quitTimeout
);
243 // ---------------------------------------------------------------- //
245 // ---------------------------------------------------------------- //
247 void ObservableLooper::_handleAddObserver(
253 status_t err
= message
->FindMessenger(
254 "observer", &observer
);
257 "* ObservableLooper::_handleAddObserver(): no observer specified!\n"));
262 // at this point, a reply of some sort will be sent
263 reply
.AddMessenger("target", BMessenger(this));
264 reply
.AddMessenger("observer", observer
);
268 reply
.what
= M_BAD_TARGET
;
270 else if(IndexOfTarget(observer
.Target(0)) != -1) {
271 // observer already added
272 reply
.what
= M_BAD_OBSERVER
;
276 err
= AddTarget(observer
.Target(0));
278 reply
.what
= M_OBSERVER_ADDED
;
282 message
->SendReply(&reply
);
285 observerAdded(observer
);
288 void ObservableLooper::_handleRemoveObserver(
291 // PRINT(("ObservableLooper::_handleRemoveObserver():\n"
292 // " %ld targets\n", CountTargets()));
296 status_t err
= message
->FindMessenger(
297 "observer", &observer
);
300 "* ObservableLooper::_handleRemoveObserver(): no observer specified!\n"));
305 // at this point, a reply of some sort will be sent
306 reply
.AddMessenger("target", BMessenger(this));
307 reply
.AddMessenger("observer", observer
);
309 int32 index
= IndexOfTarget(observer
.Target(0));
311 reply
.what
= M_BAD_OBSERVER
;
315 reply
.what
= M_OBSERVER_REMOVED
;
318 message
->SendReply(&reply
);
321 observerRemoved(observer
);
323 // time to shut down?
324 if(m_quitting
&& !CountTargets()) {
330 // END -- ObservableLooper.cpp --