- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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