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 COIN_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 
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:
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 
160  { }
161 
163  inline
164  virtual ~Subject();
166 
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:
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 (Index i = 0; i < (Index)subjects_.size(); i++)
237  {
238  DBG_PRINT((1, "subjects_[%d] = 0x%x\n", i, subjects_[i]));
239  }
240  }
241 #endif
242  // Detach all subjects
243  for( Int i = (Int) (subjects_.size() - 1); i >= 0; i-- )
244  {
245 #ifdef IP_DEBUG_OBSERVER
246  DBG_PRINT((1, "About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
247 #endif
248 
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: 0x%x\n", 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: 0x%x from the list\n", 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  std::vector<Observer*>::iterator iter;
350  for( iter = observers_.begin(); iter != observers_.end(); iter++ )
351  {
352  (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
353  }
354 }
355 
356 inline
358  Observer::NotifyType /*notify_type*/,
359  Observer* observer
360 ) const
361 {
362 #ifdef IP_DEBUG_OBSERVER
363  DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
364  // current implementation notifies all observers of everything
365  // they must filter the notifications that they are not interested
366  // in (i.e. a hub, not a router)
367  DBG_ASSERT(observer);
368 
369  std::vector<Observer*>::iterator attached_observer;
370  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
371  DBG_ASSERT(attached_observer == observers_.end());
372 
373  DBG_ASSERT(observer);
374 #endif
375 
376  observers_.push_back(observer);
377 }
378 
379 inline
381  Observer::NotifyType /*notify_type*/,
382  Observer* observer
383 ) const
384 {
385 #ifdef IP_DEBUG_OBSERVER
386  DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
387  DBG_ASSERT(observer);
388 #endif
389 
390  if( observer )
391  {
392  std::vector<Observer*>::iterator attached_observer;
393  attached_observer = std::find(observers_.begin(), observers_.end(), observer);
394 #ifdef IP_DEBUG_OBSERVER
395 
396  DBG_ASSERT(attached_observer != observers_.end());
397 #endif
398 
399  if( attached_observer != observers_.end() )
400  {
401  observers_.erase(attached_observer);
402  }
403  }
404 }
405 
406 inline
408  Observer::NotifyType notify_type
409 ) const
410 {
411 #ifdef IP_DEBUG_OBSERVER
412  DBG_START_METH("Subject::Notify", dbg_verbosity);
413 #endif
414 
415  std::vector<Observer*>::iterator iter;
416  for( iter = observers_.begin(); iter != observers_.end(); iter++ )
417  {
418  (*iter)->ProcessNotification(notify_type, this);
419  }
420 }
421 
422 } // namespace Ipopt
423 
424 #endif
IpUtils.hpp
DBG_PRINT
#define DBG_PRINT(__printf_args)
Definition: IpDebug.hpp:40
Ipopt::Observer::RequestDetach
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
Ipopt::Observer::subjects_
std::vector< const Subject * > subjects_
A list of the subjects currently being observed.
Definition: IpObserver.hpp:121
Ipopt
This file contains a base class for all exceptions and a set of macros to help with exceptions.
Definition: IpInexactAlgBuilder.hpp:14
Ipopt::Subject::DetachObserver
void DetachObserver(Observer::NotifyType notify_type, Observer *observer) const
Detach the specified observer (i.e., no longer receive notifications).
Definition: IpObserver.hpp:380
Ipopt::Observer
Slight Variation of the Observer Design Pattern.
Definition: IpObserver.hpp:39
IPOPTLIB_EXPORT
#define IPOPTLIB_EXPORT
Definition: config_default.h:16
Ipopt::Observer::RequestAttach
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
Ipopt::Observer::~Observer
virtual ~Observer()
Destructor.
Definition: IpObserver.hpp:230
Ipopt::Index
int Index
Type of all indices of vectors, matrices etc.
Definition: IpTypes.hpp:17
DBG_START_METH
#define DBG_START_METH(__func_name, __verbose_level)
Definition: IpDebug.hpp:39
Ipopt::Observer::ReceiveNotification
virtual void ReceiveNotification(NotifyType notify_type, const Subject *subject)=0
Derived classes should overload this method to receive the requested notification from attached Subje...
Ipopt::Subject::Subject
Subject(const Subject &)
Copy Constructor.
Ipopt::Subject::~Subject
virtual ~Subject()
Destructor.
Definition: IpObserver.hpp:343
DBG_VERBOSITY
#define DBG_VERBOSITY()
Definition: IpDebug.hpp:44
Ipopt::Subject::Notify
void Notify(Observer::NotifyType notify_type) const
Definition: IpObserver.hpp:407
Ipopt::Subject::operator=
void operator=(const Subject &)
Default Assignment Operator.
Ipopt::Subject
Slight Variation of the Observer Design Pattern (Subject part).
Definition: IpObserver.hpp:150
Ipopt::Subject::observers_
std::vector< Observer * > observers_
Definition: IpObserver.hpp:226
Ipopt::Observer::NT_BeingDestroyed
@ NT_BeingDestroyed
Definition: IpObserver.hpp:60
Ipopt::Observer::NotifyType
NotifyType
Enumeration specifying the type of notification.
Definition: IpObserver.hpp:58
Ipopt::Observer::Observer
Observer()
Default Constructor.
Definition: IpObserver.hpp:48
Ipopt::Subject::AttachObserver
void AttachObserver(Observer::NotifyType notify_type, Observer *observer) const
Attach the specified observer (i.e., begin receiving notifications).
Definition: IpObserver.hpp:357
Ipopt::Observer::ProcessNotification
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
Ipopt::Subject::Subject
Subject()
Default Constructor.
Definition: IpObserver.hpp:159
DBG_ASSERT
#define DBG_ASSERT(test)
Definition: IpDebug.hpp:28
Ipopt::Observer::operator=
void operator=(const Observer &)
Default Assignment Operator.
Ipopt::Int
int Int
Type of default integer.
Definition: IpTypes.hpp:19
IpDebug.hpp
Ipopt::Observer::Observer
Observer(const Observer &)
Copy Constructor.
Ipopt::Observer::NT_All
@ NT_All
Definition: IpObserver.hpp:59