mirror of https://github.com/deavmi/eventy.git
181 lines
3.3 KiB
D
181 lines
3.3 KiB
D
module eventy;
|
|
|
|
import core.thread : Thread;
|
|
import std.container.dlist : DList;
|
|
import core.sync.mutex : Mutex;
|
|
|
|
public class EventManager : Thread
|
|
{
|
|
/* List of signals than we can expect */
|
|
private Signal[] signals;
|
|
private Mutex signalMutex;
|
|
|
|
/* Recieved signals */
|
|
private DList!(ulong) signalInbox;
|
|
private Mutex signalInboxMutex;
|
|
|
|
this()
|
|
{
|
|
/* Initialize the signal queue */
|
|
}
|
|
|
|
/**
|
|
* Event loop
|
|
*/
|
|
private void eventLoop()
|
|
{
|
|
while(true)
|
|
{
|
|
/* Whether or not there is anything to process */
|
|
bool isEmpty;
|
|
|
|
/* The signal ID to be processed */
|
|
ulong currentID;
|
|
|
|
/* Lock the signal inbox */
|
|
signalInboxMutex.lock();
|
|
|
|
/* Check whether or not it is empty */
|
|
isEmpty = signalInbox.empty();
|
|
|
|
/* If it is not empty then dequeue a signal */
|
|
if(!isEmpty)
|
|
{
|
|
currentID = signalInbox.front();
|
|
signalInbox.removeFront(1);
|
|
}
|
|
|
|
/* Unlock the signal inbox */
|
|
signalInboxMutex.unlock();
|
|
|
|
/* Only process if we got something */
|
|
if(!isEmpty)
|
|
{
|
|
/* Find the matching Signal */
|
|
Signal matchingSignal = findSignal(currentID);
|
|
|
|
/* Get the Signal's Event(s) */
|
|
Event[] signalHandlers = matchingSignal.getEvents();
|
|
|
|
/* Dispatch all events */
|
|
foreach(Event signalHandler; signalHandlers)
|
|
{
|
|
/* Dispatch the current signal handler */
|
|
signalHandler.run();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Attach a new Signal to the event loop that
|
|
* can then be triggered with signal(ulong id)
|
|
*/
|
|
public void attachSignal(Signal signal)
|
|
{
|
|
|
|
}
|
|
|
|
private Signal findSignal(ulong id)
|
|
{
|
|
/* The matching Signal */
|
|
Signal matchingSignal;
|
|
|
|
/* Lock the signal registry */
|
|
signalMutex.lock();
|
|
|
|
/* Find the matching Signal */
|
|
foreach(Signal signal; signals)
|
|
{
|
|
if(signal.getID() == id)
|
|
{
|
|
matchingSignal = signal;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Unllcok the signal registry */
|
|
signalMutex.unlock();
|
|
|
|
return matchingSignal;
|
|
}
|
|
|
|
/*
|
|
* Sends a signal by putting it in the signal queue
|
|
*
|
|
*/
|
|
public void signal(ulong id)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Signal
|
|
*
|
|
* A signal is associates a unique number (used to trigger
|
|
* the signal) with an event to be run on reception of the
|
|
* signal
|
|
*/
|
|
public final class Signal
|
|
{
|
|
/* The Event to trigger on reception of this signal */
|
|
private Event[] triggerEvents;
|
|
|
|
/* Unique signal ID */
|
|
private ulong ID;
|
|
|
|
/* Get the events */
|
|
public Event[] getEvents()
|
|
{
|
|
return triggerEvents;
|
|
}
|
|
|
|
/* Get this Signal's unique identifier */
|
|
public ulong getID()
|
|
{
|
|
return ID;
|
|
}
|
|
}
|
|
|
|
public final class Event
|
|
{
|
|
/* The function to call when this event is ran */
|
|
private void function() handler;
|
|
|
|
/* Whether or not a new thread should be spwaned for running this event */
|
|
private bool spawnThread;
|
|
|
|
/**
|
|
* Constructs a new Event with the given function to be
|
|
* run, `handler`, and whether or not a new thread should
|
|
* be spawned to run the handler, `spawnThread`, which
|
|
* is `false` by default
|
|
*/
|
|
this(void function() handler, bool spawnThread = false)
|
|
{
|
|
this.handler = handler;
|
|
|
|
/* TODO: Handle `spwanThread` = true */
|
|
this.spawnThread = spawnThread;
|
|
}
|
|
|
|
public void run()
|
|
{
|
|
/* Call on this thread if spawnThread = false */
|
|
if(!spawnThread)
|
|
{
|
|
handler();
|
|
}
|
|
/* Call on a new thread if spawnThread = true */
|
|
else
|
|
{
|
|
/* Create the new thread with the handler function */
|
|
Thread eventHandlerThread = new Thread(handler);
|
|
|
|
/* Start the thread */
|
|
eventHandlerThread.start();
|
|
}
|
|
|
|
}
|
|
} |