00001
00002
00003
00004
00005
00006
00007
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
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
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
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
00220 subjects_.push_back(subject);
00221
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
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
00268
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
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
00302
00303
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 }
00356
00357 #endif