1 // ObservableHandler.cpp 2 3 #include "ObservableHandler.h" 4 5 #include <Debug.h> 6 #include <Looper.h> 7 8 __USE_CORTEX_NAMESPACE 9 10 // ---------------------------------------------------------------- // 11 // *** deletion 12 // ---------------------------------------------------------------- // 13 14 // clients must call release() rather than deleting, 15 // to ensure that all observers are notified of the 16 // object's demise. if the object has already been 17 // released, return an error. 18 19 status_t ObservableHandler::release() { 20 if(m_released) 21 return B_NOT_ALLOWED; 22 23 // PRINT(( 24 // "ObservableHandler::release(): %ld targets\n", CountTargets())); 25 26 if(!LockLooper()) { 27 ASSERT(!"failed to lock looper"); 28 } 29 30 m_released = true; 31 32 if(CountTargets()) { 33 // notify 34 notifyRelease(); 35 UnlockLooper(); 36 } 37 else { 38 releaseComplete(); 39 UnlockLooper(); 40 delete this; 41 } 42 43 return B_OK; 44 } 45 46 // ---------------------------------------------------------------- // 47 // *** ctor/dtor 48 // ---------------------------------------------------------------- // 49 50 ObservableHandler::~ObservableHandler() { 51 if(CountTargets()) { 52 PRINT(( 53 "*** ~ObservableHandler() '%s': %ld observers remain\n", 54 Name(), CountTargets())); 55 } 56 } 57 58 ObservableHandler::ObservableHandler( 59 const char* name) : 60 BHandler(name), 61 m_released(false) {} 62 63 ObservableHandler::ObservableHandler( 64 BMessage* archive) : 65 BHandler(archive), 66 m_released(false) {} 67 68 // ---------------------------------------------------------------- // 69 // *** accessors 70 // ---------------------------------------------------------------- // 71 72 // return true if release() has been called, false otherwise. 73 bool ObservableHandler::isReleased() const { 74 return m_released; 75 } 76 77 // ---------------------------------------------------------------- // 78 // *** hooks 79 // ---------------------------------------------------------------- // 80 81 // sends M_OBSERVER_ADDED to the newly-added observer 82 void ObservableHandler::observerAdded( 83 const BMessenger& observer) { 84 85 BMessage m(M_OBSERVER_ADDED); 86 m.AddMessenger("target", BMessenger(this)); 87 observer.SendMessage(&m); 88 } 89 90 // sends M_OBSERVER_REMOVED to the newly-removed observer 91 void ObservableHandler::observerRemoved( 92 const BMessenger& observer) { 93 94 BMessage m(M_OBSERVER_REMOVED); 95 m.AddMessenger("target", BMessenger(this)); 96 observer.SendMessage(&m); 97 } 98 99 // ---------------------------------------------------------------- // 100 // *** internal operations 101 // ---------------------------------------------------------------- // 102 103 // call to send the given message to all observers. 104 // Responsibility for deletion of the message remains with 105 // the caller. 106 107 status_t ObservableHandler::notify( 108 BMessage* message) { 109 #if DEBUG 110 BLooper* l = Looper(); 111 ASSERT(l); 112 ASSERT(l->IsLocked()); 113 #endif 114 115 return Invoke(message); 116 } 117 118 // sends M_RELEASE_OBSERVABLE 119 void ObservableHandler::notifyRelease() { 120 BMessage m(M_RELEASE_OBSERVABLE); 121 m.AddMessenger("target", BMessenger(this)); 122 notify(&m); 123 } 124 125 // ---------------------------------------------------------------- // 126 // *** BHandler 127 // ---------------------------------------------------------------- // 128 129 void ObservableHandler::MessageReceived( 130 BMessage* message) { 131 132 // PRINT(( 133 // "### ObservableHandler::MessageReceived()\n")); 134 // message->PrintToStream(); 135 136 switch(message->what) { 137 case M_ADD_OBSERVER: 138 _handleAddObserver(message); 139 break; 140 141 case M_REMOVE_OBSERVER: 142 _handleRemoveObserver(message); 143 break; 144 145 case M_KILL_OBSERVABLE: 146 // +++++ this should be an optional feature 147 releaseComplete(); 148 delete this; // BOOM! 149 break; 150 151 default: 152 _inherited::MessageReceived(message); 153 } 154 } 155 156 // ---------------------------------------------------------------- // 157 // *** BArchivable 158 // ---------------------------------------------------------------- // 159 160 status_t ObservableHandler::Archive( 161 BMessage* archive, 162 bool deep) const { 163 164 #if DEBUG 165 BLooper* l = Looper(); 166 ASSERT(l); 167 ASSERT(l->IsLocked()); 168 #endif 169 if(m_released) 170 return B_NOT_ALLOWED; // can't archive a dead object 171 172 return _inherited::Archive(archive, deep); 173 } 174 175 // ---------------------------------------------------------------- // 176 // implementation 177 // ---------------------------------------------------------------- // 178 179 void ObservableHandler::_handleAddObserver( 180 BMessage* message) { 181 182 #if DEBUG 183 BLooper* l = Looper(); 184 ASSERT(l); 185 ASSERT(l->IsLocked()); 186 #endif 187 BMessage reply; 188 189 BMessenger observer; 190 status_t err = message->FindMessenger( 191 "observer", &observer); 192 if(err < B_OK) { 193 PRINT(( 194 "* ObservableHandler::_handleAddObserver(): no observer specified!\n")); 195 // send reply? +++++ 196 return; 197 } 198 199 if(m_released) { 200 // already quitting 201 reply.what = M_BAD_TARGET; 202 reply.AddMessenger("target", BMessenger(this)); 203 reply.AddMessenger("observer", observer); 204 message->SendReply(&reply); 205 206 return; 207 } 208 else if(IndexOfTarget(observer.Target(0)) != -1) { 209 // observer already added 210 reply.what = M_BAD_OBSERVER; 211 reply.AddMessenger("target", BMessenger(this)); 212 reply.AddMessenger("observer", observer); 213 message->SendReply(&reply); 214 215 return; 216 } 217 218 // valid observer given 219 220 // add it 221 err = AddTarget(observer.Target(0)); 222 ASSERT(err == B_OK); 223 224 // call hook 225 observerAdded(observer); 226 } 227 228 void ObservableHandler::_handleRemoveObserver( 229 BMessage* message) { 230 231 #if DEBUG 232 BLooper* l = Looper(); 233 ASSERT(l); 234 ASSERT(l->IsLocked()); 235 #endif 236 BMessage reply; 237 238 BMessenger observer; 239 status_t err = message->FindMessenger( 240 "observer", &observer); 241 if(err < B_OK) { 242 PRINT(( 243 "* ObservableHandler::_handleRemoveObserver(): no observer specified!\n")); 244 // send reply? +++++ 245 return; 246 } 247 248 int32 index = IndexOfTarget(observer.Target(0)); 249 if(index == -1) { 250 reply.what = M_BAD_OBSERVER; 251 252 reply.AddMessenger("target", BMessenger(this)); 253 reply.AddMessenger("observer", observer); 254 message->SendReply(&reply); 255 return; 256 } 257 258 // valid observer given; remove it & call notification hook 259 RemoveTarget(index); 260 observerRemoved(observer); 261 262 // time to shut down? 263 if(m_released && !CountTargets()) { 264 releaseComplete(); 265 delete this; // BOOM! 266 } 267 } 268 269 270 // END -- ObservableHandler.cpp --