source: src/Patterns/Observer/Relay.cpp@ e2e035e

Last change on this file since e2e035e was e2e035e, checked in by Frederik Heber <heber@…>, 14 years ago

Refactored all Observer stuff into own subfolder and split up into distinct modules.

  • Observer/all.hpp is all that's needed.
  • Property mode set to 100644
File size: 4.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 * Relay.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 "MemDebug.hpp"
21
22#include "Observer/Relay.hpp"
23
24
25/** Constructor for class Relay.
26 */
27Relay::Relay(string name) :
28 Observer(Observer::BaseConstructor())
29{
30#ifdef LOG_OBSERVER
31 observerLog().addName(this,name);
32 observerLog().addMessage() << "++ Creating Relay " << observerLog().getName(this) << endl;
33#endif
34}
35
36/** Destructor for class Relay.
37 * When an observable is deleted, we let all our observers know. \sa Relay::subjectKilled().
38 */
39Relay::~Relay()
40{
41#ifdef LOG_OBSERVER
42 observerLog().addMessage() << "-- Destroying Relay " << observerLog().getName(this) << endl;
43#endif
44 if(callTable.count(this)) {
45 // delete all entries for this observable
46 callees_t callees = callTable[this];
47 callees_t::iterator iter;
48 for(iter=callees.begin();iter!=callees.end();++iter){
49 (*iter).second->subjectKilled(this);
50 }
51 callTable.erase(this);
52 }
53}
54
55
56/** Notify all Observers of changes.
57 * Puts \a *this into Relay::busyRelays, calls Observer::update() for all in callee_t
58 * and removes from busy list.
59 */
60void Relay::notifyAll() {
61 // we are busy notifying others right now
62 // add ourselves to the list of busy subjects to enable circle detection
63 busyRelays.insert(this);
64 // see if anyone has signed up for observation
65 // and call all observers
66 try {
67 if(callTable.count(this)) {
68 // elements are stored sorted by keys in the multimap
69 // so iterating over it gives us a the callees sorted by
70 // the priorities
71 callees_t callees = callTable[this];
72 callees_t::iterator iter;
73 for(iter=callees.begin();iter!=callees.end();++iter){
74#ifdef LOG_OBSERVER
75 observerLog().addMessage() << "-> " << observerLog().getName(this)
76 << " is relaying update from " << observerLog().getName(Updater)
77 << " to " << observerLog().getName((*iter).second)
78 << " (priority=" << (*iter).first << ")"<< endl;
79#endif
80 (*iter).second->update(Updater);
81 }
82 }
83 }
84 ASSERT_NOCATCH("Exception thrown from Observer Update");
85
86 // send out all notifications that need to be done
87
88 notificationSet currentNotifications = notifications[this];
89 for(notificationSet::iterator it = currentNotifications.begin();
90 it != currentNotifications.end();++it){
91 (*it)->notifyAll();
92 }
93
94 notifications.erase(this);
95
96 // done with notification, we can leave the set of busy subjects
97 busyRelays.erase(this);
98}
99
100
101/** Handles passing on updates from sub-Relays.
102 * Mimicks basically the Observer::update() function.
103 *
104 * \param *publisher The \a *this we observe.
105 */
106void Relay::update(Observable *publisher) {
107 // circle detection
108 if(busyRelays.find(this)!=busyRelays.end()) {
109 // somehow a circle was introduced... we were busy notifying our
110 // observers, but still we are called by one of our sub-Relays
111 // we cannot be sure observation will still work at this point
112 ASSERT(0,"Circle detected in observation-graph.\n"
113 "Observation-graph always needs to be a DAG to work correctly!\n"
114 "Please check your observation code and fix this!\n");
115 return;
116 }
117 else {
118 // see if we are in the process of changing ourselves
119 // if we are changing ourselves at the same time our sub-observables change
120 // we do not need to publish all the changes at each time we are called
121 if(depth.find(this)==depth.end()) {
122#ifdef LOG_OBSERVER
123 observerLog().addMessage() << "-* Update from " << observerLog().getName(publisher)
124 << " relayed by " << observerLog().getName(this) << endl;
125#endif
126 Updater = publisher;
127 notifyAll();
128 }
129 else{
130#ifdef LOG_OBSERVER
131 observerLog().addMessage() << "-| Update from " << observerLog().getName(publisher)
132 << " not relayed by " << observerLog().getName(this) << endl;
133#endif
134 }
135 }
136}
137
138//Notification_ptr Relay::getChannel(size_t no) const
139//{
140// ASSERT(NotificationChannels != NULL,
141// "Relay::getChannel() - observable has no channels.");
142// return NotificationChannels->getChannel(no);
143//}
144
145/** Handles sub-observables that just got killed
146 * when an sub-observerable dies we usually don't need to do anything
147 * \param *publisher Sub-Relay.
148 */
149void Relay::subjectKilled(Observable *publisher){
150}
151
Note: See TracBrowser for help on using the repository browser.