/home/coin/SVN-release/Ipopt-3.3.1/Ipopt/src/Common/IpObserver.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2004, 2006 International Business Machines and others.
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // $Id: IpObserver.hpp 1010 2007-06-21 15:54:36Z andreasw $
00006 //
00007 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
00008 
00009 #ifndef __IPOBSERVER_HPP__
00010 #define __IPOBSERVER_HPP__
00011 
00012 #include "IpUtils.hpp"
00013 #include <vector>
00014 #include <algorithm>
00015 
00016 //#define IP_DEBUG_OBSERVER
00017 #if COIN_IPOPT_CHECKLEVEL > 2
00018 # define IP_DEBUG_OBSERVER
00019 #endif
00020 #ifdef IP_DEBUG_OBSERVER
00021 # include "IpDebug.hpp"
00022 #endif
00023 
00024 namespace Ipopt
00025 {
00027   class Subject;
00028 
00039   class Observer
00040   {
00041   public:
00042 #ifdef IP_DEBUG_OBSERVER
00043 
00044     static const Index dbg_verbosity;
00045 #endif
00046 
00050     Observer()
00051     {}
00052 
00054     virtual ~Observer();
00056 
00058     enum NotifyType {
00059       NT_All,
00060       NT_BeingDestroyed,
00061       NT_Changed
00062     };
00063 
00064   protected:
00070     void RequestAttach(NotifyType notify_type, const Subject* subject);
00071 
00077     void RequestDetach(NotifyType notify_type, const Subject* subject);
00078 
00083     virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
00084 
00085   private:
00095     Observer(const Observer&);
00096 
00098     void operator=(const Observer&);
00100 
00103     std::vector<const Subject*> subjects_;
00104 
00111     void ProcessNotification(NotifyType notify_type, const Subject* subject);
00112 
00113     friend class Subject;
00114   };
00115 
00124   class Subject
00125   {
00126   public:
00127 #ifdef IP_DEBUG_OBSERVER
00128 
00129     static const Index dbg_verbosity;
00130 #endif
00131 
00135     Subject()
00136     {}
00137 
00139     virtual ~Subject();
00141 
00153 
00156     void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00157 
00160     void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00162 
00163   protected:
00164 
00165     void Notify(Observer::NotifyType notify_type) const;
00166 
00167   private:
00177     Subject(const Subject&);
00178 
00180     void operator=(const Subject&);
00182 
00183     mutable std::vector<Observer*> observers_;
00184 
00185   };
00186 
00187   /* inline methods */
00188   inline
00189   Observer::~Observer()
00190   {
00191 #ifdef IP_DEBUG_OBSERVER
00192     DBG_START_METH("Observer::~Observer", dbg_verbosity);
00193     if (DBG_VERBOSITY()>=1) {
00194       for (Index i=0; i<(Index)subjects_.size(); i++) {
00195         DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
00196       }
00197     }
00198 #endif
00199     // Detach all subjects
00200     for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
00201 #ifdef IP_DEBUG_OBSERVER
00202       DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
00203 #endif
00204 
00205       RequestDetach(NT_All, subjects_[i]);
00206     }
00207   }
00208 
00209   inline
00210   void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
00211   {
00212 #ifdef IP_DEBUG_OBSERVER
00213     DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
00214 
00215     // Add the subject to the list if it does not already exist
00216     std::vector<const Subject*>::iterator attached_subject;
00217     attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00218     DBG_ASSERT(attached_subject == subjects_.end());
00219     DBG_ASSERT(subject);
00220 #endif
00221 
00222     // add the subject to the list
00223     subjects_.push_back(subject);
00224     // Attach the observer to the subject
00225     subject->AttachObserver(notify_type, this);
00226   }
00227 
00228   inline
00229   void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
00230   {
00231 #ifdef IP_DEBUG_OBSERVER
00232     DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
00233     DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
00234     DBG_ASSERT(subject);
00235 #endif
00236 
00237     if (subject) {
00238       std::vector<const Subject*>::iterator attached_subject;
00239       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00240 #ifdef IP_DEBUG_OBSERVER
00241 
00242       DBG_ASSERT(attached_subject != subjects_.end());
00243 #endif
00244 
00245       if (attached_subject != subjects_.end()) {
00246 #ifdef IP_DEBUG_OBSERVER
00247         DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
00248 #endif
00249 
00250         subjects_.erase(attached_subject);
00251       }
00252 
00253       // Detach the observer from the subject
00254       subject->DetachObserver(notify_type, this);
00255     }
00256   }
00257 
00258   inline
00259   void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
00260   {
00261 #ifdef IP_DEBUG_OBSERVER
00262     DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
00263     DBG_ASSERT(subject);
00264 #endif
00265 
00266     if (subject) {
00267       std::vector<const Subject*>::iterator attached_subject;
00268       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00269 
00270       // We must be processing a notification for a
00271       // subject that was previously attached.
00272 #ifdef IP_DEBUG_OBSERVER
00273 
00274       DBG_ASSERT(attached_subject != subjects_.end());
00275 #endif
00276 
00277       this->RecieveNotification(notify_type, subject);
00278 
00279       if (notify_type == NT_BeingDestroyed) {
00280         // the subject is going away, remove it from our list
00281         subjects_.erase(attached_subject);
00282       }
00283     }
00284   }
00285 
00286   inline
00287   Subject::~Subject()
00288   {
00289 #ifdef IP_DEBUG_OBSERVER
00290     DBG_START_METH("Subject::~Subject", dbg_verbosity);
00291 #endif
00292 
00293     std::vector<Observer*>::iterator iter;
00294     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00295       (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
00296     }
00297   }
00298 
00299   inline
00300   void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
00301   {
00302 #ifdef IP_DEBUG_OBSERVER
00303     DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
00304     // current implementation notifies all observers of everything
00305     // they must filter the notifications that they are not interested
00306     // in (i.e. a hub, not a router)
00307     DBG_ASSERT(observer);
00308 
00309     std::vector<Observer*>::iterator attached_observer;
00310     attached_observer = std::find(observers_.begin(), observers_.end(), observer);
00311     DBG_ASSERT(attached_observer == observers_.end());
00312 
00313     DBG_ASSERT(observer);
00314 #endif
00315 
00316     observers_.push_back(observer);
00317   }
00318 
00319   inline
00320   void Subject::DetachObserver(Observer::NotifyType notify_type, Observer* observer) const
00321   {
00322 #ifdef IP_DEBUG_OBSERVER
00323     DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
00324     DBG_ASSERT(observer);
00325 #endif
00326 
00327     if (observer) {
00328       std::vector<Observer*>::iterator attached_observer;
00329       attached_observer = std::find(observers_.begin(), observers_.end(), observer);
00330 #ifdef IP_DEBUG_OBSERVER
00331 
00332       DBG_ASSERT(attached_observer != observers_.end());
00333 #endif
00334 
00335       if (attached_observer != observers_.end()) {
00336         observers_.erase(attached_observer);
00337       }
00338     }
00339   }
00340 
00341   inline
00342   void Subject::Notify(Observer::NotifyType notify_type) const
00343   {
00344 #ifdef IP_DEBUG_OBSERVER
00345     DBG_START_METH("Subject::Notify", dbg_verbosity);
00346 #endif
00347 
00348     std::vector<Observer*>::iterator iter;
00349     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00350       (*iter)->ProcessNotification(notify_type, this);
00351     }
00352   }
00353 
00354 
00355 } // namespace Ipopt
00356 
00357 #endif

Generated on Thu May 15 22:25:43 2008 by  doxygen 1.4.7