- Main Page
- Classes
- Files

- File List
- File Members

# 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 Eclipse Public License.
    00004 //
    00005 // $Id: IpObserver.hpp 2161 2013-01-01 20:39:05Z stefan $
    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     inline
    00055     virtual ~Observer();
    00057
    00059     enum NotifyType
    00060     {
    00061       NT_All,
    00062       NT_BeingDestroyed,
    00063       NT_Changed
    00064     };
    00065
    00066   protected:
    00072     inline
    00073     void RequestAttach(NotifyType notify_type, const Subject* subject);
    00074
    00080     inline
    00081     void RequestDetach(NotifyType notify_type, const Subject* subject);
    00082
    00087     virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
    00088
    00089   private:
    00099     Observer(const Observer&);
    00100
    00102     void operator=(const Observer&);
    00104
    00107     std::vector<const Subject*> subjects_;
    00108
    00115     inline
    00116     void ProcessNotification(NotifyType notify_type, const Subject* subject);
    00117
    00118     friend class Subject;
    00119   };
    00120
    00129   class Subject
    00130   {
    00131   public:
    00132 #ifdef IP_DEBUG_OBSERVER
    00133
    00134     static const Index dbg_verbosity;
    00135 #endif
    00136
    00140     Subject()
    00141     {}
    00142
    00144     inline
    00145     virtual ~Subject();
    00147
    00159
    00162     inline
    00163     void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
    00164
    00167     inline
    00168     void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
    00170
    00171   protected:
    00172
    00173     inline
    00174     void Notify(Observer::NotifyType notify_type) const;
    00175
    00176   private:
    00186     Subject(const Subject&);
    00187
    00189     void operator=(const Subject&);
    00191
    00192     mutable std::vector<Observer*> observers_;
    00193
    00194   };
    00195
    00196   /* inline methods */
    00197   inline
    00198   Observer::~Observer()
    00199   {
    00200 #ifdef IP_DEBUG_OBSERVER
    00201     DBG_START_METH("Observer::~Observer", dbg_verbosity);
    00202     if (DBG_VERBOSITY()>=1) {
    00203       for (Index i=0; i<(Index)subjects_.size(); i++) {
    00204         DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
    00205       }
    00206     }
    00207 #endif
    00208     // Detach all subjects
    00209     for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
    00210 #ifdef IP_DEBUG_OBSERVER
    00211       DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
    00212 #endif
    00213
    00214       RequestDetach(NT_All, subjects_[i]);
    00215     }
    00216   }
    00217
    00218   inline
    00219   void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
    00220   {
    00221 #ifdef IP_DEBUG_OBSERVER
    00222     DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
    00223
    00224     // Add the subject to the list if it does not already exist
    00225     std::vector<const Subject*>::iterator attached_subject;
    00226     attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
    00227     DBG_ASSERT(attached_subject == subjects_.end());
    00228     DBG_ASSERT(subject);
    00229 #endif
    00230
    00231     // add the subject to the list
    00232     subjects_.push_back(subject);
    00233     // Attach the observer to the subject
    00234     subject->AttachObserver(notify_type, this);
    00235   }
    00236
    00237   inline
    00238   void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
    00239   {
    00240 #ifdef IP_DEBUG_OBSERVER
    00241     DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
    00242     DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
    00243     DBG_ASSERT(subject);
    00244 #endif
    00245
    00246     if (subject) {
    00247       std::vector<const Subject*>::iterator attached_subject;
    00248       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
    00249 #ifdef IP_DEBUG_OBSERVER
    00250
    00251       DBG_ASSERT(attached_subject != subjects_.end());
    00252 #endif
    00253
    00254       if (attached_subject != subjects_.end()) {
    00255 #ifdef IP_DEBUG_OBSERVER
    00256         DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
    00257 #endif
    00258
    00259         subjects_.erase(attached_subject);
    00260       }
    00261
    00262       // Detach the observer from the subject
    00263       subject->DetachObserver(notify_type, this);
    00264     }
    00265   }
    00266
    00267   inline
    00268   void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
    00269   {
    00270 #ifdef IP_DEBUG_OBSERVER
    00271     DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
    00272     DBG_ASSERT(subject);
    00273 #endif
    00274
    00275     if (subject) {
    00276       std::vector<const Subject*>::iterator attached_subject;
    00277       attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
    00278
    00279       // We must be processing a notification for a
    00280       // subject that was previously attached.
    00281 #ifdef IP_DEBUG_OBSERVER
    00282
    00283       DBG_ASSERT(attached_subject != subjects_.end());
    00284 #endif
    00285
    00286       this->RecieveNotification(notify_type, subject);
    00287
    00288       if (notify_type == NT_BeingDestroyed) {
    00289         // the subject is going away, remove it from our list
    00290         subjects_.erase(attached_subject);
    00291       }
    00292     }
    00293   }
    00294
    00295   inline
    00296   Subject::~Subject()
    00297   {
    00298 #ifdef IP_DEBUG_OBSERVER
    00299     DBG_START_METH("Subject::~Subject", dbg_verbosity);
    00300 #endif
    00301
    00302     std::vector<Observer*>::iterator iter;
    00303     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
    00304       (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
    00305     }
    00306   }
    00307
    00308   inline
    00309   void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
    00310   {
    00311 #ifdef IP_DEBUG_OBSERVER
    00312     DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
    00313     // current implementation notifies all observers of everything
    00314     // they must filter the notifications that they are not interested
    00315     // in (i.e. a hub, not a router)
    00316     DBG_ASSERT(observer);
    00317
    00318     std::vector<Observer*>::iterator attached_observer;
    00319     attached_observer = std::find(observers_.begin(), observers_.end(), observer);
    00320     DBG_ASSERT(attached_observer == observers_.end());
    00321
    00322     DBG_ASSERT(observer);
    00323 #endif
    00324
    00325     observers_.push_back(observer);
    00326   }
    00327
    00328   inline
    00329   void Subject::DetachObserver(Observer::NotifyType notify_type, Observer* observer) const
    00330   {
    00331 #ifdef IP_DEBUG_OBSERVER
    00332     DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
    00333     DBG_ASSERT(observer);
    00334 #endif
    00335
    00336     if (observer) {
    00337       std::vector<Observer*>::iterator attached_observer;
    00338       attached_observer = std::find(observers_.begin(), observers_.end(), observer);
    00339 #ifdef IP_DEBUG_OBSERVER
    00340
    00341       DBG_ASSERT(attached_observer != observers_.end());
    00342 #endif
    00343
    00344       if (attached_observer != observers_.end()) {
    00345         observers_.erase(attached_observer);
    00346       }
    00347     }
    00348   }
    00349
    00350   inline
    00351   void Subject::Notify(Observer::NotifyType notify_type) const
    00352   {
    00353 #ifdef IP_DEBUG_OBSERVER
    00354     DBG_START_METH("Subject::Notify", dbg_verbosity);
    00355 #endif
    00356
    00357     std::vector<Observer*>::iterator iter;
    00358     for (iter = observers_.begin(); iter != observers_.end(); iter++) {
    00359       (*iter)->ProcessNotification(notify_type, this);
    00360     }
    00361   }
    00362
    00363
    00364 } // namespace Ipopt
    00365
    00366 #endif

All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines