// ************************************************************** // * * // * Spheres.h -- Version 2.0 * // * * // * (C) Christian Scheideler, 2003 * // * * // ************************************************************** // room for definitions... // -------------------------------------------------------------- // Do not change anything below this line // -------------------------------------------------------------- // Sphere class enables non-blocking method invokation (NMI) class Sphere; // SphereCall can be used for pointing to a Sphere function typedef void (Sphere::*_SphereCall)(void *); // Send adds an event to the event queue ES #define Send(SpherePtr, Method, ParList) \ _ES->Add(new _Event(dynamic_cast(SpherePtr), (_SphereCall) &Method, (void*) ParList)) // Register registers a Sphere under a given group ID #define Register(GID) \ _ES->_Register(this, GID) // Unregister removes a Sphere from a given group ID list #define Unregister(GID) \ _ES->_Unregister(this, GID) // Any gives back any pointer to a Sphere registered under GID #define Any(GID) \ _ES->_Any(GID) // Simulate starts the simulation for time many rounds #define Simulate(time) \ _ES->Run(time) // definition of class Sphere class Sphere { public: // Call performs calls to methods in classes derived from Sphere virtual void Call(_SphereCall CallPtr, void* PListPtr) { (this->*CallPtr)(PListPtr); } }; // An Event stores a NMI request for a Sphere object class _Event { public: Sphere *SpherePtr; // pointer to Sphere to be activated _SphereCall CallPtr; // function within ID to be called void *PListPtr; // pointer to parameter list _Event *next; // next event in event list _Event(Sphere *s, _SphereCall c, void *pl) { SpherePtr = s; CallPtr = c; PListPtr = pl; next = NULL; } }; // Implementation of node for list of Sphere pointers class _SLNode { public: Sphere *SpherePtr; _SLNode *next; _SLNode(Sphere *s, _SLNode *n) { SpherePtr = s; next = n; } }; // Implementation of node for Sphere group IDs (GIDs) class _GIDNode { public: int GID; _SLNode *begin; _SLNode *end; _GIDNode *next; _GIDNode(int id, _SLNode *s, _GIDNode *n) { GID = id; begin = s; end = s; next = n; } void Remove(Sphere *sp) { _SLNode *SLPtr, *SLPtr2; while (begin!=NULL && begin->SpherePtr == sp) { SLPtr = begin; begin = begin->next; delete SLPtr; } if (begin!=NULL) { SLPtr = begin; while (SLPtr!=end) { while (SLPtr->next!=end && SLPtr->next->SpherePtr!=sp) SLPtr = SLPtr->next; if (SLPtr->next==end) { if (SLPtr->next->SpherePtr==sp) { SLPtr2 = SLPtr->next; SLPtr->next = NULL; end = SLPtr; delete SLPtr2; } else SLPtr = end; } else { SLPtr2 = SLPtr->next; SLPtr->next = SLPtr2->next; delete SLPtr2; } } } } }; // The Scheduler inserts Events and executes them in the order of their time class _Scheduler { private: _Event *_OldEvents; // pointer to list of current events _Event *_NewEvents; // pointer to list of new events _Event *_NewEnd; // pointer to last event in new event list _GIDNode *GIDList; // sorted list of GIDs public: _Scheduler() { _OldEvents = NULL; _NewEvents = NULL; _NewEnd = NULL; GIDList = NULL; } // Add adds a new event to the new events list void Add(_Event *e) { if (_NewEvents == NULL) _NewEvents = e; else _NewEnd->next = e; _NewEnd = e; } // Remove removes an event from the old events list _Event *Remove() { _Event *e = _OldEvents; _OldEvents = _OldEvents->next; return e; } // Register adds a Sphere pointer to the list for GID void _Register(Sphere *sp, int id) { _GIDNode *GIDPtr; _SLNode *SLPtr; SLPtr = new _SLNode(sp, NULL); if (GIDList==NULL || GIDList->GID>id) GIDList = new _GIDNode(id, SLPtr, GIDList); else { if (GIDList->GID == id) { SLPtr->next = GIDList->begin; GIDList->begin = SLPtr; } else { GIDPtr = GIDList; while (GIDPtr->next!=NULL && GIDPtr->next->GIDnext; if (GIDPtr->next==NULL || GIDPtr->next->GID>id) GIDPtr->next = new _GIDNode(id, SLPtr, GIDPtr->next); else { SLPtr->next = GIDPtr->next->begin; GIDPtr->next->begin = SLPtr; } } } } // Unregister removes a Sphere pointer from the list for GID void _Unregister(Sphere* sp, int id) { _GIDNode *GIDPtr, *GIDPtr2; if (GIDList!=NULL && GIDList->GID<=id) { if (GIDList->GID == id) { GIDList->Remove(sp); if (GIDList->begin == NULL) { GIDPtr = GIDList; GIDList = GIDList->next; delete GIDPtr; } } else { GIDPtr = GIDList; while (GIDPtr->next!=NULL && GIDPtr->next->GIDnext; if (GIDPtr->next!=NULL && GIDPtr->next->GID==id) { GIDPtr->next->Remove(sp); if (GIDPtr->next->begin == NULL) { GIDPtr2 = GIDPtr->next; GIDPtr->next = GIDPtr2->next; delete GIDPtr2; } } } } } // Any gives back a Sphere pointer from the list for GID Sphere* _Any(int id) { _GIDNode *GIDPtr; _SLNode *SLPtr; GIDPtr = GIDList; while (GIDPtr!=NULL && GIDPtr->GIDnext; if (GIDPtr == NULL || GIDPtr->GID>id) return NULL; else { SLPtr = GIDPtr->begin; if (GIDPtr->begin->next != NULL) { GIDPtr->begin = GIDPtr->begin->next; GIDPtr->end->next = SLPtr; GIDPtr->end = SLPtr; } return SLPtr->SpherePtr; } } // Run executes the RMI requests until the queue is empty or time is reached void Run(long time) { _Event *e; long t; t=1; while (t<=time && _NewEvents != NULL) { _OldEvents = _NewEvents; _NewEvents = NULL; _NewEnd = NULL; while (_OldEvents != NULL) { e = Remove(); (e->SpherePtr)->Call(e->CallPtr, e->PListPtr); delete e; } t++; } } }; // ES is the object handling the RMI requests _Scheduler *_ES = new _Scheduler();