xref: /haiku/src/apps/cortex/support/observe.h (revision 19ae20e67e91fc09cc9fc5c0e60e21e24e7a53eb)
1*c284bb0fSMatt Madia /*
2*c284bb0fSMatt Madia  * Copyright (c) 1999-2000, Eric Moon.
3*c284bb0fSMatt Madia  * All rights reserved.
4*c284bb0fSMatt Madia  *
5*c284bb0fSMatt Madia  * Redistribution and use in source and binary forms, with or without
6*c284bb0fSMatt Madia  * modification, are permitted provided that the following conditions
7*c284bb0fSMatt Madia  * are met:
8*c284bb0fSMatt Madia  *
9*c284bb0fSMatt Madia  * 1. Redistributions of source code must retain the above copyright
10*c284bb0fSMatt Madia  *    notice, this list of conditions, and the following disclaimer.
11*c284bb0fSMatt Madia  *
12*c284bb0fSMatt Madia  * 2. Redistributions in binary form must reproduce the above copyright
13*c284bb0fSMatt Madia  *    notice, this list of conditions, and the following disclaimer in the
14*c284bb0fSMatt Madia  *    documentation and/or other materials provided with the distribution.
15*c284bb0fSMatt Madia  *
16*c284bb0fSMatt Madia  * 3. The name of the author may not be used to endorse or promote products
17*c284bb0fSMatt Madia  *    derived from this software without specific prior written permission.
18*c284bb0fSMatt Madia  *
19*c284bb0fSMatt Madia  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20*c284bb0fSMatt Madia  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21*c284bb0fSMatt Madia  * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*c284bb0fSMatt Madia  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23*c284bb0fSMatt Madia  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24*c284bb0fSMatt Madia  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*c284bb0fSMatt Madia  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26*c284bb0fSMatt Madia  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27*c284bb0fSMatt Madia  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28*c284bb0fSMatt Madia  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*c284bb0fSMatt Madia  */
30*c284bb0fSMatt Madia 
31*c284bb0fSMatt Madia 
32a0795c6fSMarcus Overhagen // Observe.h (cortex)
33a0795c6fSMarcus Overhagen // * PURPOSE
34a0795c6fSMarcus Overhagen //   Messages used for implementation of the Observer pattern.
35a0795c6fSMarcus Overhagen //
36a0795c6fSMarcus Overhagen // * HISTORY
37a0795c6fSMarcus Overhagen //   e.moon		19aug99		Begun
38a0795c6fSMarcus Overhagen 
39a0795c6fSMarcus Overhagen #ifndef __Observe_H__
40a0795c6fSMarcus Overhagen #define __Observe_H__
41a0795c6fSMarcus Overhagen 
42a0795c6fSMarcus Overhagen #include <Messenger.h>
4323e67806SIthamar R. Adema #include <Debug.h>
44e501ca3bSMaurice Kalinowski #include <string.h>
45a0795c6fSMarcus Overhagen 
46a0795c6fSMarcus Overhagen #include "cortex_defs.h"
47a0795c6fSMarcus Overhagen __BEGIN_CORTEX_NAMESPACE
48a0795c6fSMarcus Overhagen 
49a0795c6fSMarcus Overhagen // -------------------------------------------------------- //
50a0795c6fSMarcus Overhagen // *** MESSAGES ***
51a0795c6fSMarcus Overhagen // -------------------------------------------------------- //
52a0795c6fSMarcus Overhagen 
53a0795c6fSMarcus Overhagen // messages sent to the Observable (source)
54a0795c6fSMarcus Overhagen enum observer_message_t {
55a0795c6fSMarcus Overhagen 	// Requests that an observer be added to a given
56a0795c6fSMarcus Overhagen 	// observable (target).
57a0795c6fSMarcus Overhagen 	// - "observer" (BMessenger)
58a0795c6fSMarcus Overhagen 	M_ADD_OBSERVER							= Observer_message_base,
59a0795c6fSMarcus Overhagen 
60a0795c6fSMarcus Overhagen 	// Requests that a given observable (target) stop
61a0795c6fSMarcus Overhagen 	// sending notifications to a given observer.
62a0795c6fSMarcus Overhagen 	// Should be sent in response to M_RELEASE_OBSERVABLE
63a0795c6fSMarcus Overhagen 	// in order to allow the observable object to be deleted.
64a0795c6fSMarcus Overhagen 	// - "observer" (BMessenger)
65a0795c6fSMarcus Overhagen 	M_REMOVE_OBSERVER,
66a0795c6fSMarcus Overhagen 
67a0795c6fSMarcus Overhagen 	// Requests that an observable quit immediately without
68a0795c6fSMarcus Overhagen 	// waiting for its observers to acknowledge that they're done.
69a0795c6fSMarcus Overhagen 	// This should only be posted to an Observable in an
70a0795c6fSMarcus Overhagen 	// emergency
71a0795c6fSMarcus Overhagen 	M_KILL_OBSERVABLE
72a0795c6fSMarcus Overhagen };
73a0795c6fSMarcus Overhagen 
74a0795c6fSMarcus Overhagen 
75a0795c6fSMarcus Overhagen // messages sent by the Observable (target)
76a0795c6fSMarcus Overhagen enum target_message_t {
77a0795c6fSMarcus Overhagen 	// sent when the target is no longer needed; the
78a0795c6fSMarcus Overhagen 	// observer should reply with M_REMOVE_OBSERVER in order
79a0795c6fSMarcus Overhagen 	// to release (allow the deletion of) the target
80a0795c6fSMarcus Overhagen 	// - "target" (BMessenger)
81a0795c6fSMarcus Overhagen 	M_RELEASE_OBSERVABLE				= Observable_message_base,
82a0795c6fSMarcus Overhagen 
83a0795c6fSMarcus Overhagen 	// SUGGESTED BUT NOT REQUIRED FOR IObservable IMPLEMENTATION:
84a0795c6fSMarcus Overhagen 	// *** IObservables are encouraged to send other replies!
85a0795c6fSMarcus Overhagen 	// sent upon successful receipt of M_ADD_OBSERVER
86a0795c6fSMarcus Overhagen 	// - "target" (BMessenger)
87a0795c6fSMarcus Overhagen 	M_OBSERVER_ADDED,
88a0795c6fSMarcus Overhagen 
89a0795c6fSMarcus Overhagen 	// SUGGESTED BUT NOT REQUIRED FOR IObservable IMPLEMENTATION:
90a0795c6fSMarcus Overhagen 	// *** IObservables are encouraged to send other replies!
91a0795c6fSMarcus Overhagen 	// sent upon successful receipt of M_REMOVE_OBSERVER
92a0795c6fSMarcus Overhagen 	// - "target" (BMessenger)
93a0795c6fSMarcus Overhagen 	M_OBSERVER_REMOVED,
94a0795c6fSMarcus Overhagen 
95a0795c6fSMarcus Overhagen 	// sent when no matching observer was found for an
96a0795c6fSMarcus Overhagen 	// M_REMOVE_OBSERVER message, or if the observer specified
97a0795c6fSMarcus Overhagen 	// in an M_ADD_OBSERVER message was previously added.
98a0795c6fSMarcus Overhagen 	// - "target" (BMessenger)
99a0795c6fSMarcus Overhagen 	// - "observer" (BMessenger)
100a0795c6fSMarcus Overhagen 	M_BAD_OBSERVER,
101a0795c6fSMarcus Overhagen 
102a0795c6fSMarcus Overhagen 	// sent when the target receiving an M_ADD_OBSERVER
103a0795c6fSMarcus Overhagen 	// or M_REMOVE_OBSERVER didn't match the target described
104a0795c6fSMarcus Overhagen 	// in the message.  also sent if the target is currently
105a0795c6fSMarcus Overhagen 	// in the process of quitting (it's already sent M_RELEASE_OBSERVABLE
106a0795c6fSMarcus Overhagen 	// to its current observers, and is waiting for them to acknowledge
107a0795c6fSMarcus Overhagen 	// with M_REMOVE_OBSERVER so that it can delete itself.)
108a0795c6fSMarcus Overhagen 	// - "target" (BMessenger)
109a0795c6fSMarcus Overhagen 	// - "observer" (BMessenger)
110a0795c6fSMarcus Overhagen 	M_BAD_TARGET
111a0795c6fSMarcus Overhagen };
112a0795c6fSMarcus Overhagen 
113a0795c6fSMarcus Overhagen // -------------------------------------------------------- //
114a0795c6fSMarcus Overhagen // *** FUNCTIONS ***
115a0795c6fSMarcus Overhagen // -------------------------------------------------------- //
116a0795c6fSMarcus Overhagen 
117a0795c6fSMarcus Overhagen // * Asynchronous
118a0795c6fSMarcus Overhagen 
119a0795c6fSMarcus Overhagen status_t add_observer(
120a0795c6fSMarcus Overhagen 	const BMessenger&				observer,
121a0795c6fSMarcus Overhagen 	const BMessenger&				target);
122a0795c6fSMarcus Overhagen 
123a0795c6fSMarcus Overhagen status_t remove_observer(
124a0795c6fSMarcus Overhagen 	const BMessenger&				observer,
125a0795c6fSMarcus Overhagen 	const BMessenger&				target);
126a0795c6fSMarcus Overhagen 
127a0795c6fSMarcus Overhagen // * Synchronous
128a0795c6fSMarcus Overhagen 
129a0795c6fSMarcus Overhagen status_t add_observer(
130a0795c6fSMarcus Overhagen 	const BMessenger&				observer,
131a0795c6fSMarcus Overhagen 	const BMessenger&				target,
132a0795c6fSMarcus Overhagen 	BMessage&								reply,
133a0795c6fSMarcus Overhagen 	bigtime_t								timeout =B_INFINITE_TIMEOUT);
134a0795c6fSMarcus Overhagen 
135a0795c6fSMarcus Overhagen status_t remove_observer(
136a0795c6fSMarcus Overhagen 	const BMessenger&				observer,
137a0795c6fSMarcus Overhagen 	const BMessenger&				target,
138a0795c6fSMarcus Overhagen 	BMessage&								reply,
139a0795c6fSMarcus Overhagen 	bigtime_t								timeout =B_INFINITE_TIMEOUT);
140a0795c6fSMarcus Overhagen 
141a0795c6fSMarcus Overhagen // -------------------------------------------------------- //
142a0795c6fSMarcus Overhagen // *** TOOL CLASSES ***
143a0795c6fSMarcus Overhagen // -------------------------------------------------------- //
144a0795c6fSMarcus Overhagen 
145a0795c6fSMarcus Overhagen template <class _observable_t>
146a0795c6fSMarcus Overhagen class observer_handle {
147a0795c6fSMarcus Overhagen 
148a0795c6fSMarcus Overhagen public:										// ctor/dtor
149a0795c6fSMarcus Overhagen 
~observer_handle()150a0795c6fSMarcus Overhagen 	virtual ~observer_handle() {}
151a0795c6fSMarcus Overhagen 
152a0795c6fSMarcus Overhagen 	observer_handle(
153a0795c6fSMarcus Overhagen 		const BMessenger&			observer,
154a0795c6fSMarcus Overhagen 		_observable_t*				target,
155a0795c6fSMarcus Overhagen 		bigtime_t							timeout =B_INFINITE_TIMEOUT) :
156a0795c6fSMarcus Overhagen 
_observer_messenger(observer)157a0795c6fSMarcus Overhagen 		_observer_messenger(observer),
158a0795c6fSMarcus Overhagen 		_target_messenger(target),
159a0795c6fSMarcus Overhagen 		_target_cache(target),
160a0795c6fSMarcus Overhagen 		_timeout(timeout),
161a0795c6fSMarcus Overhagen 		_valid(false) {
162a0795c6fSMarcus Overhagen 
163a0795c6fSMarcus Overhagen 		BMessage reply;
164a0795c6fSMarcus Overhagen 		status_t err = add_observer(
165a0795c6fSMarcus Overhagen 			_observer_messenger,
166a0795c6fSMarcus Overhagen 			_target_messenger,
167a0795c6fSMarcus Overhagen 			reply, timeout);
168a0795c6fSMarcus Overhagen 		if(err < B_OK) {
169a0795c6fSMarcus Overhagen 			PRINT((
170a0795c6fSMarcus Overhagen 				"! observer_handle<>(): add_observer() failed:\n"
171a0795c6fSMarcus Overhagen 				"  %s\n", strerror(err)));
172a0795c6fSMarcus Overhagen #if DEBUG
173a0795c6fSMarcus Overhagen 			PRINT((
174a0795c6fSMarcus Overhagen 				"  * target's reply:\n"));
175a0795c6fSMarcus Overhagen 			reply.PrintToStream();
176a0795c6fSMarcus Overhagen #endif
177a0795c6fSMarcus Overhagen 		}
178a0795c6fSMarcus Overhagen 		else _valid = true;
179a0795c6fSMarcus Overhagen 	}
180a0795c6fSMarcus Overhagen 
181a0795c6fSMarcus Overhagen public:										// interface
182a0795c6fSMarcus Overhagen 
release()183a0795c6fSMarcus Overhagen 	virtual void release() {
184a0795c6fSMarcus Overhagen 		if(!_valid) {
185a0795c6fSMarcus Overhagen 			PRINT((
186a0795c6fSMarcus Overhagen 				"! observer_handle<>::release(): invalid or already released.\n"));
187a0795c6fSMarcus Overhagen 			return;
188a0795c6fSMarcus Overhagen 		}
189a0795c6fSMarcus Overhagen 
190a0795c6fSMarcus Overhagen 		BMessage reply;
191a0795c6fSMarcus Overhagen 		status_t err = remove_observer(
192a0795c6fSMarcus Overhagen 			_observer_messenger,
193a0795c6fSMarcus Overhagen 			_target_messenger,
194a0795c6fSMarcus Overhagen 			reply,
19523e67806SIthamar R. Adema 			_timeout);
196a0795c6fSMarcus Overhagen 		if(err < B_OK) {
197a0795c6fSMarcus Overhagen 			PRINT((
198a0795c6fSMarcus Overhagen 				"! observer_handle<>::release(): remove_observer() failed:\n"
199a0795c6fSMarcus Overhagen 				"  %s\n", strerror(err)));
200a0795c6fSMarcus Overhagen #if DEBUG
201a0795c6fSMarcus Overhagen 			PRINT((
202a0795c6fSMarcus Overhagen 				"  * target's reply:\n"));
203a0795c6fSMarcus Overhagen 			reply.PrintToStream();
204a0795c6fSMarcus Overhagen #endif
205a0795c6fSMarcus Overhagen 		}
206a0795c6fSMarcus Overhagen 
207a0795c6fSMarcus Overhagen 		_valid = false;
208a0795c6fSMarcus Overhagen 	}
209a0795c6fSMarcus Overhagen 
210a0795c6fSMarcus Overhagen private:
211a0795c6fSMarcus Overhagen 	const BMessenger				_observer_messenger;
212a0795c6fSMarcus Overhagen 	BMessenger							_target_messenger;
213a0795c6fSMarcus Overhagen 	_observable_t*					_target_cache;
214a0795c6fSMarcus Overhagen 	bigtime_t								_timeout;
215a0795c6fSMarcus Overhagen 	bool										_valid;
216a0795c6fSMarcus Overhagen };
217a0795c6fSMarcus Overhagen 
218a0795c6fSMarcus Overhagen 
219a0795c6fSMarcus Overhagen __END_CORTEX_NAMESPACE
220a0795c6fSMarcus Overhagen #endif /*__Observe_H__*/
221