source: ThirdParty/CodePatterns/src/Observer/Notification.cpp

Candidate_v1.6.1
Last change on this file was 9ac3d3, checked in by Frederik Heber <frederik.heber@…>, 6 years ago

FIX: Constrained locking in CodePattern's Notification and Observable.

  • this is not a full soluton to possible race conditions with Qt's own threading but seems to help for the guichecks.
  • Property mode set to 100644
File size: 2.6 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * Notification.cpp
10 *
11 * Created on: Dec 1, 2011
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20//#include "CodePatterns/MemDebug.hpp"
21
22#include <boost/thread/locks.hpp>
23
24#include "CodePatterns/Observer/Notification.hpp"
25#include "CodePatterns/Observer/Observer.hpp"
26#include "CodePatterns/Observer/ObserverLog.hpp"
27
28Notification::Notification(size_t _channelno) :
29 channelno(_channelno)
30{}
31
32Notification::~Notification(){}
33
34void Notification::addObserver(Observer *target, const int priority)
35{
36 boost::recursive_mutex::scoped_lock guard(TargetsLock);
37 targets.insert( std::make_pair(priority, target) );
38}
39
40void Notification::removeObserver(Observer *target)
41{
42 boost::recursive_mutex::scoped_lock guard(TargetsLock);
43 for(targets_t::iterator iter=targets.begin();iter!=targets.end();) {
44 if((*iter).second == target) {
45 targets.erase(iter++);
46 } else {
47 ++iter;
48 }
49 }
50}
51
52void Notification::notifyAll(Observable * const publisher)
53{
54 targets_t temp_targets;
55 {
56 boost::recursive_mutex::scoped_lock guard(TargetsLock);
57 // copy such that signOff() within receiving update() does not affect iterating
58 // this is because within the same thread and with the update() signOff() may be
59 // called and when executed it modifies targets
60 temp_targets = targets;
61 }
62 for(targets_t::iterator it=temp_targets.begin();
63 it!=temp_targets.end();++it){
64#ifdef LOG_OBSERVER
65 observerLog().addMessage() << "-> Sending update from " << observerLog().getName(publisher)
66 << " for channel " << channelno
67 << " to " << observerLog().getName((*it).second);
68#endif
69 (*it).second->recieveNotification(publisher,this);
70 }
71}
72
73void Notification::subjectKilled(Observable * const publisher)
74{
75 boost::recursive_mutex::scoped_lock guard(TargetsLock);
76 // copy such that signOff() within receiving subjectKilled() does not affect iterating
77 // this is because within the same thread and with the subjectKilled() signOff() may be
78 // called and when executed it modifies targets
79 for(targets_t::iterator it=targets.begin();
80 !targets.empty();it=targets.begin()){
81 Observer *target = (*it).second;
82 const size_t prior_size = targets.size();
83 target->subjectKilled(publisher);
84 if (prior_size == targets.size())
85 targets.erase(it);
86 }
87}
Note: See TracBrowser for help on using the repository browser.