Ipopt Documentation  
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 // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
6 
7 #ifndef __IPOBSERVER_HPP__
8 #define __IPOBSERVER_HPP__
9 
10 #include "IpUtils.hpp"
11 #include <vector>
12 #include <algorithm>
13 
14 //#define IP_DEBUG_OBSERVER
15 #if IPOPT_CHECKLEVEL > 2
16 # define IP_DEBUG_OBSERVER
17 #endif
18 #ifdef IP_DEBUG_OBSERVER
19 # include "IpDebug.hpp"
20 #endif
21 
22 namespace Ipopt
23 {
24 /* Forward declaration */
25 class Subject;
26 
39 {
40 public:
41 #ifdef IP_DEBUG_OBSERVER
42  static const Index dbg_verbosity;
43 #endif
44 
47 
49  { }
50 
52  inline
53  virtual ~Observer();
55 
58  {
61  NT_Changed
62  };
63 
64 protected:
71  inline
72  void RequestAttach(
73  NotifyType notify_type,
74  const Subject* subject
75  );
76 
83  inline
84  void RequestDetach(
85  NotifyType notify_type,
86  const Subject* subject
87  );
88 
93  virtual void ReceiveNotification(
94  NotifyType notify_type,
95  const Subject* subject
96  ) = 0;
97 
98 private:
109 
111  const Observer&
112  );
113 
115  void operator=(
116  const Observer&
117  );
119 
121  std::vector<const Subject*> subjects_;
122 
131  inline
132  void ProcessNotification(
133  NotifyType notify_type,
134  const Subject* subject
135  );
136 
137  friend class Subject;
138 };
139 
150 {
151 public:
152 #ifdef IP_DEBUG_OBSERVER
153  static const Index dbg_verbosity;
154 #endif
155 
158 
160  { }
161 
163  inline
164  virtual ~Subject();
166 
180 
182  inline
183  void AttachObserver(
184  Observer::NotifyType notify_type,
185  Observer* observer
186  ) const;
187 
190  inline
191  void DetachObserver(
192  Observer::NotifyType notify_type,
193  Observer* observer
194  ) const;
196 
197 protected:
198 
199  inline
200  void Notify(
201  Observer::NotifyType notify_type
202  ) const;
203 
204 private:
215 
217  const Subject&
218  );
219 
221  void operator=(
222  const Subject&
223  );
225 
226  mutable std::vector<Observer*> observers_;
227 };
228 
229 /* inline methods */
231 {
232 #ifdef IP_DEBUG_OBSERVER
233  DBG_START_METH("Observer::~Observer", dbg_verbosity);
234  if (DBG_VERBOSITY() >= 1)
235  {
236  for( size_t i = 0; i < subjects_.size(); ++i )
237  {
238  DBG_PRINT((1, "subjects_[%zd] = %p\n", i, (const void*)subjects_[i]));
239  }
240  }
241 #endif
242  // Detach all subjects
243  for( size_t i = subjects_.size(); i > 0; --i )
244  {
245 #ifdef IP_DEBUG_OBSERVER
246  DBG_PRINT((1, "About to detach subjects_[%zd] = %p\n", i, (const void*)subjects_[i - 1]));
247 #endif
248 
249  RequestDetach(NT_All, subjects_[i - 1]);
250  }
251 }
252 
253 inline
255  NotifyType notify_type,
256  const Subject* subject
257 )
258 {
259 #ifdef IP_DEBUG_OBSERVER
260  DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
261 
262  // Add the subject to the list if it does not already exist
263  std::vector<const Subject*>::iterator attached_subject;
264  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
265  DBG_ASSERT(attached_subject == subjects_.end());
266  DBG_ASSERT(subject);
267 #endif
268 
269  // add the subject to the list
270  subjects_.push_back(subject);
271  // Attach the observer to the subject
272  subject->AttachObserver(notify_type, this);
273 }
274 
275 inline
277  NotifyType notify_type,
278  const Subject* subject
279 )
280 {
281 #ifdef IP_DEBUG_OBSERVER
282  DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
283  DBG_PRINT((1, "Requesting detach of subject: %p\n", (const void*)subject));
284  DBG_ASSERT(subject);
285 #endif
286 
287  if( subject )
288  {
289  std::vector<const Subject*>::iterator attached_subject;
290  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
291 #ifdef IP_DEBUG_OBSERVER
292 
293  DBG_ASSERT(attached_subject != subjects_.end());
294 #endif
295 
296  if( attached_subject != subjects_.end() )
297  {
298 #ifdef IP_DEBUG_OBSERVER
299  DBG_PRINT((1, "Removing subject: %p from the list\n", (const void*)subject));
300 #endif
301 
302  subjects_.erase(attached_subject);
303  }
304 
305  // Detach the observer from the subject
306  subject->DetachObserver(notify_type, this);
307  }
308 }
309 
310 inline
312  NotifyType notify_type,
313  const Subject* subject
314 )
315 {
316 #ifdef IP_DEBUG_OBSERVER
317  DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
318  DBG_ASSERT(subject);
319 #endif
320 
321  if( subject )
322  {
323  std::vector<const Subject*>::iterator attached_subject;
324  attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
325 
326  // We must be processing a notification for a
327  // subject that was previously attached.
328 #ifdef IP_DEBUG_OBSERVER
329 
330  DBG_ASSERT(attached_subject != subjects_.end());
331 #endif
332 
333  this->ReceiveNotification(notify_type, subject);
334 
335  if( notify_type == NT_BeingDestroyed )
336  {
337  // the subject is going away, remove it from our list
338  subjects_.erase(attached_subject);
339  }
340  }
341 }
342 
344 {
345 #ifdef IP_DEBUG_OBSERVER
346  DBG_START_METH("Subject::~Subject", dbg_verbosity);
347 #endif
348 
349  for( std::vector<Observer*>::iterator iter = observers_.begin(); iter != observers_.end(); ++iter )
350  {
351  (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
352  }
353 }
354 
355 inline
357  Observer::NotifyType /*notify_type*/,
358  Observer* observer
359 ) const
360 {
361 #ifdef IP_DEBUG_OBSERVER
362  DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
363  // current implementation notifies all observers of everything
364  // they must filter the notifications that they are not interested
365  // in (i.e. a hub, not a router)
366  DBG_ASSERT(observer);
367 
368  std::vector<Observer*>::iterator attached_observer;
369  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
370  DBG_ASSERT(attached_observer == observers_.end());
371 
372  DBG_ASSERT(observer);
373 #endif
374 
375  observers_.push_back(observer);
376 }
377 
378 inline
380  Observer::NotifyType /*notify_type*/,
381  Observer* observer
382 ) const
383 {
384 #ifdef IP_DEBUG_OBSERVER
385  DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
386  DBG_ASSERT(observer);
387 #endif
388 
389  if( observer )
390  {
391  std::vector<Observer*>::iterator attached_observer;
392  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
393 #ifdef IP_DEBUG_OBSERVER
394 
395  DBG_ASSERT(attached_observer != observers_.end());
396 #endif
397 
398  if( attached_observer != observers_.end() )
399  {
400  observers_.erase(attached_observer);
401  }
402  }
403 }
404 
405 inline
407  Observer::NotifyType notify_type
408 ) const
409 {
410 #ifdef IP_DEBUG_OBSERVER
411  DBG_START_METH("Subject::Notify", dbg_verbosity);
412 #endif
413 
414  for( std::vector<Observer*>::iterator iter = observers_.begin(); iter != observers_.end(); ++iter )
415  {
416  (*iter)->ProcessNotification(notify_type, this);
417  }
418 }
419 
420 } // namespace Ipopt
421 
422 #endif
#define DBG_ASSERT(test)
Definition: IpDebug.hpp:27
#define DBG_PRINT(__printf_args)
Definition: IpDebug.hpp:39
#define DBG_VERBOSITY()
Definition: IpDebug.hpp:43
#define DBG_START_METH(__func_name, __verbose_level)
Definition: IpDebug.hpp:38
Slight Variation of the Observer Design Pattern.
Definition: IpObserver.hpp:39
void ProcessNotification(NotifyType notify_type, const Subject *subject)
Private Method for Receiving Notification should only be called by the friend class Subject.
Definition: IpObserver.hpp:311
virtual void ReceiveNotification(NotifyType notify_type, const Subject *subject)=0
Derived classes should overload this method to receive the requested notification from attached Subje...
virtual ~Observer()
Destructor.
Definition: IpObserver.hpp:230
void RequestDetach(NotifyType notify_type, const Subject *subject)
Derived classes should call this method to request a "Detach" to a Subject.
Definition: IpObserver.hpp:276
void operator=(const Observer &)
Default Assignment Operator.
NotifyType
Enumeration specifying the type of notification.
Definition: IpObserver.hpp:58
std::vector< const Subject * > subjects_
A list of the subjects currently being observed.
Definition: IpObserver.hpp:121
Observer()
Default Constructor.
Definition: IpObserver.hpp:48
void RequestAttach(NotifyType notify_type, const Subject *subject)
Derived classes should call this method to request an "Attach" to a Subject.
Definition: IpObserver.hpp:254
Observer(const Observer &)
Copy Constructor.
Slight Variation of the Observer Design Pattern (Subject part).
Definition: IpObserver.hpp:150
void Notify(Observer::NotifyType notify_type) const
Definition: IpObserver.hpp:406
Subject(const Subject &)
Copy Constructor.
Subject()
Default Constructor.
Definition: IpObserver.hpp:159
void AttachObserver(Observer::NotifyType notify_type, Observer *observer) const
Attach the specified observer (i.e., begin receiving notifications).
Definition: IpObserver.hpp:356
void DetachObserver(Observer::NotifyType notify_type, Observer *observer) const
Detach the specified observer (i.e., no longer receive notifications).
Definition: IpObserver.hpp:379
virtual ~Subject()
Destructor.
Definition: IpObserver.hpp:343
std::vector< Observer * > observers_
Definition: IpObserver.hpp:226
void operator=(const Subject &)
Default Assignment Operator.
#define IPOPTLIB_EXPORT
Definition: config.h:94
This file contains a base class for all exceptions and a set of macros to help with exceptions.
ipindex Index
Type of all indices of vectors, matrices etc.
Definition: IpTypes.hpp:20