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

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

Added unit test on Relay.

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