- Timestamp:
- Jul 30, 2015, 8:47:36 PM (10 years ago)
- Children:
- 454bc54
- Parents:
- 163eec
- git-author:
- Frederik Heber <heber@…> (06/18/15 00:02:38)
- git-committer:
- Frederik Heber <heber@…> (07/30/15 20:47:36)
- Location:
- src
- Files:
-
- 2 edited
-
CodePatterns/Observer/Observable.hpp (modified) (2 diffs)
-
Observer/Observable.cpp (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/CodePatterns/Observer/Observable.hpp
r163eec r1b5188 18 18 #include <string> 19 19 #include <boost/function.hpp> 20 #include <boost/thread.hpp> 20 21 21 22 #include "CodePatterns/Range.hpp" … … 135 136 static std::set<Observable*> busyObservables; 136 137 138 static boost::recursive_mutex ObservablesMapLock; //!< a lock for the pointer of the instance 139 137 140 private: 138 141 friend class Zombie; -
src/Observer/Observable.cpp
r163eec r1b5188 46 46 std::set<Observable*> Observable::busyObservables; //!< Set of Observables that are currently busy notifying their sign-on'ed Observers 47 47 Observable::ChannelMap Observable::NotificationChannels; //!< Map of Observables to their Channels. 48 boost::recursive_mutex Observable::ObservablesMapLock; //!< mutex for locking the above maps 48 49 49 50 // ValidRange must be initialized before PriorityLevel. … … 77 78 * \param *publisher reference of sub-observable 78 79 */ 79 void Observable::start_observer_internal(Observable *publisher){ 80 void Observable::start_observer_internal(Observable *publisher) 81 { 82 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 80 83 // increase the count for this observable by one 81 84 // if no entry for this observable is found, an new one is created … … 97 100 * \param *publisher reference of sub-observable 98 101 */ 99 void Observable::finish_observer_internal(Observable *publisher){ 102 void Observable::finish_observer_internal(Observable *publisher) 103 { 100 104 // decrease the count for this observable 101 105 // if zero is reached all observed blocks are done and we can 102 106 // start to notify our observers 107 ObservablesMapLock.lock(); 103 108 --depth[publisher]; 109 ObservablesMapLock.unlock(); 104 110 #ifdef LOG_OBSERVER 105 111 observerLog().addMessage(depth[publisher]) << "<< Unlocking " << observerLog().getName(publisher); 106 112 #endif 107 if(depth[publisher]){} 113 ObservablesMapLock.lock(); 114 int depth_publisher = depth[publisher]; 115 ObservablesMapLock.unlock(); 116 if(depth_publisher){} 108 117 else{ 109 118 publisher->notifyAll(); 110 119 // this item is done, so we don't have to keep the count with us 111 120 // save some memory by erasing it 121 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 112 122 depth.erase(publisher); 113 123 } 114 124 } 115 125 116 void Observable::enque_notification_internal(Observable *publisher, Notification_ptr notification){ 126 void Observable::enque_notification_internal(Observable *publisher, Notification_ptr notification) 127 { 128 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 117 129 notifications[publisher].insert(notification); 118 130 } … … 160 172 // we are busy notifying others right now 161 173 // add ourselves to the list of busy subjects to enable circle detection 174 ObservablesMapLock.lock(); 162 175 busyObservables.insert(this); 176 ObservablesMapLock.unlock(); 163 177 // see if anyone has signed up for observation 164 178 // and call all observers 165 179 try { 166 if(callTable.count(this)) { 180 ObservablesMapLock.lock(); 181 const bool anybodyThere = callTable.count(this); 182 ObservablesMapLock.unlock(); 183 if(anybodyThere) { 167 184 // elements are stored sorted by keys in the multimap 168 185 // so iterating over it gives us a the callees sorted by 169 186 // the priorities 187 ObservablesMapLock.lock(); 170 188 callees_t callees = callTable[this]; 189 ObservablesMapLock.unlock(); 171 190 callees_t::iterator iter; 172 191 for(iter=callees.begin();iter!=callees.end();++iter){ … … 190 209 } 191 210 211 ObservablesMapLock.lock(); 192 212 notifications.erase(this); 193 213 194 214 // done with notification, we can leave the set of busy subjects 195 215 busyObservables.erase(this); 216 ObservablesMapLock.unlock(); 196 217 197 218 #ifdef LOG_OBSERVER … … 209 230 void Observable::update(Observable *publisher) { 210 231 // circle detection 211 if(busyObservables.find(this)!=busyObservables.end()) { 232 ObservablesMapLock.lock(); 233 const bool presentCircle = busyObservables.find(this)!=busyObservables.end(); 234 ObservablesMapLock.unlock(); 235 if(presentCircle) { 212 236 // somehow a circle was introduced... we were busy notifying our 213 237 // observers, but still we are called by one of our sub-Observables … … 222 246 // if we are changing ourselves at the same time our sub-observables change 223 247 // we do not need to publish all the changes at each time we are called 224 if(depth.find(this)==depth.end()) { 248 ObservablesMapLock.lock(); 249 const bool depth_this = depth.find(this)==depth.end(); 250 ObservablesMapLock.unlock(); 251 if(depth_this) { 225 252 #ifdef LOG_OBSERVER 226 253 observerLog().addMessage() << "-* Update from " << observerLog().getName(publisher) … … 249 276 #endif 250 277 bool res = false; 278 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 251 279 callees_t &callees = callTable[const_cast<Observable *>(this)]; 252 280 … … 265 293 void Observable::signOff(Observer *target) const 266 294 { 295 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 267 296 ASSERT(callTable.count(const_cast<Observable *>(this)), 268 297 "SignOff called for an Observable without Observers."); … … 290 319 void Observable::signOn(Observer *target, size_t channelno) const 291 320 { 321 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 292 322 Notification_ptr notification = getChannel(channelno); 293 323 #ifdef LOG_OBSERVER … … 301 331 void Observable::signOff(Observer *target, size_t channelno) const 302 332 { 333 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 303 334 Notification_ptr notification = getChannel(channelno); 304 335 #ifdef LOG_OBSERVER … … 313 344 bool Observable::isBlocked() const 314 345 { 346 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 315 347 return depth.count(const_cast<Observable *>(this)) > 0; 316 348 } … … 318 350 Notification_ptr Observable::getChannel(size_t no) const 319 351 { 352 ObservablesMapLock.lock(); 320 353 const ChannelMap::const_iterator iter = NotificationChannels.find(const_cast<Observable * const>(this)); 321 ASSERT(iter != NotificationChannels.end(), 354 const bool status = iter != NotificationChannels.end(); 355 Channels *OurChannel = NULL; 356 if (status) 357 OurChannel = iter->second; 358 ObservablesMapLock.unlock(); 359 ASSERT(status, 322 360 "Observable::getChannel() - we do not have a channel in NotificationChannels."); 323 const Channels *OurChannel = iter->second;324 361 ASSERT(OurChannel != NULL, 325 362 "Observable::getChannel() - observable has no channels."); … … 329 366 size_t Observable::getNumberOfObservers() const 330 367 { 368 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 331 369 size_t ObserverCount = 0; 332 370 { … … 354 392 * \param *publisher Sub-Observable. 355 393 */ 356 void Observable::subjectKilled(Observable *publisher){ 394 void Observable::subjectKilled(Observable *publisher) 395 { 357 396 } 358 397 … … 379 418 << observerLog().getName(static_cast<Observable *>(this)); 380 419 #endif 420 boost::recursive_mutex::scoped_lock guard(ObservablesMapLock); 381 421 if(callTable.count(this)) { 382 422 // delete all entries for this observable 423 ObservablesMapLock.lock(); 383 424 callees_t callees = callTable[this]; 425 ObservablesMapLock.unlock(); 384 426 callees_t::iterator iter; 385 427 for(iter=callees.begin();iter!=callees.end();++iter) 386 428 (*iter).second->subjectKilled(this); 429 ObservablesMapLock.lock(); 387 430 callTable.erase(this); 431 ObservablesMapLock.unlock(); 388 432 } 389 433 … … 392 436 if (iter != NotificationChannels.end()) { 393 437 iter->second->subjectKilled(static_cast<Observable *>(this)); 438 ObservablesMapLock.lock(); 394 439 delete iter->second; 395 440 NotificationChannels.erase(iter); 396 } 397 } 441 ObservablesMapLock.unlock(); 442 } 443 }
Note:
See TracChangeset
for help on using the changeset viewer.
