/home/coin/SVN-release/CoinAll-1.1.0/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 1019 2007-06-24 03:52:34Z 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     {
00060       NT_All,
00061       NT_BeingDestroyed,
00062       NT_Changed
00063     };
00064 
00065   protected:
00071     void RequestAttach(NotifyType notify_type, const Subject* subject);
00072 
00078     void RequestDetach(NotifyType notify_type, const Subject* subject);
00079 
00084     virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
00085 
00086   private:
00096     Observer(const Observer&);
00097 
00099     void operator=(const Observer&);
00101 
00104     std::vector<const Subject*> subjects_;
00105 
00112     void ProcessNotification(NotifyType notify_type, const Subject* subject);
00113 
00114     friend class Subject;
00115   };
00116 
00125   class Subject
00126   {
00127   public:
00128 #ifdef IP_DEBUG_OBSERVER
00129 
00130     static const Index dbg_verbosity;
00131 #endif
00132 
00136     Subject()
00137     {}
00138 
00140     virtual ~Subject();
00142 
00154 
00157     void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00158 
00161     void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00163 
00164   protected:
00165 
00166     void Notify(Observer::NotifyType notify_type) const;
00167 
00168   private:
00178     Subject(const Subject&);
00179 
00181     void operator=(const Subject&);
00183 
00184     mutable std::vector<Observer*> observers_;
00185 
00186   };
00187 
00188   /* inline methods */
00189   inline
00190   Observer::~Observer()
00191   {
00192 #ifdef IP_DEBUG_OBSERVER
00193     DBG_START_METH("Observer::~Observer", dbg_verbosity);
00194     if (DBG_VERBOSITY()>=1) {
00195       for (Index i=0; i<(Index)subjects_.size(); i++) {
00196         DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
00197       }
00198     }
00199 #endif
00200     // Detach all subjects
00201     for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
00202 #ifdef IP_DEBUG_OBSERVER
00203       DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
00204 #endif
00205 
00206       RequestDetach(NT_All, subjects_[i]);
00207     }
00208   }
00209 
00210   inline
00211   void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
00212   {
00213 #ifdef IP_DEBUG_OBSERVER
00214     DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
00215 
00216     // Add the subject to the list if it does not already exist
00217     std::vector<const Subject*>::iterator attached_subject;
00218     attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00219     DBG_ASSERT(attached_subject == subjects_.end());
00220     DBG_ASSERT(subject);
00221 #endif
00222 
00223     // add the subject to the list
00224     subjects_.push_back(subject);
00225     // Attach the observer to the subject
00226     subject->AttachObserver(notify_type, this);
00227   }
00228 
00229   inline
00230   void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
00231   {
00232 #ifdef IP_DEBUG_OBSERVER
00233     DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
00234     DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
00235     DBG_ASSERT(subject);
00236 #endif
00237 
00238     if (subject) {
00239       std::vector<const Subject*>::iterator attached_subject;
00240       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00241 #ifdef IP_DEBUG_OBSERVER
00242 
00243       DBG_ASSERT(attached_subject != subjects_.end());
00244 #endif
00245 
00246       if (attached_subject != subjects_.end()) {
00247 #ifdef IP_DEBUG_OBSERVER
00248         DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
00249 #endif
00250 
00251         subjects_.erase(attached_subject);
00252       }
00253 
00254       // Detach the observer from the subject
00255       subject->DetachObserver(notify_type, this);
00256     }
00257   }
00258 
00259   inline
00260   void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
00261   {
00262 #ifdef IP_DEBUG_OBSERVER
00263     DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
00264     DBG_ASSERT(subject);
00265 #endif
00266 
00267     if (subject) {
00268       std::vector<const Subject*>::iterator attached_subject;
00269       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00270 
00271       // We must be processing a notification for a
00272       // subject that was previously attached.
00273 #ifdef IP_DEBUG_OBSERVER
00274 
00275       DBG_ASSERT(attached_subject != subjects_.end());
00276 #endif
00277 
00278       this->RecieveNotification(notify_type, subject);
00279 
00280       if (notify_type == NT_BeingDestroyed) {
00281         // the subject is going away, remove it from our list
00282         subjects_.erase(attached_subject);
00283       }
00284     }
00285   }
00286 
00287   inline
00288   Subject::~Subject()
00289   {
00290 #ifdef IP_DEBUG_OBSERVER
00291     DBG_START_METH("Subject::~Subject", dbg_verbosity);
00292 #endif
00293 
00294     std::vector<Observer*>::iterator iter;
00295     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00296       (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
00297     }
00298   }
00299 
00300   inline
00301   void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
00302   {
00303 #ifdef IP_DEBUG_OBSERVER
00304     DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
00305     // current implementation notifies all observers of everything
00306     // they must filter the notifications that they are not interested
00307     // in (i.e. a hub, not a router)
00308     DBG_ASSERT(observer);
00309 
00310     std::vector<Observer*>::iterator attached_observer;
00311     attached_observer = std::find(observers_.begin(), observers_.end(), observer);
00312     DBG_ASSERT(attached_observer == observers_.end());
00313 
00314     DBG_ASSERT(observer);
00315 #endif
00316 
00317     observers_.push_back(observer);
00318   }
00319 
00320   inline
00321   void Subject::DetachObserver(Observer::NotifyType notify_type, Observer* observer) const
00322   {
00323 #ifdef IP_DEBUG_OBSERVER
00324     DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
00325     DBG_ASSERT(observer);
00326 #endif
00327 
00328     if (observer) {
00329       std::vector<Observer*>::iterator attached_observer;
00330       attached_observer = std::find(observers_.begin(), observers_.end(), observer);
00331 #ifdef IP_DEBUG_OBSERVER
00332 
00333       DBG_ASSERT(attached_observer != observers_.end());
00334 #endif
00335 
00336       if (attached_observer != observers_.end()) {
00337         observers_.erase(attached_observer);
00338       }
00339     }
00340   }
00341 
00342   inline
00343   void Subject::Notify(Observer::NotifyType notify_type) const
00344   {
00345 #ifdef IP_DEBUG_OBSERVER
00346     DBG_START_METH("Subject::Notify", dbg_verbosity);
00347 #endif
00348 
00349     std::vector<Observer*>::iterator iter;
00350     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00351       (*iter)->ProcessNotification(notify_type, this);
00352     }
00353   }
00354 
00355 
00356 } // namespace Ipopt
00357 
00358 #endif

Generated on Sun Nov 14 14:06:35 2010 for Coin-All by  doxygen 1.4.7