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 759 2006-07-07 03:07:08Z 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 "IpDebug.hpp"
00014 #include <vector>
00015 #include <algorithm>
00016 
00017 namespace Ipopt
00018 {
00020   class Subject;
00021 
00032   class Observer
00033   {
00034   public:
00035 #ifdef IP_DEBUG_OBSERVER
00036 
00037     static const Index dbg_verbosity;
00038 #endif
00039 
00043     Observer()
00044     {}
00045 
00047     virtual ~Observer();
00049 
00051     enum NotifyType {
00052       NT_All,
00053       NT_BeingDestroyed,
00054       NT_Changed
00055     };
00056 
00057   protected:
00063     void RequestAttach(NotifyType notify_type, const Subject* subject);
00064 
00070     void RequestDetach(NotifyType notify_type, const Subject* subject);
00071 
00076     virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
00077 
00078   private:
00088     Observer(const Observer&);
00089 
00091     void operator=(const Observer&);
00093 
00096     std::vector<const Subject*> subjects_;
00097 
00104     void ProcessNotification(NotifyType notify_type, const Subject* subject);
00105 
00106     friend class Subject;
00107   };
00108 
00117   class Subject
00118   {
00119   public:
00120 #ifdef IP_DEBUG_OBSERVER
00121 
00122     static const Index dbg_verbosity;
00123 #endif
00124 
00128     Subject()
00129     {}
00130     ;
00131 
00133     virtual ~Subject();
00135 
00147 
00150     void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00151 
00154     void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00156 
00157   protected:
00158 
00159     void Notify(Observer::NotifyType notify_type) const;
00160 
00161   private:
00171     Subject(const Subject&);
00172 
00174     void operator=(const Subject&);
00176 
00177     mutable std::vector<Observer*> observers_;
00178 
00179   };
00180 
00181   /* inline methods */
00182   inline
00183   Observer::~Observer()
00184   {
00185 #ifdef IP_DEBUG_OBSERVER
00186     DBG_START_METH("Observer::~Observer", dbg_verbosity);
00187     if (DBG_VERBOSITY()>=1) {
00188       for (Index i=0; i<(Index)subjects_.size(); i++) {
00189         DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
00190       }
00191     }
00192 #endif
00193     // Detach all subjects
00194     for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
00195 #ifdef IP_DEBUG_OBSERVER
00196       DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
00197 #endif
00198 
00199       RequestDetach(NT_All, subjects_[i]);
00200     }
00201   }
00202 
00203   inline
00204   void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
00205   {
00206 #ifdef IP_DEBUG_OBSERVER
00207     DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
00208 #endif
00209 
00210 #ifdef IP_DEBUG
00211     // Add the subject to the list if it does not already exist
00212     std::vector<const Subject*>::iterator attached_subject;
00213     attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00214     DBG_ASSERT(attached_subject == subjects_.end());
00215 #endif
00216 
00217     DBG_ASSERT(subject);
00218 
00219     // add the subject to the list
00220     subjects_.push_back(subject);
00221     // Attach the observer to the subject
00222     subject->AttachObserver(notify_type, this);
00223   }
00224 
00225   inline
00226   void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
00227   {
00228 #ifdef IP_DEBUG_OBSERVER
00229     DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
00230     DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
00231     DBG_ASSERT(subject);
00232 #endif
00233 
00234     if (subject) {
00235       std::vector<const Subject*>::iterator attached_subject;
00236       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00237 #ifdef IP_DEBUG_OBSERVER
00238 
00239       DBG_ASSERT(attached_subject != subjects_.end());
00240 #endif
00241 
00242       if (attached_subject != subjects_.end()) {
00243 #ifdef IP_DEBUG_OBSERVER
00244         DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
00245 #endif
00246 
00247         subjects_.erase(attached_subject);
00248       }
00249 
00250       // Detach the observer from the subject
00251       subject->DetachObserver(notify_type, this);
00252     }
00253   }
00254 
00255   inline
00256   void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
00257   {
00258 #ifdef IP_DEBUG_OBSERVER
00259     DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
00260     DBG_ASSERT(subject);
00261 #endif
00262 
00263     if (subject) {
00264       std::vector<const Subject*>::iterator attached_subject;
00265       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00266 
00267       // We must be processing a notification for a
00268       // subject that was previously attached.
00269 #ifdef IP_DEBUG_OBSERVER
00270 
00271       DBG_ASSERT(attached_subject != subjects_.end());
00272 #endif
00273 
00274       this->RecieveNotification(notify_type, subject);
00275 
00276       if (notify_type == NT_BeingDestroyed) {
00277         // the subject is going away, remove it from our list
00278         subjects_.erase(attached_subject);
00279       }
00280     }
00281   }
00282 
00283   inline
00284   Subject::~Subject()
00285   {
00286 #ifdef IP_DEBUG_OBSERVER
00287     DBG_START_METH("Subject::~Subject", dbg_verbosity);
00288 #endif
00289 
00290     std::vector<Observer*>::iterator iter;
00291     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00292       (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
00293     }
00294   }
00295 
00296   inline
00297   void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
00298   {
00299 #ifdef IP_DEBUG_OBSERVER
00300     DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
00301     // current implementation notifies all observers of everything
00302     // they must filter the notifications that they are not interested
00303     // in (i.e. a hub, not a router)
00304     DBG_ASSERT(observer);
00305 #endif
00306 
00307 
00308 #ifdef IP_DEBUG
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 #endif
00314 
00315     DBG_ASSERT(observer);
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 Fri Sep 26 07:44:12 2008 for SimTKcore by  doxygen 1.5.6