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 virtual ~Observer();
00056
00058 enum NotifyType {
00059 NT_All,
00060 NT_BeingDestroyed,
00061 NT_Changed
00062 };
00063
00064 protected:
00070 void RequestAttach(NotifyType notify_type, const Subject* subject);
00071
00077 void RequestDetach(NotifyType notify_type, const Subject* subject);
00078
00083 virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
00084
00085 private:
00095 Observer(const Observer&);
00096
00098 void operator=(const Observer&);
00100
00103 std::vector<const Subject*> subjects_;
00104
00111 void ProcessNotification(NotifyType notify_type, const Subject* subject);
00112
00113 friend class Subject;
00114 };
00115
00124 class Subject
00125 {
00126 public:
00127 #ifdef IP_DEBUG_OBSERVER
00128
00129 static const Index dbg_verbosity;
00130 #endif
00131
00135 Subject()
00136 {}
00137
00139 virtual ~Subject();
00141
00153
00156 void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00157
00160 void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00162
00163 protected:
00164
00165 void Notify(Observer::NotifyType notify_type) const;
00166
00167 private:
00177 Subject(const Subject&);
00178
00180 void operator=(const Subject&);
00182
00183 mutable std::vector<Observer*> observers_;
00184
00185 };
00186
00187
00188 inline
00189 Observer::~Observer()
00190 {
00191 #ifdef IP_DEBUG_OBSERVER
00192 DBG_START_METH("Observer::~Observer", dbg_verbosity);
00193 if (DBG_VERBOSITY()>=1) {
00194 for (Index i=0; i<(Index)subjects_.size(); i++) {
00195 DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
00196 }
00197 }
00198 #endif
00199
00200 for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
00201 #ifdef IP_DEBUG_OBSERVER
00202 DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
00203 #endif
00204
00205 RequestDetach(NT_All, subjects_[i]);
00206 }
00207 }
00208
00209 inline
00210 void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
00211 {
00212 #ifdef IP_DEBUG_OBSERVER
00213 DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
00214
00215
00216 std::vector<const Subject*>::iterator attached_subject;
00217 attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00218 DBG_ASSERT(attached_subject == subjects_.end());
00219 DBG_ASSERT(subject);
00220 #endif
00221
00222
00223 subjects_.push_back(subject);
00224
00225 subject->AttachObserver(notify_type, this);
00226 }
00227
00228 inline
00229 void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
00230 {
00231 #ifdef IP_DEBUG_OBSERVER
00232 DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
00233 DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
00234 DBG_ASSERT(subject);
00235 #endif
00236
00237 if (subject) {
00238 std::vector<const Subject*>::iterator attached_subject;
00239 attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00240 #ifdef IP_DEBUG_OBSERVER
00241
00242 DBG_ASSERT(attached_subject != subjects_.end());
00243 #endif
00244
00245 if (attached_subject != subjects_.end()) {
00246 #ifdef IP_DEBUG_OBSERVER
00247 DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
00248 #endif
00249
00250 subjects_.erase(attached_subject);
00251 }
00252
00253
00254 subject->DetachObserver(notify_type, this);
00255 }
00256 }
00257
00258 inline
00259 void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
00260 {
00261 #ifdef IP_DEBUG_OBSERVER
00262 DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
00263 DBG_ASSERT(subject);
00264 #endif
00265
00266 if (subject) {
00267 std::vector<const Subject*>::iterator attached_subject;
00268 attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00269
00270
00271
00272 #ifdef IP_DEBUG_OBSERVER
00273
00274 DBG_ASSERT(attached_subject != subjects_.end());
00275 #endif
00276
00277 this->RecieveNotification(notify_type, subject);
00278
00279 if (notify_type == NT_BeingDestroyed) {
00280
00281 subjects_.erase(attached_subject);
00282 }
00283 }
00284 }
00285
00286 inline
00287 Subject::~Subject()
00288 {
00289 #ifdef IP_DEBUG_OBSERVER
00290 DBG_START_METH("Subject::~Subject", dbg_verbosity);
00291 #endif
00292
00293 std::vector<Observer*>::iterator iter;
00294 for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00295 (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
00296 }
00297 }
00298
00299 inline
00300 void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
00301 {
00302 #ifdef IP_DEBUG_OBSERVER
00303 DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
00304
00305
00306
00307 DBG_ASSERT(observer);
00308
00309 std::vector<Observer*>::iterator attached_observer;
00310 attached_observer = std::find(observers_.begin(), observers_.end(), observer);
00311 DBG_ASSERT(attached_observer == observers_.end());
00312
00313 DBG_ASSERT(observer);
00314 #endif
00315
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 }
00356
00357 #endif