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 {
00060 NT_All,
00061 NT_BeingDestroyed,
00062 NT_Changed
00063 };
00064
00065 protected:
00071 void RequestAttach(NotifyType notify_type, const Subject* subject);
00072
00078 void RequestDetach(NotifyType notify_type, const Subject* subject);
00079
00084 virtual void RecieveNotification(NotifyType notify_type, const Subject* subject)=0;
00085
00086 private:
00096 Observer(const Observer&);
00097
00099 void operator=(const Observer&);
00101
00104 std::vector<const Subject*> subjects_;
00105
00112 void ProcessNotification(NotifyType notify_type, const Subject* subject);
00113
00114 friend class Subject;
00115 };
00116
00125 class Subject
00126 {
00127 public:
00128 #ifdef IP_DEBUG_OBSERVER
00129
00130 static const Index dbg_verbosity;
00131 #endif
00132
00136 Subject()
00137 {}
00138
00140 virtual ~Subject();
00142
00154
00157 void AttachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00158
00161 void DetachObserver(Observer::NotifyType notify_type, Observer* observer) const;
00163
00164 protected:
00165
00166 void Notify(Observer::NotifyType notify_type) const;
00167
00168 private:
00178 Subject(const Subject&);
00179
00181 void operator=(const Subject&);
00183
00184 mutable std::vector<Observer*> observers_;
00185
00186 };
00187
00188
00189 inline
00190 Observer::~Observer()
00191 {
00192 #ifdef IP_DEBUG_OBSERVER
00193 DBG_START_METH("Observer::~Observer", dbg_verbosity);
00194 if (DBG_VERBOSITY()>=1) {
00195 for (Index i=0; i<(Index)subjects_.size(); i++) {
00196 DBG_PRINT((1,"subjects_[%d] = 0x%x\n", i, subjects_[i]));
00197 }
00198 }
00199 #endif
00200
00201 for (Int i=(Int)(subjects_.size()-1); i>=0; i--) {
00202 #ifdef IP_DEBUG_OBSERVER
00203 DBG_PRINT((1,"About to detach subjects_[%d] = 0x%x\n", i, subjects_[i]));
00204 #endif
00205
00206 RequestDetach(NT_All, subjects_[i]);
00207 }
00208 }
00209
00210 inline
00211 void Observer::RequestAttach(NotifyType notify_type, const Subject* subject)
00212 {
00213 #ifdef IP_DEBUG_OBSERVER
00214 DBG_START_METH("Observer::RequestAttach", dbg_verbosity);
00215
00216
00217 std::vector<const Subject*>::iterator attached_subject;
00218 attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00219 DBG_ASSERT(attached_subject == subjects_.end());
00220 DBG_ASSERT(subject);
00221 #endif
00222
00223
00224 subjects_.push_back(subject);
00225
00226 subject->AttachObserver(notify_type, this);
00227 }
00228
00229 inline
00230 void Observer::RequestDetach(NotifyType notify_type, const Subject* subject)
00231 {
00232 #ifdef IP_DEBUG_OBSERVER
00233 DBG_START_METH("Observer::RequestDetach", dbg_verbosity);
00234 DBG_PRINT((1, "Requesting detach of subject: 0x%x\n", subject));
00235 DBG_ASSERT(subject);
00236 #endif
00237
00238 if (subject) {
00239 std::vector<const Subject*>::iterator attached_subject;
00240 attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00241 #ifdef IP_DEBUG_OBSERVER
00242
00243 DBG_ASSERT(attached_subject != subjects_.end());
00244 #endif
00245
00246 if (attached_subject != subjects_.end()) {
00247 #ifdef IP_DEBUG_OBSERVER
00248 DBG_PRINT((1, "Removing subject: 0x%x from the list\n", subject));
00249 #endif
00250
00251 subjects_.erase(attached_subject);
00252 }
00253
00254
00255 subject->DetachObserver(notify_type, this);
00256 }
00257 }
00258
00259 inline
00260 void Observer::ProcessNotification(NotifyType notify_type, const Subject* subject)
00261 {
00262 #ifdef IP_DEBUG_OBSERVER
00263 DBG_START_METH("Observer::ProcessNotification", dbg_verbosity);
00264 DBG_ASSERT(subject);
00265 #endif
00266
00267 if (subject) {
00268 std::vector<const Subject*>::iterator attached_subject;
00269 attached_subject = std::find(subjects_.begin(), subjects_.end(), subject);
00270
00271
00272
00273 #ifdef IP_DEBUG_OBSERVER
00274
00275 DBG_ASSERT(attached_subject != subjects_.end());
00276 #endif
00277
00278 this->RecieveNotification(notify_type, subject);
00279
00280 if (notify_type == NT_BeingDestroyed) {
00281
00282 subjects_.erase(attached_subject);
00283 }
00284 }
00285 }
00286
00287 inline
00288 Subject::~Subject()
00289 {
00290 #ifdef IP_DEBUG_OBSERVER
00291 DBG_START_METH("Subject::~Subject", dbg_verbosity);
00292 #endif
00293
00294 std::vector<Observer*>::iterator iter;
00295 for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00296 (*iter)->ProcessNotification(Observer::NT_BeingDestroyed, this);
00297 }
00298 }
00299
00300 inline
00301 void Subject::AttachObserver(Observer::NotifyType notify_type, Observer* observer) const
00302 {
00303 #ifdef IP_DEBUG_OBSERVER
00304 DBG_START_METH("Subject::AttachObserver", dbg_verbosity);
00305
00306
00307
00308 DBG_ASSERT(observer);
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
00314 DBG_ASSERT(observer);
00315 #endif
00316
00317 observers_.push_back(observer);
00318 }
00319
00320 inline
00321 void Subject::DetachObserver(Observer::NotifyType notify_type, Observer* observer) const
00322 {
00323 #ifdef IP_DEBUG_OBSERVER
00324 DBG_START_METH("Subject::DetachObserver", dbg_verbosity);
00325 DBG_ASSERT(observer);
00326 #endif
00327
00328 if (observer) {
00329 std::vector<Observer*>::iterator attached_observer;
00330 attached_observer = std::find(observers_.begin(), observers_.end(), observer);
00331 #ifdef IP_DEBUG_OBSERVER
00332
00333 DBG_ASSERT(attached_observer != observers_.end());
00334 #endif
00335
00336 if (attached_observer != observers_.end()) {
00337 observers_.erase(attached_observer);
00338 }
00339 }
00340 }
00341
00342 inline
00343 void Subject::Notify(Observer::NotifyType notify_type) const
00344 {
00345 #ifdef IP_DEBUG_OBSERVER
00346 DBG_START_METH("Subject::Notify", dbg_verbosity);
00347 #endif
00348
00349 std::vector<Observer*>::iterator iter;
00350 for (iter = observers_.begin(); iter != observers_.end(); iter++) {
00351 (*iter)->ProcessNotification(notify_type, this);
00352 }
00353 }
00354
00355
00356 }
00357
00358 #endif