Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1018 lines
25 KiB
C++
1018 lines
25 KiB
C++
//===========================================================================//
|
|
// File: event.cc //
|
|
// Project: MUNGA Brick: Event Manager //
|
|
// Contents: implementation details of event processing //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 10/19/94 JMA Initial coding. //
|
|
// 11/03/94 ECH Made compatible with BC4.0 //
|
|
// 11/05/94 JMA Made compatible with GNU C++ //
|
|
// 11/30/94 JMA Adapted to new style conventions //
|
|
// 12/01/94 JMA Made compatible with SGI CC //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994, Virtual World Entertainment, Inc. All Rights reserved //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "AdeptHeaders.hpp"
|
|
|
|
#include "EventStatistics.hpp"
|
|
#include "Network.hpp"
|
|
|
|
//#############################################################################
|
|
//########################### AbstractEvent #############################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent::AbstractEvent(
|
|
ClassData *class_data,
|
|
const Receiver::Message *message,
|
|
Time time
|
|
):
|
|
Plug(class_data)
|
|
{
|
|
Verify(message);
|
|
alarmTime = time;
|
|
|
|
//
|
|
//--------------------------------------------------------
|
|
// Allocate some memory to store the message parameters in
|
|
//--------------------------------------------------------
|
|
//
|
|
size_t long_size = (message->messageLength+3)>>2;
|
|
messageToSend = Cast_Pointer(Receiver::Message*, new long[long_size]);
|
|
Register_Object(messageToSend);
|
|
|
|
Mem_Copy(
|
|
messageToSend,
|
|
message,
|
|
message->messageLength,
|
|
long_size*sizeof(long)
|
|
);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent::~AbstractEvent()
|
|
{
|
|
if (messageToSend)
|
|
{
|
|
Unregister_Pointer(messageToSend);
|
|
delete messageToSend;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
AbstractEvent::Process()
|
|
{
|
|
STOP(("AbstractEvent::Process should not be called!\n"));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
AbstractEvent::DumpData()
|
|
{
|
|
STOP(("AbstractEvent::DumpData should not be called!\n"));
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################### Event #################################
|
|
//#############################################################################
|
|
|
|
MemoryBlock*
|
|
Event::AllocatedMemory = NULL;
|
|
Event::ClassData*
|
|
Event::DefaultData = NULL;
|
|
|
|
static DWORD
|
|
Event_Count;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Event::InitializeClass(
|
|
size_t block_count,
|
|
size_t block_delta
|
|
)
|
|
{
|
|
Verify(!AllocatedMemory);
|
|
AllocatedMemory =
|
|
new MemoryBlock(
|
|
sizeof(Event),
|
|
block_count,
|
|
block_delta,
|
|
"Event",
|
|
g_LibraryHeap
|
|
);
|
|
Register_Object(AllocatedMemory);
|
|
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
EventClassID,
|
|
"Adept::Event",
|
|
AbstractEvent::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
|
|
Event_Count = 0;
|
|
#if !defined(NO_STATS)
|
|
AddStatistic("Queued Events", "events", gos_DWORD, &Event_Count, 0);
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Event::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
|
|
Unregister_Object(AllocatedMemory);
|
|
delete AllocatedMemory;
|
|
AllocatedMemory = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Event::Event(
|
|
Receiver *target,
|
|
const Receiver::Message *message,
|
|
Time time
|
|
):
|
|
AbstractEvent(DefaultData, message, time)
|
|
{
|
|
targetReceiver.Add(target);
|
|
Set_Statistic(Event_Count, Event_Count+1);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Event::~Event()
|
|
{
|
|
Set_Statistic(Event_Count, Event_Count-1);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Event::Repost(
|
|
EventQueue* queue,
|
|
Time new_time
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(queue);
|
|
|
|
//
|
|
//-------------------------------------------
|
|
// Delete the link to the current event queue
|
|
//-------------------------------------------
|
|
//
|
|
STOP(("Not functional"));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Event::Process()
|
|
{
|
|
Check_Object(this);
|
|
Receiver *target = targetReceiver.GetCurrent();
|
|
if (target)
|
|
{
|
|
Check_Object(target);
|
|
target->Receive(this);
|
|
}
|
|
else
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Event::DumpData()
|
|
{
|
|
Check_Object(this);
|
|
#if defined(_ARMOR)
|
|
Receiver *target = targetReceiver.GetCurrent();
|
|
if (target)
|
|
{
|
|
Check_Object(target);
|
|
Receiver::ClassData *class_data = target->GetClassData();
|
|
Check_Object(class_data);
|
|
const Receiver::MessageEntry *entry =
|
|
target->GetMessageEntry(messageToSend->messageID);
|
|
Check_Object(entry);
|
|
Check_Pointer(entry->messageName);
|
|
SPEW((
|
|
GROUP_ADEPT_EVENT,
|
|
"%s::%s",
|
|
class_data->GetClassName(),
|
|
entry->messageName
|
|
));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Event::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//#############################################################################
|
|
//########################### NetworkEvent ##############################
|
|
//#############################################################################
|
|
|
|
NetworkEvent::ClassData*
|
|
NetworkEvent::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NetworkEvent::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
NetworkEventClassID,
|
|
"Adept::NetworkEvent",
|
|
AbstractEvent::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NetworkEvent::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NetworkEvent::NetworkEvent(
|
|
Connection *connection,
|
|
InBox *box,
|
|
EventStyle event_style,
|
|
const Receiver::Message *message,
|
|
Time time
|
|
):
|
|
AbstractEvent(DefaultData, message, time)
|
|
{
|
|
eventConnection = connection;
|
|
eventBox = box;
|
|
eventStyle = event_style;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NetworkEvent::~NetworkEvent()
|
|
{
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NetworkEvent::Process()
|
|
{
|
|
Check_Object(this);
|
|
switch (eventStyle)
|
|
{
|
|
case SendStyle:
|
|
Check_Object(Network::GetInstance());
|
|
STOP(("Not implemented"));
|
|
// Network::GetInstance()->Send(messageToSend, hostID);
|
|
break;
|
|
|
|
case BroadcastStyle:
|
|
Check_Object(Network::GetInstance());
|
|
Network::GetInstance()->Broadcast(messageToSend);
|
|
break;
|
|
|
|
case ExclusiveBroadcastStyle:
|
|
Check_Object(Network::GetInstance());
|
|
Network::GetInstance()->ExclusiveBroadcast(messageToSend);
|
|
break;
|
|
}
|
|
|
|
Unregister_Object(this);
|
|
delete this;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
NetworkEvent::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//#############################################################################
|
|
//####################### GeneralEventQueue ############################
|
|
//#############################################################################
|
|
|
|
//
|
|
// Shared Data Support
|
|
//
|
|
GeneralEventQueue::ClassData*
|
|
GeneralEventQueue::DefaultData = NULL;
|
|
|
|
GeneralEventQueue*
|
|
GeneralEventQueue::Instance = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void GeneralEventQueue::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
GeneralEventQueueClassID,
|
|
"Adept::GeneralEventQueue",
|
|
Plug::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void GeneralEventQueue::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
GeneralEventQueue::GeneralEventQueue(ClassData *class_data):
|
|
Plug(class_data)
|
|
{
|
|
priorityLevels = -1;
|
|
eventCount = 0;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
GeneralEventQueue::~GeneralEventQueue()
|
|
{
|
|
pendingEvents.DeletePlugs();
|
|
timedEvents.DeletePlugs();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
GeneralEventQueue*
|
|
GeneralEventQueue::Make(
|
|
int priorities,
|
|
const char* count_trace_name,
|
|
const char* delay_trace_name
|
|
)
|
|
{
|
|
gos_PushCurrentHeap(g_Heap);
|
|
GeneralEventQueue *queue = new GeneralEventQueue[priorities];
|
|
Register_Object(queue);
|
|
|
|
queue->priorityLevels = priorities;
|
|
gos_PopCurrentHeap();
|
|
return queue;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent*
|
|
GeneralEventQueue::Post(
|
|
Receiver *target,
|
|
const Receiver::Message *message,
|
|
Time time
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(target);
|
|
Check_Object(message);
|
|
|
|
//
|
|
//------------------------------------------------------
|
|
// Create a new event, then insert it in the event queue
|
|
//------------------------------------------------------
|
|
//
|
|
Event *event = new Event(target, message, time);
|
|
Register_Object(event);
|
|
|
|
Enqueue(event);
|
|
return event;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent*
|
|
GeneralEventQueue::SendEvent(
|
|
Connection *connection,
|
|
InBox *box,
|
|
const Receiver::Message *message,
|
|
Time when
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
NetworkEvent *event =
|
|
new NetworkEvent(
|
|
connection,
|
|
box,
|
|
NetworkEvent::SendStyle,
|
|
message,
|
|
when
|
|
);
|
|
Register_Object(event);
|
|
Enqueue(event);
|
|
return event;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent*
|
|
GeneralEventQueue::BroadcastEvent(
|
|
InBox *box,
|
|
const Receiver::Message *message,
|
|
Time when
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
//
|
|
// HACK - What is a null network address?
|
|
//
|
|
NetworkEvent *event =
|
|
new NetworkEvent(
|
|
NULL,
|
|
box,
|
|
NetworkEvent::BroadcastStyle,
|
|
message,
|
|
when
|
|
);
|
|
Register_Object(event);
|
|
Enqueue(event);
|
|
return event;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent*
|
|
GeneralEventQueue::ExclusiveBroadcastEvent(
|
|
InBox *box,
|
|
const Receiver::Message *message,
|
|
Time when
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message);
|
|
|
|
//
|
|
// HACK - What is a null network address?
|
|
//
|
|
NetworkEvent *event =
|
|
new NetworkEvent(
|
|
NULL,
|
|
box,
|
|
NetworkEvent::ExclusiveBroadcastStyle,
|
|
message,
|
|
when
|
|
);
|
|
Register_Object(event);
|
|
Enqueue(event);
|
|
return event;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
GeneralEventQueue::Enqueue(AbstractEvent *event)
|
|
{
|
|
Check_Object(event);
|
|
Check_Pointer(event->messageToSend);
|
|
int priority = event->messageToSend->messagePriority;
|
|
Verify(static_cast<unsigned>(priority) < priorityLevels);
|
|
|
|
//
|
|
//------------------------------------------------------------
|
|
// If this is not a timed event, stuff it in the pending queue
|
|
//------------------------------------------------------------
|
|
//
|
|
if (event->alarmTime == -1.0)
|
|
{
|
|
this[priority].pendingEvents.Add(event);
|
|
}
|
|
|
|
//
|
|
//----------------------------------------
|
|
// Otherwise, sort it into the timed queue
|
|
//----------------------------------------
|
|
//
|
|
else
|
|
{
|
|
ChainIteratorOf<AbstractEvent*>
|
|
timed_events(&this[priority].timedEvents);
|
|
timed_events.Last();
|
|
AbstractEvent* next_event = timed_events.GetCurrent();
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// If the timed queue is empty, or if we are later than the last entry,
|
|
// just add the event to the end
|
|
//---------------------------------------------------------------------
|
|
//
|
|
if (!next_event || next_event->alarmTime <= event->alarmTime)
|
|
{
|
|
this[priority].timedEvents.Add(event);
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Find the event to insert before. If we run off the beginning, stop
|
|
// checking and set the iterator to the first event in the queue
|
|
//--------------------------------------------------------------------
|
|
//
|
|
else
|
|
{
|
|
do
|
|
{
|
|
timed_events.Previous();
|
|
next_event = timed_events.GetCurrent();
|
|
if (!next_event)
|
|
{
|
|
timed_events.First();
|
|
break;
|
|
}
|
|
} while (next_event->alarmTime > event->alarmTime);
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// If we didn't run off the queue, we need to insert after the current
|
|
// event, so bump the iterator forward one event
|
|
//--------------------------------------------------------------------
|
|
//
|
|
if (next_event)
|
|
{
|
|
timed_events.Next();
|
|
}
|
|
|
|
//
|
|
//------------------------------------------------------------------
|
|
// Insert the new event ahead of where the iterator currently points
|
|
//------------------------------------------------------------------
|
|
//
|
|
timed_events.Insert(event);
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
AbstractEvent*
|
|
GeneralEventQueue::PeekAtNextEvent(int min_priority)
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// Start at the top of the priority queue, searching backwards until we find
|
|
// an available event or run off the minimum queue priority
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
Verify(min_priority >= 0);
|
|
int priority = priorityLevels;
|
|
while (--priority >= min_priority)
|
|
{
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// See if the first event in the timed queue is ready to go. If not,
|
|
// none of the other timed events will be ready to go either
|
|
//-------------------------------------------------------------------
|
|
//
|
|
ChainIteratorOf<AbstractEvent*>
|
|
timed_events(&this[priority].timedEvents);
|
|
AbstractEvent
|
|
*event = timed_events.GetCurrent();
|
|
if (event)
|
|
{
|
|
Check_Object(event);
|
|
if (event->alarmTime <= gos_GetElapsedTime())
|
|
{
|
|
return event;
|
|
}
|
|
}
|
|
|
|
//
|
|
//------------------------------
|
|
// Now look in the untimed queue
|
|
//------------------------------
|
|
//
|
|
ChainIteratorOf<AbstractEvent*>
|
|
events(&this[priority].pendingEvents);
|
|
event = events.GetCurrent();
|
|
if (event)
|
|
{
|
|
Check_Object(event);
|
|
return event;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
GeneralEventQueue::IsPriorityEmpty(int priority)
|
|
{
|
|
Check_Object(this);
|
|
|
|
Verify(priority >= 0 && priority < priorityLevels);
|
|
ChainIteratorOf<AbstractEvent*> i(&this[priority].pendingEvents);
|
|
ChainIteratorOf<AbstractEvent*> j(&this[priority].timedEvents);
|
|
return !i.GetCurrent() && !j.GetCurrent();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
GeneralEventQueue::ProcessOneEvent(int min_priority)
|
|
{
|
|
Check_Object(this);
|
|
Verify(min_priority >= 0);
|
|
|
|
AbstractEvent *event=PeekAtNextEvent(min_priority);
|
|
if (event)
|
|
{
|
|
event->Process();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
GeneralEventQueue::ProcessAllEvents(int min_priority)
|
|
{
|
|
Check_Object(this);
|
|
Verify(min_priority >= 0);
|
|
while (ProcessOneEvent(min_priority));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
GeneralEventQueue::FlushAllEvents(int max_priority)
|
|
{
|
|
Check_Object(this);
|
|
Verify(max_priority < priorityLevels);
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Make sure that max_priority is set right
|
|
//-----------------------------------------
|
|
//
|
|
if (max_priority < 0)
|
|
{
|
|
max_priority = priorityLevels - 1;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Step through each of the priority queues and delete any events found
|
|
// within
|
|
//---------------------------------------------------------------------
|
|
//
|
|
for (int priority=max_priority; priority>=0; --priority)
|
|
{
|
|
|
|
//
|
|
//---------------------------------------
|
|
// Delete the events from the timed queue
|
|
//---------------------------------------
|
|
//
|
|
ChainIteratorOf<AbstractEvent*> i(&this[priority].timedEvents);
|
|
AbstractEvent *event;
|
|
while ((event = i.ReadAndNext()) != NULL)
|
|
{
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Delete the events from the regular queue
|
|
//-----------------------------------------
|
|
//
|
|
ChainIteratorOf<AbstractEvent*> j(&this[priority].pendingEvents);
|
|
while ((event = j.ReadAndNext()) != NULL)
|
|
{
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
GeneralEventQueue::FlushMatchingEvents(
|
|
Receiver::MessageID target_message,
|
|
int max_priority
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Verify(max_priority < priorityLevels);
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Make sure that max_priority is set right
|
|
//-----------------------------------------
|
|
//
|
|
if (max_priority < 0)
|
|
{
|
|
max_priority = priorityLevels - 1;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Step through each of the priority queues and delete any events found
|
|
// within
|
|
//---------------------------------------------------------------------
|
|
//
|
|
for (int p=max_priority; p>=0; --p)
|
|
{
|
|
//
|
|
//-------------------------------------------
|
|
// Delete events from the regular queue first
|
|
//-------------------------------------------
|
|
//
|
|
ChainIteratorOf<AbstractEvent*> i(&this[p].pendingEvents);
|
|
AbstractEvent *event;
|
|
while ((event = i.ReadAndNext()) != NULL)
|
|
{
|
|
|
|
//
|
|
//------------------------------
|
|
// Make sure the message matches
|
|
//------------------------------
|
|
//
|
|
if (
|
|
target_message == Receiver::AnyMessageID
|
|
|| target_message == event->messageToSend->messageID
|
|
)
|
|
{
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
}
|
|
|
|
//
|
|
//-----------------------------------
|
|
// Delete events from the timed queue
|
|
//-----------------------------------
|
|
//
|
|
ChainIteratorOf<AbstractEvent*> j(&this[p].timedEvents);
|
|
while ((event = j.ReadAndNext()) != NULL)
|
|
{
|
|
|
|
//
|
|
//------------------------------
|
|
// Make sure the message matches
|
|
//------------------------------
|
|
//
|
|
if (
|
|
target_message == Receiver::AnyMessageID
|
|
|| target_message == event->messageToSend->messageID
|
|
)
|
|
{
|
|
Unregister_Object(event);
|
|
delete event;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
GeneralEventQueue::DumpEventQueue()
|
|
{
|
|
Check_Object(this);
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Step through each of the priority queues and display any events found
|
|
// within
|
|
//----------------------------------------------------------------------
|
|
//
|
|
unsigned total_count = 0;
|
|
for (int priority=priorityLevels - 1; priority>=0; --priority)
|
|
{
|
|
SPEW((GROUP_ADEPT_EVENT, "EventQueue priority %d", priority));
|
|
SPEW((
|
|
GROUP_ADEPT_EVENT,
|
|
"--------------------------------------------------------------"
|
|
));
|
|
|
|
ChainIteratorOf<AbstractEvent*> i(&this[priority].pendingEvents);
|
|
AbstractEvent *event;
|
|
size_t count=0;
|
|
while ((event = i.ReadAndNext()) != NULL)
|
|
{
|
|
++count;
|
|
event->DumpData();
|
|
}
|
|
SPEW((
|
|
GROUP_ADEPT_EVENT,
|
|
"%d priority %d events",
|
|
count,
|
|
priority
|
|
));
|
|
count = 0;
|
|
ChainIteratorOf<AbstractEvent*> j(&this[priority].timedEvents);
|
|
while ((event = j.ReadAndNext()) != NULL)
|
|
{
|
|
++count;
|
|
event->DumpData();
|
|
}
|
|
SPEW((
|
|
GROUP_ADEPT_EVENT,
|
|
"%d priority %d timed events",
|
|
count,
|
|
priority
|
|
));
|
|
total_count += count;
|
|
|
|
}
|
|
SPEW((
|
|
GROUP_ADEPT_EVENT, "%d total events in queues", total_count));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
GeneralEventQueue::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//#############################################################################
|
|
//############################ EventQueue ###############################
|
|
//#############################################################################
|
|
|
|
//
|
|
// Shared Data Support
|
|
//
|
|
EventQueue::ClassData*
|
|
EventQueue::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
EventQueue::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
DefaultData =
|
|
new ClassData(
|
|
EventQueueClassID,
|
|
"Adept::EventQueue",
|
|
GeneralEventQueue::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
EventQueue::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EventQueue::EventQueue():
|
|
GeneralEventQueue(DefaultData)
|
|
{
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EventQueue::~EventQueue()
|
|
{
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
EventQueue*
|
|
EventQueue::Make(
|
|
int priorities,
|
|
const char* trace_name,
|
|
const char* delay_trace_name
|
|
)
|
|
{
|
|
gos_PushCurrentHeap(g_Heap);
|
|
EventQueue *queue = new EventQueue[priorities];
|
|
Register_Object(queue);
|
|
|
|
queue->priorityLevels = priorities;
|
|
gos_PopCurrentHeap();
|
|
return queue;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
EventQueue::ProcessMatchingEvents(
|
|
Receiver *receiver,
|
|
Receiver::MessageID message_ID
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(receiver);
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// Step through each of the priority queues and process any events
|
|
// found within
|
|
//----------------------------------------------------------------
|
|
//
|
|
for (int p=priorityLevels-1; p>=0; --p)
|
|
{
|
|
Event *event;
|
|
AbstractEvent *abstract_event;
|
|
ChainIteratorOf<AbstractEvent*> i(&this[p].pendingEvents);
|
|
while ((abstract_event = i.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(abstract_event);
|
|
event = Cast_Object(Event*, abstract_event);
|
|
|
|
//
|
|
//------------------------------
|
|
// Make sure the message matches
|
|
//------------------------------
|
|
//
|
|
if (
|
|
(event->targetReceiver.GetCurrent() == receiver) &&
|
|
(message_ID == Receiver::AnyMessageID ||
|
|
message_ID == event->messageToSend->messageID)
|
|
)
|
|
{
|
|
event->Process();
|
|
}
|
|
}
|
|
|
|
ChainIteratorOf<AbstractEvent*> j(&this[p].timedEvents);
|
|
while ((abstract_event = j.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(abstract_event);
|
|
event = Cast_Object(Event*, abstract_event);
|
|
|
|
//
|
|
//------------------------------
|
|
// Make sure the message matches
|
|
//------------------------------
|
|
//
|
|
if (
|
|
(event->targetReceiver.GetCurrent() == receiver) &&
|
|
(message_ID == Receiver::AnyMessageID ||
|
|
message_ID == event->messageToSend->messageID)
|
|
)
|
|
{
|
|
event->Process();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
EventQueue::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|