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