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 1861 2010-12-21 21:34:47Z andreasw $
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  virtual ~Observer();
56 
59  {
63  };
64 
65  protected:
71  void RequestAttach(NotifyType notify_type, const Subject* subject);
72 
78  void RequestDetach(NotifyType notify_type, const Subject* subject);
79 
84  virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
85 
86  private:
96  Observer(const Observer&);
97 
99  void operator=(const Observer&);
101 
104  std::vector<const Subject*> subjects_;
105 
112  void ProcessNotification(NotifyType notify_type, const Subject* subject);
113 
114  friend class Subject;
115  };
116 
125  class Subject
126  {
127  public:
128 #ifdef IP_DEBUG_OBSERVER
129 
130  static const Index dbg_verbosity;
131 #endif
132 
137  {}
138 
140  virtual ~Subject();
142 
154 
157  void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
158 
161  void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
163 
164  protected:
165 
166  void Notify(Observer::NotifyType notify_type) const;
167 
168  private:
178  Subject(const Subject&);
179 
181  void operator=(const Subject&);
183 
184  mutable std::vector<Observer*> observers_;
185 
186  };
187 
188  /* inline methods */
189  inline
191  {
192 #ifdef IP_DEBUG_OBSERVER
193  DBG_START_METH("Observer::~Observer", dbg_verbosity);
194  if (DBG_VERBOSITY()>=1) {
195  for (Index i=0; i<(Index)subjects_.size(); i++) {
196  DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
197  }
198  }
199 #endif
200  // Detach all subjects
201  for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
202 #ifdef IP_DEBUG_OBSERVER
203  DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
204 #endif
205 
207  }
208  }
209 
210  inline
211  void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
212  {
213 #ifdef IP_DEBUG_OBSERVER
214  DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
215 
216  // Add the subject to the list if it does not already exist
217  std::vector<const Subject*>::iterator attached_subject;
218  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
219  DBG_ASSERT(attached_subject == subjects_.end());
220  DBG_ASSERT(subject);
221 #endif
222 
223  // add the subject to the list
224  subjects_.push_back(subject);
225  // Attach the observer to the subject
226  subject->AttachObserver(notify_type, this);
227  }
228 
229  inline
230  void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
231  {
232 #ifdef IP_DEBUG_OBSERVER
233  DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
234  DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
235  DBG_ASSERT(subject);
236 #endif
237 
238  if (subject) {
239  std::vector<const Subject*>::iterator attached_subject;
240  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
241 #ifdef IP_DEBUG_OBSERVER
242 
243  DBG_ASSERT(attached_subject != subjects_.end());
244 #endif
245 
246  if (attached_subject != subjects_.end()) {
247 #ifdef IP_DEBUG_OBSERVER
248  DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
249 #endif
250 
251  subjects_.erase(attached_subject);
252  }
253 
254  // Detach the observer from the subject
255  subject->DetachObserver(notify_type, this);
256  }
257  }
258 
259  inline
260  void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
261  {
262 #ifdef IP_DEBUG_OBSERVER
263  DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
264  DBG_ASSERT(subject);
265 #endif
266 
267  if (subject) {
268  std::vector<const Subject*>::iterator attached_subject;
269  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
270 
271  // We must be processing a notification for a
272  // subject that was previously attached.
273 #ifdef IP_DEBUG_OBSERVER
274 
275  DBG_ASSERT(attached_subject != subjects_.end());
276 #endif
277 
278  this->RecieveNotification(notify_type, subject);
279 
280  if (notify_type == NT_BeingDestroyed) {
281  // the subject is going away, remove it from our list
282  subjects_.erase(attached_subject);
283  }
284  }
285  }
286 
287  inline
289  {
290 #ifdef IP_DEBUG_OBSERVER
291  DBG_START_METH("Subject::~Subject", dbg_verbosity);
292 #endif
293 
294  std::vector<Observer*>::iterator iter;
295  for (iter = observers_.begin(); iter != observers_.end(); iter++) {
296  (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
297  }
298  }
299 
300  inline
301  void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
302  {
303 #ifdef IP_DEBUG_OBSERVER
304  DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
305  // current implementation notifies all observers of everything
306  // they must filter the notifications that they are not interested
307  // in (i.e. a hub, not a router)
308  DBG_ASSERT(observer);
309 
310  std::vector<Observer*>::iterator attached_observer;
311  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
312  DBG_ASSERT(attached_observer == observers_.end());
313 
314  DBG_ASSERT(observer);
315 #endif
316 
317  observers_.push_back(observer);
318  }
319 
320  inline
321  void Subject::DetachObserver(Observer::NotifyType notify_type, Observer* observer) const
322  {
323 #ifdef IP_DEBUG_OBSERVER
324  DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
325  DBG_ASSERT(observer);
326 #endif
327 
328  if (observer) {
329  std::vector<Observer*>::iterator attached_observer;
330  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
331 #ifdef IP_DEBUG_OBSERVER
332 
333  DBG_ASSERT(attached_observer != observers_.end());
334 #endif
335 
336  if (attached_observer != observers_.end()) {
337  observers_.erase(attached_observer);
338  }
339  }
340  }
341 
342  inline
343  void Subject::Notify(Observer::NotifyType notify_type) const
344  {
345 #ifdef IP_DEBUG_OBSERVER
346  DBG_START_METH("Subject::Notify", dbg_verbosity);
347 #endif
348 
349  std::vector<Observer*>::iterator iter;
350  for (iter = observers_.begin(); iter != observers_.end(); iter++) {
351  (*iter)->ProcessNotification(notify_type, this);
352  }
353  }
354 
355 
356 } // namespace Ipopt
357 
358 #endif