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