Ipopt  3.12.12
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
IpObserver.hpp
Go to the documentation of this file.
1 // Copyright (C) 2004, 2006 International Business Machines and others.
2 // All Rights Reserved.
3 // This code is published under the Eclipse Public License.
4 //
5 // $Id: IpObserver.hpp 2161 2013-01-01 20:39:05Z stefan $
6 //
7 // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
8 
9 #ifndef __IPOBSERVER_HPP__
10 #define __IPOBSERVER_HPP__
11 
12 #include "IpUtils.hpp"
13 #include <vector>
14 #include <algorithm>
15 
16 //#define IP_DEBUG_OBSERVER
17 #if COIN_IPOPT_CHECKLEVEL > 2
18 # define IP_DEBUG_OBSERVER
19 #endif
20 #ifdef IP_DEBUG_OBSERVER
21 # include "IpDebug.hpp"
22 #endif
23 
24 namespace Ipopt
25 {
27  class Subject;
28 
39  class Observer
40  {
41  public:
42 #ifdef IP_DEBUG_OBSERVER
43 
44  static const Index dbg_verbosity;
45 #endif
46 
51  {}
52 
54  inline
55  virtual ~Observer();
57 
60  {
64  };
65 
66  protected:
72  inline
73  void RequestAttach(NotifyType notify_type, const Subject* subject);
74 
80  inline
81  void RequestDetach(NotifyType notify_type, const Subject* subject);
82 
87  virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
88 
89  private:
99  Observer(const Observer&);
100 
102  void operator=(const Observer&);
104 
107  std::vector<const Subject*> subjects_;
108 
115  inline
116  void ProcessNotification(NotifyType notify_type, const Subject* subject);
117 
118  friend class Subject;
119  };
120 
129  class Subject
130  {
131  public:
132 #ifdef IP_DEBUG_OBSERVER
133 
134  static const Index dbg_verbosity;
135 #endif
136 
141  {}
142 
144  inline
145  virtual ~Subject();
147 
159 
162  inline
163  void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
164 
167  inline
168  void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
170 
171  protected:
172 
173  inline
174  void Notify(Observer::NotifyType notify_type) const;
175 
176  private:
186  Subject(const Subject&);
187 
189  void operator=(const Subject&);
191 
192  mutable std::vector<Observer*> observers_;
193 
194  };
195 
196  /* inline methods */
197  inline
199  {
200 #ifdef IP_DEBUG_OBSERVER
201  DBG_START_METH("Observer::~Observer", dbg_verbosity);
202  if (DBG_VERBOSITY()>=1) {
203  for (Index i=0; i<(Index)subjects_.size(); i++) {
204  DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
205  }
206  }
207 #endif
208  // Detach all subjects
209  for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
210 #ifdef IP_DEBUG_OBSERVER
211  DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
212 #endif
213 
215  }
216  }
217 
218  inline
219  void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
220  {
221 #ifdef IP_DEBUG_OBSERVER
222  DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
223 
224  // Add the subject to the list if it does not already exist
225  std::vector<const Subject*>::iterator attached_subject;
226  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
227  DBG_ASSERT(attached_subject == subjects_.end());
228  DBG_ASSERT(subject);
229 #endif
230 
231  // add the subject to the list
232  subjects_.push_back(subject);
233  // Attach the observer to the subject
234  subject->AttachObserver(notify_type, this);
235  }
236 
237  inline
238  void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
239  {
240 #ifdef IP_DEBUG_OBSERVER
241  DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
242  DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
243  DBG_ASSERT(subject);
244 #endif
245 
246  if (subject) {
247  std::vector<const Subject*>::iterator attached_subject;
248  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
249 #ifdef IP_DEBUG_OBSERVER
250 
251  DBG_ASSERT(attached_subject != subjects_.end());
252 #endif
253 
254  if (attached_subject != subjects_.end()) {
255 #ifdef IP_DEBUG_OBSERVER
256  DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
257 #endif
258 
259  subjects_.erase(attached_subject);
260  }
261 
262  // Detach the observer from the subject
263  subject->DetachObserver(notify_type, this);
264  }
265  }
266 
267  inline
268  void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
269  {
270 #ifdef IP_DEBUG_OBSERVER
271  DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
272  DBG_ASSERT(subject);
273 #endif
274 
275  if (subject) {
276  std::vector<const Subject*>::iterator attached_subject;
277  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
278 
279  // We must be processing a notification for a
280  // subject that was previously attached.
281 #ifdef IP_DEBUG_OBSERVER
282 
283  DBG_ASSERT(attached_subject != subjects_.end());
284 #endif
285 
286  this->RecieveNotification(notify_type, subject);
287 
288  if (notify_type == NT_BeingDestroyed) {
289  // the subject is going away, remove it from our list
290  subjects_.erase(attached_subject);
291  }
292  }
293  }
294 
295  inline
297  {
298 #ifdef IP_DEBUG_OBSERVER
299  DBG_START_METH("Subject::~Subject", dbg_verbosity);
300 #endif
301 
302  std::vector<Observer*>::iterator iter;
303  for (iter = observers_.begin(); iter != observers_.end(); iter++) {
304  (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
305  }
306  }
307 
308  inline
309  void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
310  {
311 #ifdef IP_DEBUG_OBSERVER
312  DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
313  // current implementation notifies all observers of everything
314  // they must filter the notifications that they are not interested
315  // in (i.e. a hub, not a router)
316  DBG_ASSERT(observer);
317 
318  std::vector<Observer*>::iterator attached_observer;
319  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
320  DBG_ASSERT(attached_observer == observers_.end());
321 
322  DBG_ASSERT(observer);
323 #endif
324 
325  observers_.push_back(observer);
326  }
327 
328  inline
329  void Subject::DetachObserver(Observer::NotifyType notify_type, Observer* observer) const
330  {
331 #ifdef IP_DEBUG_OBSERVER
332  DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
333  DBG_ASSERT(observer);
334 #endif
335 
336  if (observer) {
337  std::vector<Observer*>::iterator attached_observer;
338  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
339 #ifdef IP_DEBUG_OBSERVER
340 
341  DBG_ASSERT(attached_observer != observers_.end());
342 #endif
343 
344  if (attached_observer != observers_.end()) {
345  observers_.erase(attached_observer);
346  }
347  }
348  }
349 
350  inline
351  void Subject::Notify(Observer::NotifyType notify_type) const
352  {
353 #ifdef IP_DEBUG_OBSERVER
354  DBG_START_METH("Subject::Notify", dbg_verbosity);
355 #endif
356 
357  std::vector<Observer*>::iterator iter;
358  for (iter = observers_.begin(); iter != observers_.end(); iter++) {
359  (*iter)->ProcessNotification(notify_type, this);
360  }
361  }
362 
363 
364 } // namespace Ipopt
365 
366 #endif
void DetachObserver(Observer::NotifyType notify_type, Observer *observer) const
Detach the specified observer (i.e., no longer recieve notifications).
Definition: IpObserver.hpp:329
void operator=(const Observer &)
Overloaded Equals Operator.
std::vector< Observer * > observers_
Definition: IpObserver.hpp:192
NotifyType
Enumeration specifying the type of notification.
Definition: IpObserver.hpp:59
void operator=(const Subject &)
Overloaded Equals Operator.
int Int
Type of default integer.
Definition: IpTypes.hpp:21
void Notify(Observer::NotifyType notify_type) const
Definition: IpObserver.hpp:351
#define DBG_START_METH(__func_name, __verbose_level)
Definition: IpDebug.hpp:49
void RequestAttach(NotifyType notify_type, const Subject *subject)
Derived classes should call this method to request an &quot;Attach&quot; to a Subject.
Definition: IpObserver.hpp:219
virtual ~Observer()
Default destructor.
Definition: IpObserver.hpp:198
virtual ~Subject()
Default destructor.
Definition: IpObserver.hpp:296
Slight Variation of the Observer Design Pattern (Subject part).
Definition: IpObserver.hpp:129
void AttachObserver(Observer::NotifyType notify_type, Observer *observer) const
Attach the specified observer (i.e., begin recieving notifications).
Definition: IpObserver.hpp:309
Slight Variation of the Observer Design Pattern.
Definition: IpObserver.hpp:39
Subject()
Default Constructor.
Definition: IpObserver.hpp:140
void ProcessNotification(NotifyType notify_type, const Subject *subject)
Private Method for Recieving Notification should only be called by the friend class Subject...
Definition: IpObserver.hpp:268
int Index
Type of all indices of vectors, matrices etc.
Definition: IpTypes.hpp:19
#define DBG_ASSERT(test)
Definition: IpDebug.hpp:38
Observer()
Default Constructor.
Definition: IpObserver.hpp:50
#define DBG_PRINT(__printf_args)
Definition: IpDebug.hpp:50
void RequestDetach(NotifyType notify_type, const Subject *subject)
Derived classes should call this method to request a &quot;Detach&quot; to a Subject.
Definition: IpObserver.hpp:238
virtual void RecieveNotification(NotifyType notify_type, const Subject *subject)=0
Derived classes should overload this method to recieve the requested notification from attached Subje...
std::vector< const Subject * > subjects_
A list of the subjects currently being observed.
Definition: IpObserver.hpp:107
#define DBG_VERBOSITY()
Definition: IpDebug.hpp:54