Ipopt
trunk
|
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$ 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