## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# csutil/cssubscription.h

    00001 /*
    00002   Crystal Space 3D engine - Event Subscription internals
    00003   Copyright (C) 2005 by Adam D. Bradley <artdodge@cs.bu.edu>
    00004
    00005   This library is free software; you can redistribute it and/or
    00006   modify it under the terms of the GNU Library General Public
    00007   License as published by the Free Software Foundation; either
    00008   version 2 of the License, or (at your option) any later version.
    00009
    00010   This library is distributed in the hope that it will be useful,
    00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013   Library General Public License for more details.
    00014
    00015   You should have received a copy of the GNU Library General Public
    00016   License along with this library; if not, write to the Free
    00017   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    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   // forward declarator
    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   // Dump the event tree and subscriptions to stderr.
    00084   void Dump();
    00085 #endif
    00086
    00087   static inline csEventTree *CreateRootNode(csRef<iEventHandlerRegistry> &reg1,
    00088                                             csRef<iEventNameRegistry> &reg2,
    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 #ifdef CS_DEBUG
    00123   csString *self_name;
    00124 #endif
    00125   csEventQueue *queue;
    00126
    00127   bool SubscribeInternal (csHandlerID, csEventID);
    00128   void UnsubscribeInternal (csHandlerID);
    00137   bool fatNode;
    00138
    00146   class FatRecordObject
    00147   {
    00148   private:
    00149     csRef<iEventHandlerRegistry> handler_reg;
    00150     csRef<iEventNameRegistry> name_reg;
    00151   public:
    00152     FatRecordObject(csEventTree *root,
    00153                     csRef<iEventHandlerRegistry> &h_reg,
    00154                     csRef<iEventNameRegistry> &n_reg,
    00155                     csPartialOrder<csHandlerID> *new_sg,
    00156                     csList<iEventHandler *> *new_sq) :
    00157       handler_reg (h_reg), name_reg (n_reg),
    00158       SubscriberGraph (new_sg), SubscriberQueue (new_sq),
    00159       my_root (root), iterator (0), iterating_for (0)
    00160     {
    00161       /* If there's no SQ, mark it for creation */
    00162       StaleSubscriberQueue = (SubscriberQueue==0);
    00163     }
    00164
    00165     ~FatRecordObject()
    00166     {
    00167       delete SubscriberGraph;
    00168       if (SubscriberQueue)
    00169         delete SubscriberQueue;
    00170       CS_ASSERT (iterator == 0);
    00171       CS_ASSERT (iterating_for == 0);
    00172     }
    00173
    00177     void RebuildQueue();
    00181     csPartialOrder<csHandlerID> *SubscribeInternal(csHandlerID, csEventID);
    00185     void UnsubscribeInternal(csHandlerID);
    00186
    00190     csPartialOrder<csHandlerID> *SubscriberGraph;
    00195     csList<iEventHandler *> *SubscriberQueue;
    00201     bool StaleSubscriberQueue;
    00205     csEventTree *my_root;
    00211     SubscriberIterator *iterator;
    00216     csEventTree *iterating_for;
    00217   };
    00218
    00219   FatRecordObject *fatRecord;
    00220
    00227   void ForceFatCopy();
    00228
    00233   void KillFatCopy();
    00234
    00240   void PushFatCopy(FatRecordObject *);
    00241
    00242
    00243  public:
    00254   class SubscriberIterator
    00255   {
    00256   public:
    00261     SubscriberIterator (csRef<iEventHandlerRegistry> &r,
    00262                         csEventTree *t, csEventID bevent) :
    00263       handler_reg(r), record(t->fatRecord),
    00264       baseevent(bevent), mode(SI_LIST), qit(*t->fatRecord->SubscriberQueue,
    00265         false)
    00266     {
    00267       CS_ASSERT(record->iterator == 0);
    00268       record->iterator = this;
    00269       record->iterating_for = t;
    00270     }
    00271
    00275     ~SubscriberIterator ()
    00276     {
    00277       CS_ASSERT(record->iterator == this);
    00278       record->iterator = 0;
    00279       record->iterating_for = 0;
    00280     }
    00281
    00283     inline bool HasNext ()
    00284     {
    00285       switch(mode)
    00286       {
    00287       case SI_LIST:
    00288         return qit.HasNext ();
    00289
    00290       case SI_GRAPH:
    00291         do
    00292         {
    00293           csHandlerID id = record->SubscriberGraph->GetEnabled (
    00294                 CS_HANDLER_INVALID);
    00295           if (id == CS_HANDLER_INVALID)
    00296             break;
    00297           else if (handler_reg->IsInstance(id))
    00298             return true;
    00299           else
    00300             record->SubscriberGraph->Mark(id);
    00301         }
    00302         while (true);
    00303         return false;
    00304
    00305       default:
    00306         CS_ASSERT((mode == SI_LIST) ||
    00307                   (mode == SI_GRAPH));
    00308         return false;
    00309       }
    00310     }
    00311
    00313     inline iEventHandler *Next ()
    00314     {
    00315       switch(mode)
    00316       {
    00317       case SI_LIST:
    00318         /* DOME : see if the current element has been deleted. */
    00319         return qit.Next ();
    00320
    00321       case SI_GRAPH:
    00322         /* see if the current element has been flagged for deletion. */
    00323         do
    00324         {
    00325           csHandlerID id = record->SubscriberGraph->GetEnabled (
    00326                 CS_HANDLER_INVALID);
    00327           if (id == CS_HANDLER_INVALID)
    00328             break;
    00329           else if (handler_reg->IsInstance (id))
    00330           {
    00331             record->SubscriberGraph->Mark (id);
    00332             return handler_reg->GetHandler (id);
    00333           }
    00334           else
    00335             record->SubscriberGraph->Mark(id);
    00336         }
    00337         while (true);
    00338         return 0;
    00339
    00340       default:
    00341         CS_ASSERT((mode == SI_LIST) ||
    00342                   (mode == SI_GRAPH));
    00343         return 0;
    00344       }
    00345     }
    00346
    00347     /* SI_GRAPH mode data structures and methods */
    00348     void GraphMode (); // change to graph (SI_GRAPH) iterator mode.
    00349
    00350   private:
    00351     friend class csEventTree;
    00352
    00353     csRef<iEventHandlerRegistry> handler_reg;
    00354     FatRecordObject *record;
    00355     csEventID baseevent;
    00356     enum
    00357     {
    00358       SI_LIST,
    00359       SI_GRAPH
    00360     } mode;
    00361
    00362     /* SI_LIST mode data structures */
    00363     csList<iEventHandler *>::Iterator qit;
    00364   };
    00365   friend class SubscriberIterator;
    00366
    00371   SubscriberIterator *GetIterator();
    00372
    00373 };
    00374
    00375 #endif // __CS_CSEVENTSUBSCRIPTION_H__