1/*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer.
11 *
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.
15 *
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.
18 *
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.
29 */
30
31
32// Observe.h (cortex)
33// * PURPOSE
34//   Messages used for implementation of the Observer pattern.
35//
36// * HISTORY
37//   e.moon		19aug99		Begun
38
39#ifndef __Observe_H__
40#define __Observe_H__
41
42#include <Messenger.h>
43#include <Debug.h>
44#include <string.h>
45
46#include "cortex_defs.h"
47__BEGIN_CORTEX_NAMESPACE
48
49// -------------------------------------------------------- //
50// *** MESSAGES ***
51// -------------------------------------------------------- //
52
53// messages sent to the Observable (source)
54enum observer_message_t {
55	// Requests that an observer be added to a given
56	// observable (target).
57	// - "observer" (BMessenger)
58	M_ADD_OBSERVER							= Observer_message_base,
59
60	// Requests that a given observable (target) stop
61	// sending notifications to a given observer.
62	// Should be sent in response to M_RELEASE_OBSERVABLE
63	// in order to allow the observable object to be deleted.
64	// - "observer" (BMessenger)
65	M_REMOVE_OBSERVER,
66
67	// Requests that an observable quit immediately without
68	// waiting for its observers to acknowledge that they're done.
69	// This should only be posted to an Observable in an
70	// emergency
71	M_KILL_OBSERVABLE
72};
73
74
75// messages sent by the Observable (target)
76enum target_message_t {
77	// sent when the target is no longer needed; the
78	// observer should reply with M_REMOVE_OBSERVER in order
79	// to release (allow the deletion of) the target
80	// - "target" (BMessenger)
81	M_RELEASE_OBSERVABLE				= Observable_message_base,
82
83	// SUGGESTED BUT NOT REQUIRED FOR IObservable IMPLEMENTATION:
84	// *** IObservables are encouraged to send other replies!
85	// sent upon successful receipt of M_ADD_OBSERVER
86	// - "target" (BMessenger)
87	M_OBSERVER_ADDED,
88
89	// SUGGESTED BUT NOT REQUIRED FOR IObservable IMPLEMENTATION:
90	// *** IObservables are encouraged to send other replies!
91	// sent upon successful receipt of M_REMOVE_OBSERVER
92	// - "target" (BMessenger)
93	M_OBSERVER_REMOVED,
94
95	// sent when no matching observer was found for an
96	// M_REMOVE_OBSERVER message, or if the observer specified
97	// in an M_ADD_OBSERVER message was previously added.
98	// - "target" (BMessenger)
99	// - "observer" (BMessenger)
100	M_BAD_OBSERVER,
101
102	// sent when the target receiving an M_ADD_OBSERVER
103	// or M_REMOVE_OBSERVER didn't match the target described
104	// in the message.  also sent if the target is currently
105	// in the process of quitting (it's already sent M_RELEASE_OBSERVABLE
106	// to its current observers, and is waiting for them to acknowledge
107	// with M_REMOVE_OBSERVER so that it can delete itself.)
108	// - "target" (BMessenger)
109	// - "observer" (BMessenger)
110	M_BAD_TARGET
111};
112
113// -------------------------------------------------------- //
114// *** FUNCTIONS ***
115// -------------------------------------------------------- //
116
117// * Asynchronous
118
119status_t add_observer(
120	const BMessenger&				observer,
121	const BMessenger&				target);
122
123status_t remove_observer(
124	const BMessenger&				observer,
125	const BMessenger&				target);
126
127// * Synchronous
128
129status_t add_observer(
130	const BMessenger&				observer,
131	const BMessenger&				target,
132	BMessage&								reply,
133	bigtime_t								timeout =B_INFINITE_TIMEOUT);
134
135status_t remove_observer(
136	const BMessenger&				observer,
137	const BMessenger&				target,
138	BMessage&								reply,
139	bigtime_t								timeout =B_INFINITE_TIMEOUT);
140
141// -------------------------------------------------------- //
142// *** TOOL CLASSES ***
143// -------------------------------------------------------- //
144
145template <class _observable_t>
146class observer_handle {
147
148public:										// ctor/dtor
149
150	virtual ~observer_handle() {}
151
152	observer_handle(
153		const BMessenger&			observer,
154		_observable_t*				target,
155		bigtime_t							timeout =B_INFINITE_TIMEOUT) :
156
157		_observer_messenger(observer),
158		_target_messenger(target),
159		_target_cache(target),
160		_timeout(timeout),
161		_valid(false) {
162
163		BMessage reply;
164		status_t err = add_observer(
165			_observer_messenger,
166			_target_messenger,
167			reply, timeout);
168		if(err < B_OK) {
169			PRINT((
170				"! observer_handle<>(): add_observer() failed:\n"
171				"  %s\n", strerror(err)));
172#if DEBUG
173			PRINT((
174				"  * target's reply:\n"));
175			reply.PrintToStream();
176#endif
177		}
178		else _valid = true;
179	}
180
181public:										// interface
182
183	virtual void release() {
184		if(!_valid) {
185			PRINT((
186				"! observer_handle<>::release(): invalid or already released.\n"));
187			return;
188		}
189
190		BMessage reply;
191		status_t err = remove_observer(
192			_observer_messenger,
193			_target_messenger,
194			reply,
195			_timeout);
196		if(err < B_OK) {
197			PRINT((
198				"! observer_handle<>::release(): remove_observer() failed:\n"
199				"  %s\n", strerror(err)));
200#if DEBUG
201			PRINT((
202				"  * target's reply:\n"));
203			reply.PrintToStream();
204#endif
205		}
206
207		_valid = false;
208	}
209
210private:
211	const BMessenger				_observer_messenger;
212	BMessenger							_target_messenger;
213	_observable_t*					_target_cache;
214	bigtime_t								_timeout;
215	bool										_valid;
216};
217
218
219__END_CORTEX_NAMESPACE
220#endif /*__Observe_H__*/
221