- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# /home/coin/SVN-release/Ipopt-3.7.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 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