00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "context.h"
00031
00032
00033 using namespace CVCL;
00034 using namespace std;
00035
00036
00037
00038
00039
00040
00041
00042 void Scope::addToChain(ContextObjChain* obj)
00043 {
00044
00045 if(d_restoreChain != NULL)
00046 d_restoreChain->d_restoreChainPrev = &obj->d_restoreChainNext;
00047 obj->d_restoreChainNext = d_restoreChain;
00048 obj->d_restoreChainPrev = &d_restoreChain;
00049 d_restoreChain = obj;
00050 }
00051
00052
00053 Scope::Scope(Context* context, Scope* prevScope)
00054 : d_context(context), d_prevScope(prevScope), d_restoreChain(NULL)
00055 {
00056 if (prevScope) d_level = prevScope->level() + 1;
00057 else d_level = 0;
00058 IF_DEBUG(d_delayDelete = false);
00059 }
00060
00061
00062 Scope::~Scope()
00063 {
00064
00065 TRACE_MSG("context verbose", "~Scope() {");
00066 ContextObjChain* obj = d_restoreChain;
00067
00068 IF_DEBUG(d_delayDelete=true);
00069
00070 IF_DEBUG(
00071 if(debugger.trace("memory") && obj != NULL) {
00072 ostream& os = debugger.getOS();
00073 int n(0);
00074 ContextObjChain* tmp = obj;
00075 while(tmp != NULL) {
00076 tmp = tmp->d_restoreChainNext;
00077 n++;
00078 }
00079 os << "*** Warning: ~Scope(): found "<< n << " leaked objects "
00080 << "in scope " << d_level << ":" << endl;
00081 if(debugger.flag("memory leaks")) {
00082 tmp = obj;
00083 while(tmp != NULL) {
00084 os << tmp->name() << "\n";
00085 tmp = tmp->d_restoreChainNext;
00086 }
00087 }
00088 os << flush;
00089 }
00090 )
00091
00092 TRACE_MSG("context verbose", "~Scope(): Deleting the chain");
00093 while (obj != NULL) {
00094 ContextObjChain* tmp = obj->d_restoreChainNext;
00095
00096
00097 if(obj->d_master!=NULL && obj->d_master->d_scope == this)
00098 obj->d_master->d_scope = NULL;
00099 delete obj;
00100 obj = tmp;
00101 }
00102 TRACE_MSG("context verbose", "~Scope() => }");
00103 }
00104
00105
00106 void Scope::restore(void)
00107 {
00108 TRACE_MSG("context verbose", "Scope::restore() {");
00109 d_delayDelete=true;
00110 while (d_restoreChain != NULL) d_restoreChain = d_restoreChain->restore();
00111 d_delayDelete=false;
00112 TRACE_MSG("context verbose", "Scope::restore() }");
00113 }
00114
00115
00116
00117
00118
00119
00120
00121 ContextObjChain::ContextObjChain(ContextObj* data, ContextObj* master,
00122 ContextObjChain* restore)
00123 : d_restoreChainNext(NULL), d_restoreChainPrev(NULL),
00124 d_restore(restore), d_data(data), d_master(master) { }
00125
00126
00127 ContextObjChain* ContextObjChain::restore(void)
00128 {
00129
00130
00131
00132
00133 ContextObjChain* next;
00134 if(d_master==NULL) {
00135 next = d_restoreChainNext;
00136 } else if(d_data == NULL) {
00137 d_master->setNull();
00138 Scope*& masterScope(d_master->d_scope);
00139 masterScope = d_master->d_scope->prevScope();
00140
00141 DebugAssert(d_restore==NULL,"Expected NULL");
00142 next = d_restoreChainNext;
00143 masterScope->addToChain(this);
00144 }
00145 else {
00146 d_master->restoreData(d_data);
00147 d_master->d_scope = d_data->d_scope;
00148 d_master->d_restore = d_restore;
00149 next = d_restoreChainNext;
00150 delete this;
00151 }
00152 return next;
00153 }
00154
00155
00156 ContextObjChain::~ContextObjChain()
00157 {
00158
00159 if(d_data != NULL) delete d_data;
00160
00161
00162 if(d_master!=NULL && d_master->d_restore == this)
00163 d_master->d_restore = NULL;
00164 }
00165
00166
00167 IF_DEBUG(
00168 std::string
00169 ContextObjChain::name() const {
00170 if(d_master == NULL) return "Unknown";
00171 return d_master->name();
00172 }
00173 )
00174
00175
00176
00177
00178
00179 ContextObj::ContextObj(const ContextObj& co)
00180 : d_scope(co.d_scope), d_restore(co.d_restore) {
00181 IF_DEBUG(d_name=co.d_name);
00182 DebugAssert(co.d_active, "ContextObj["+co.name()+"] copy constructor");
00183 IF_DEBUG(d_active = co.d_active);
00184 TRACE("context verbose", "ContextObj()[", this, "]: copy constructor");
00185 }
00186
00187
00188 ContextObj& ContextObj::operator=(const ContextObj& co) {
00189 DebugAssert(false, "ContextObj::operator=(): shouldn't be called");
00190 return *this;
00191 }
00192
00193
00194 void ContextObj::update(int scope)
00195 {
00196
00197
00198
00199
00200
00201
00202
00203 ContextObj* data = makeCopy();
00204 data->d_scope=d_scope;
00205
00206 data->d_restore=NULL;
00207 IF_DEBUG(data->setName(name()+" [copy]"));
00208 ContextObjChain* obj = new ContextObjChain(data, this, d_restore);
00209 d_restore = obj;
00210 DebugAssert(scope < 0 || d_scope->level() < scope,
00211 "ContextObj::update(scope="+int2string(scope)
00212 +"): scope < d_scope->level() = "
00213 +int2string(d_scope->level()));
00214 d_scope = d_scope->topScope();
00215 if(scope >= 0) {
00216
00217 for(int i=level(); i>scope; --i) {
00218 d_scope = d_scope->prevScope();
00219 DebugAssert(d_scope != NULL, "ContextObj::update["
00220 +name()+"]: d_scope == NULL");
00221 }
00222 }
00223 d_scope->addToChain(obj);
00224
00225 }
00226
00227
00228
00229
00230
00231
00232 ContextObj::ContextObj(Context* context, bool atBottomScope)
00233 IF_DEBUG(: d_name("ContextObj"))
00234 {
00235 IF_DEBUG(d_active=true);
00236 DebugAssert(context != NULL, "NULL context pointer");
00237 if(atBottomScope) d_scope = context->bottomScope();
00238 else d_scope = context->topScope();
00239 d_restore = new ContextObjChain(NULL, this, NULL);
00240 d_scope->addToChain(d_restore);
00241 TRACE("context verbose", "ContextObj()[", this, "]");
00242 }
00243
00244
00245 ContextObj::~ContextObj()
00246 {
00247
00248
00249 TRACE("context verbose",
00250 string("~ContextObj(")+(d_scope && d_scope->d_delayDelete? "delayed" : "")+")[",
00251 this, "] {");
00252 DebugAssert(d_scope==NULL || !d_scope->d_delayDelete,
00253 "~ContextObj["+name()+"]");
00254 DebugAssert(d_active, "~ContextObj["+name()+"]");
00255 IF_DEBUG(d_active=false);
00256
00257
00258
00259
00260
00261 for(ContextObjChain* obj = d_restore; obj != NULL; ) {
00262 ContextObjChain* tmp = obj->d_restore;
00263
00264 if(obj->d_restoreChainNext != NULL)
00265 obj->d_restoreChainNext->d_restoreChainPrev = obj->d_restoreChainPrev;
00266 *(obj->d_restoreChainPrev) = obj->d_restoreChainNext;
00267
00268 delete obj;
00269 obj = tmp;
00270 }
00271
00272 TRACE("context verbose", "~ContextObj()[", this, "] }");
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 Context::Context(ContextManager* cm, const string& name, int id)
00282 : d_cm(cm), d_name(name), d_id(id)
00283 {
00284 d_topScope = new Scope(this);
00285 d_bottomScope = d_topScope;
00286 TRACE("context", "*** [context] Creating new context: name = "
00287 + name + "id = ", id, "");
00288 }
00289
00290
00291
00292
00293 Context::~Context()
00294 {
00295
00296 Scope* top = d_topScope;
00297 while(top != NULL) {
00298 top = d_topScope->prevScope();
00299 delete d_topScope;
00300 d_topScope = top;
00301 }
00302
00303 for(vector<ContextNotifyObj*>::iterator i=d_notifyObjList.begin(),
00304 iend=d_notifyObjList.end(); i!=iend; ++i) {
00305 (*i)->d_context = NULL;
00306 }
00307
00308 }
00309
00310
00311 void Context::pop()
00312 {
00313
00314
00315
00316
00317
00318 Scope* top = d_topScope;
00319 TRACE("context", "*** [context] Popping scope from level ", level(), "...");
00320 DebugAssert(top->prevScope() != NULL,
00321 "Illegal to pop last scope off of stack.");
00322
00323 for(vector<ContextNotifyObj*>::iterator i=d_notifyObjList.begin(),
00324 iend=d_notifyObjList.end(); i != iend; ++i)
00325 (*i)->notifyPre();
00326
00327 d_topScope = top->prevScope();
00328 top->restore();
00329 delete top;
00330
00331 for(vector<ContextNotifyObj*>::iterator i=d_notifyObjList.begin(),
00332 iend=d_notifyObjList.end(); i != iend; ++i)
00333 (*i)->notify();
00334 TRACE("context", "*** [context] Popped scope to level ", level(), "}");
00335
00336 }
00337
00338
00339 void Context::popto(int toLevel)
00340 {
00341
00342
00343 while (toLevel < topScope()->level()) pop();
00344
00345 }
00346
00347
00348 void Context::deleteNotifyObj(ContextNotifyObj* obj) {
00349 size_t i(0), iend(d_notifyObjList.size());
00350 for(; i<iend && d_notifyObjList[i]!=obj; ++i);
00351 if(i<iend) {
00352 d_notifyObjList[i]=d_notifyObjList.back();
00353 d_notifyObjList.pop_back();
00354 }
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 ContextManager::ContextManager()
00364 {
00365 d_curContext = createContext("default");
00366 }
00367
00368
00369 ContextManager::~ContextManager()
00370 {
00371 while (d_contexts.size()) {
00372 delete d_contexts.back();
00373 d_contexts.pop_back();
00374 }
00375 }
00376
00377
00378 Context* ContextManager::createContext(const string& name)
00379 {
00380 d_contexts.push_back(new Context(this, name, d_contexts.size()));
00381 return d_contexts.back();
00382 }
00383
00384
00385 Context* ContextManager::switchContext(Context* context)
00386 {
00387 DebugAssert(false, "Multiple contexts not yet implemented");
00388 Context* old = d_curContext;
00389 DebugAssert(context && context == d_contexts[context->id()],
00390 "Unknown context");
00391 d_curContext = context;
00392
00393 return old;
00394 }