00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __IPOBSERVER_HPP__
00010 #define __IPOBSERVER_HPP__
00011
00012 #include "IpUtils.hpp"
00013 #include <vector>
00014 #include <algorithm>
00015
00016
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
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
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
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
00232 subjects_.push_back(subject);
00233
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
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
00280
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
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
00314
00315
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 }
00365
00366 #endif