[MUD-Dev] Re: processors
Adam Wiggins
adam at angel.com
Mon Feb 1 10:52:58 CET 1999
On Sun, 31 Jan 1999, J C Lawrence wrote:
> diablo <diablo at best.com> wrote:
> > A 3 second task would take 20 seconds, but this only happened with a
> > heavy player load. Our tasks are held in a table indexed to some
> > number (some sort of ticker in linux? I don't know the proper names
> > for anything). That table is polled every time the game searches for
> > player input (it cycles through all our player lines constantly),
> > and if a task is found to be either overdue or ready to go off, it
> > goes off.
>
> Ouch.
>
> Cheaper:
>
> 1) Keep the table, but sort it by due time and pProcess the table
> only up to the first record that has a due date in the future. You
> need to take care in your table and sort code to make it minimally
> expensive (choice of sorting algorithm), and in your storage format to
> ensure minimal traversal and ordering expense (no buffer copies, only
> pointer copies if possible).
Standard event handlers. I've written them at the start of so many projects
now I think I could do it blind, typing with my nose, and still finish
in less than 90 seconds.
In fact, here we go:
typedef float Tick;
class Event
{
friend class EventManager;
public:
Event(Tick time)
{
RipenTime = EventManager::GetCurrentTime() + time;
EventManager::AddEvent(this);
}
virtual void Ripen() = 0;
bool RipensBefore(Event *e) { return (RipenTime < e->RipenTime); }
bool RipensBy(Tick time) { return (RipenTime <= time); }
private:
Tick RipenTime; // time at which event ripens
bool HasRipened; // flag for deletion
Event *Next;
};
class EventManager
{
public:
EventManager() { Events = NULL; GameTick = 0; }
static void Update()
{
bool update = false;
// Execute each event that is due to ripen
Event *e;
for (e = Events; e; e = e->Next)
{
if (e->RipensBy(GameTick))
{
e->Ripen();
e->HasRipened = true;
update = true;
}
}
// Second pass, delete all ripened events
if (update)
{
Event *next, *prev = NULL;
for (e = Events; e; e = Next)
{
next = e->Next;
if (!e->HasRipened)
prev = e;
else
{
if (prev)
prev->Next = e->Next;
else
events = e->Next;
delete e;
}
}
}
// Increment the game timer
GameTick += TimeManager::GetTicksEllapsedLastUpdate();
}
static void AddEvent(Event *newEvent);
{
// Descend the list until a later event is found
Event *e, *prev = NULL;
for (e = events; e && e->RipensBefore(newEvent); e = e->Next)
prev = e;
// Insert the new event before that event
newEvent->HasRipened = false;
newEvent->Next = e;
if (prev)
prev->Next = newEvent;
else
Events = newEvent;
}
static Tick GetCurrentTime() { return GameTick; }
protected:
static Event *Events;
static Tick GameTick;
};
This could, of course, easily be converted to C (I'd be happy to do so
if anyone desires, it'd take probably another 90 seconds).
Those into design patterns would probably also do the event manager as
a singleton (or perhaps have multiple event managers for different types
of events) rather than using all statics, but I wanted to keep the example
simple.
Adam W.
More information about the mud-dev-archive
mailing list