xref: /haiku/src/apps/cortex/support/observe.h (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
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)
54 enum 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)
76 enum 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 
119 status_t add_observer(
120 	const BMessenger&				observer,
121 	const BMessenger&				target);
122 
123 status_t remove_observer(
124 	const BMessenger&				observer,
125 	const BMessenger&				target);
126 
127 // * Synchronous
128 
129 status_t add_observer(
130 	const BMessenger&				observer,
131 	const BMessenger&				target,
132 	BMessage&								reply,
133 	bigtime_t								timeout =B_INFINITE_TIMEOUT);
134 
135 status_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 
145 template <class _observable_t>
146 class observer_handle {
147 
148 public:										// 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 
181 public:										// 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 
210 private:
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