00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __CS_CSEVENTSUBSCRIPTION_H__
00021 #define __CS_CSEVENTSUBSCRIPTION_H__
00022
00023 #include "csutil/partialorder.h"
00024 #include "csutil/tree.h"
00025 #include "csutil/list.h"
00026 #include "csutil/eventhandlers.h"
00027 #include "iutil/eventh.h"
00028
00029 class csEventQueue;
00030
00031
00041 class csEventTree : public csTreeNode
00042 {
00043 public:
00044
00045 class SubscriberIterator;
00046
00052 csEventTree *FindNode (csEventID name, csEventQueue *q);
00059 bool Subscribe (csHandlerID, csEventID, csEventQueue *q);
00069 void Unsubscribe(csHandlerID, csEventID, csEventQueue *q);
00070
00075 void Notify();
00080 void Dispatch(iEvent &e);
00081
00082 #ifdef ADB_DEBUG
00083
00084 void Dump();
00085 #endif
00086
00087 static inline csEventTree *CreateRootNode(csRef<iEventHandlerRegistry> ®1,
00088 csRef<iEventNameRegistry> ®2,
00089 csEventQueue *q)
00090 {
00091 return new csEventTree (reg1, reg2, reg2->GetID(""), 0, q);
00092 }
00093
00094 static inline void DeleteRootNode(csEventTree *node)
00095 {
00096 CS_ASSERT(node);
00097 CS_ASSERT(node->self == node->name_reg->GetID(""));
00098 delete node;
00099 }
00100
00101 private:
00102 csRef<iEventHandlerRegistry> handler_reg;
00103 csRef<iEventNameRegistry> name_reg;
00104 #ifdef ADB_DEBUG
00105 void Dump(int depth);
00106 #endif
00107
00108 csEventTree *FindNodeInternal(csEventID &name, csEventQueue *q);
00109
00116 csEventTree (csRef<iEventHandlerRegistry> &,
00117 csRef<iEventNameRegistry> &,
00118 csEventID name, csEventTree *parent, csEventQueue *q);
00119 ~csEventTree ();
00120
00121 csEventID self;
00122 csEventQueue *queue;
00123
00124 bool SubscribeInternal (csHandlerID, csEventID);
00125 void UnsubscribeInternal (csHandlerID);
00134 bool fatNode;
00135
00143 class FatRecordObject
00144 {
00145 private:
00146 csRef<iEventHandlerRegistry> handler_reg;
00147 csRef<iEventNameRegistry> name_reg;
00148 public:
00149 FatRecordObject(csEventTree *root,
00150 csRef<iEventHandlerRegistry> &h_reg,
00151 csRef<iEventNameRegistry> &n_reg,
00152 csPartialOrder<csHandlerID> *new_sg,
00153 csList<iEventHandler *> *new_sq) :
00154 handler_reg (h_reg), name_reg (n_reg),
00155 SubscriberGraph (new_sg), SubscriberQueue (new_sq),
00156 my_root (root), iterator (0), iterating_for (0)
00157 {
00158
00159 StaleSubscriberQueue = (SubscriberQueue==0);
00160 }
00161
00162 ~FatRecordObject()
00163 {
00164 delete SubscriberGraph;
00165 if (SubscriberQueue)
00166 delete SubscriberQueue;
00167 CS_ASSERT (iterator == 0);
00168 CS_ASSERT (iterating_for == 0);
00169 }
00170
00174 void RebuildQueue();
00178 csPartialOrder<csHandlerID> *SubscribeInternal(csHandlerID, csEventID);
00182 void UnsubscribeInternal(csHandlerID);
00183
00187 csPartialOrder<csHandlerID> *SubscriberGraph;
00192 csList<iEventHandler *> *SubscriberQueue;
00198 bool StaleSubscriberQueue;
00202 csEventTree *my_root;
00208 SubscriberIterator *iterator;
00213 csEventTree *iterating_for;
00214 };
00215
00216 FatRecordObject *fatRecord;
00217
00224 void ForceFatCopy();
00225
00230 void KillFatCopy();
00231
00237 void PushFatCopy(FatRecordObject *);
00238
00239
00240 public:
00251 class SubscriberIterator
00252 {
00253 public:
00258 SubscriberIterator (iEventHandlerRegistry* r, csEventTree *t,
00259 csEventID bevent) : handler_reg(r), record(t->fatRecord),
00260 baseevent(bevent), mode(SI_LIST), qit(0)
00261 {
00262 CS_ASSERT(record->iterator == 0);
00263 record->iterator = this;
00264 record->iterating_for = t;
00265 if (t->fatRecord->SubscriberQueue)
00266 qit = new csList<iEventHandler *>::Iterator (
00267 *t->fatRecord->SubscriberQueue);
00268 else
00269 GraphMode();
00270 }
00271
00275 ~SubscriberIterator ()
00276 {
00277 CS_ASSERT(record->iterator == this);
00278 record->iterator = 0;
00279 record->iterating_for = 0;
00280 delete qit;
00281 }
00282
00284 inline bool HasNext ()
00285 {
00286 switch(mode)
00287 {
00288 case SI_LIST:
00289 return qit->HasNext ();
00290
00291 case SI_GRAPH:
00292 do
00293 {
00294 csHandlerID id = record->SubscriberGraph->GetEnabled (
00295 CS_HANDLER_INVALID);
00296 if (id == CS_HANDLER_INVALID)
00297 break;
00298 else if (handler_reg->IsInstance(id))
00299 return true;
00300 else
00301 record->SubscriberGraph->Mark(id);
00302 }
00303 while (true);
00304 return false;
00305
00306 default:
00307 CS_ASSERT((mode == SI_LIST) ||
00308 (mode == SI_GRAPH));
00309 return false;
00310 }
00311 }
00312
00314 inline iEventHandler *Next ()
00315 {
00316 switch(mode)
00317 {
00318 case SI_LIST:
00319
00320 return qit->Next ();
00321
00322 case SI_GRAPH:
00323
00324 do
00325 {
00326 csHandlerID id = record->SubscriberGraph->GetEnabled (
00327 CS_HANDLER_INVALID);
00328 if (id == CS_HANDLER_INVALID)
00329 break;
00330 else if (handler_reg->IsInstance (id))
00331 {
00332 record->SubscriberGraph->Mark (id);
00333 return handler_reg->GetHandler (id);
00334 }
00335 else
00336 record->SubscriberGraph->Mark(id);
00337 }
00338 while (true);
00339 return 0;
00340
00341 default:
00342 CS_ASSERT((mode == SI_LIST) ||
00343 (mode == SI_GRAPH));
00344 return 0;
00345 }
00346 }
00347
00348
00349 void GraphMode ();
00350
00351 private:
00352 friend class csEventTree;
00353 friend class csEventQueueTest;
00354
00355 csRef<iEventHandlerRegistry> handler_reg;
00356 FatRecordObject *record;
00357 csEventID baseevent;
00358 enum
00359 {
00360 SI_LIST,
00361 SI_GRAPH
00362 } mode;
00363
00364
00365 csList<iEventHandler *>::Iterator* qit;
00366 };
00367 friend class SubscriberIterator;
00368 friend class csEventQueueTest;
00369
00374 SubscriberIterator *GetIterator();
00375
00376 };
00377
00378 #endif // __CS_CSEVENTSUBSCRIPTION_H__