Initial version with sone partial Posix implementations.
This commit is contained in:
commit
2a926d87aa
13 changed files with 1566 additions and 0 deletions
162
source/eventcore/driver.d
Normal file
162
source/eventcore/driver.d
Normal file
|
@ -0,0 +1,162 @@
|
|||
module eventcore.driver;
|
||||
@safe: /*@nogc:*/ nothrow:
|
||||
|
||||
import core.time : Duration;
|
||||
import std.socket : Address;
|
||||
|
||||
|
||||
interface EventDriver {
|
||||
@safe: /*@nogc:*/ nothrow:
|
||||
//
|
||||
// General functionality
|
||||
//
|
||||
|
||||
/// Releases all resources associated with the driver
|
||||
void dispose();
|
||||
|
||||
/**
|
||||
The number of pending callbacks.
|
||||
|
||||
When this number drops to zero, the event loop can safely be quit. It is
|
||||
guaranteed that no callbacks will be made anymore, unless new callbacks
|
||||
get registered.
|
||||
*/
|
||||
size_t waiterCount();
|
||||
|
||||
/**
|
||||
Runs the event loop to process a chunk of events.
|
||||
|
||||
This method optionally waits for an event to arrive if none are present
|
||||
in the event queue. The function will return after either the specified
|
||||
timeout has elapsed, or once the event queue has been fully emptied.
|
||||
|
||||
Params:
|
||||
timeout = Maximum amount of time to wait for an event. A duration of
|
||||
zero will cause the function to only process pending events. The
|
||||
the default duration of `Duration.max`, if necessary, will wait
|
||||
indefinitely until an event arrives.
|
||||
*/
|
||||
void processEvents(Duration timeout = Duration.max);
|
||||
|
||||
//
|
||||
// TCP
|
||||
//
|
||||
StreamSocketFD connectStream(scope Address peer_address, ConnectCallback on_connect);
|
||||
StreamListenSocketFD listenStream(scope Address bind_address, AcceptCallback on_accept);
|
||||
void waitForConnections(StreamListenSocketFD sock, AcceptCallback on_accept);
|
||||
|
||||
void setTCPNoDelay(StreamSocketFD socket, bool enable);
|
||||
void readSocket(StreamSocketFD socket, ubyte[] buffer, IOCallback on_read_finish, IOMode mode = IOMode.once);
|
||||
void writeSocket(StreamSocketFD socket, const(ubyte)[] buffer, IOCallback on_write_finish, IOMode mode = IOMode.once);
|
||||
void waitSocketData(StreamSocketFD socket, IOCallback on_data_available);
|
||||
void shutdownSocket(StreamSocketFD socket, bool shut_read = true, bool shut_write = true);
|
||||
|
||||
//
|
||||
// Manual events
|
||||
//
|
||||
EventID createEvent();
|
||||
void triggerEvent(EventID event, bool notify_all = true);
|
||||
EventWaitID waitForEvent(EventID event, EventCallback on_event);
|
||||
void stopWaitingForEvent(EventID event, EventWaitID wait_id);
|
||||
|
||||
//
|
||||
// Timers
|
||||
//
|
||||
TimerID createTimer(TimerCallback callback);
|
||||
void setTimer(TimerID timer, Duration timeout, Duration repeat = Duration.zero);
|
||||
void stopTimer(TimerID timer);
|
||||
bool isTimerPending(TimerID timer);
|
||||
bool isTimerPeriodic(TimerID timer);
|
||||
|
||||
//
|
||||
// Resource ownership
|
||||
//
|
||||
|
||||
/**
|
||||
Increments the reference count of the given resource.
|
||||
*/
|
||||
void addRef(SocketFD descriptor);
|
||||
/// ditto
|
||||
void addRef(FileFD descriptor);
|
||||
/// ditto
|
||||
void addRef(TimerID descriptor);
|
||||
/// ditto
|
||||
void addRef(EventID descriptor);
|
||||
|
||||
/**
|
||||
Decrements the reference count of the given resource.
|
||||
|
||||
Once the reference count reaches zero, all associated resources will be
|
||||
freed and the descriptor gets invalidated.
|
||||
*/
|
||||
void releaseRef(SocketFD descriptor);
|
||||
/// ditto
|
||||
void releaseRef(FileFD descriptor);
|
||||
/// ditto
|
||||
void releaseRef(TimerID descriptor);
|
||||
/// ditto
|
||||
void releaseRef(EventID descriptor);
|
||||
}
|
||||
|
||||
|
||||
alias ConnectCallback = void delegate(StreamSocketFD, ConnectStatus);
|
||||
alias AcceptCallback = void delegate(StreamListenSocketFD, StreamSocketFD);
|
||||
alias IOCallback = void delegate(StreamSocketFD, IOStatus, size_t);
|
||||
alias EventCallback = void delegate(EventID);
|
||||
alias TimerCallback = void delegate(TimerID);
|
||||
|
||||
enum ConnectStatus {
|
||||
connected,
|
||||
refused,
|
||||
timeout,
|
||||
bindFailure,
|
||||
unknownError
|
||||
}
|
||||
|
||||
enum IOMode {
|
||||
immediate, /// Process only as much as possible without waiting
|
||||
once, /// Process as much as possible with a single call
|
||||
all /// Process the full buffer
|
||||
}
|
||||
|
||||
|
||||
enum IOStatus {
|
||||
ok, /// The data has been transferred normally
|
||||
disconnected, /// The connection was closed before all data could be transterred
|
||||
error, /// An error occured while transferring the data
|
||||
wouldBlock /// Returned for `IOMode.immediate` when no data is readily readable/writable
|
||||
}
|
||||
|
||||
struct Handle(T, T invalid_value = T.init, int MAGIC = __LINE__) {
|
||||
static if (is(T : Handle!(V, M), V, int M)) alias BaseType = T.BaseType;
|
||||
else alias BaseType = T;
|
||||
|
||||
enum invalid = Handle.init;
|
||||
|
||||
T value = invalid_value;
|
||||
|
||||
this(BaseType value) { this.value = T(value); }
|
||||
|
||||
U opCast(U : Handle!(V, M), V, int M)() {
|
||||
// TODO: verify that U derives from typeof(this)!
|
||||
return U(value);
|
||||
}
|
||||
|
||||
U opCast(U : BaseType)()
|
||||
{
|
||||
return cast(U)value;
|
||||
}
|
||||
|
||||
alias value this;
|
||||
}
|
||||
|
||||
alias FD = Handle!(int, -1);
|
||||
alias SocketFD = Handle!FD;
|
||||
alias StreamSocketFD = Handle!SocketFD;
|
||||
alias StreamListenSocketFD = Handle!SocketFD;
|
||||
alias FileFD = Handle!FD;
|
||||
|
||||
alias TimerID = Handle!int;
|
||||
alias EventID = Handle!int;
|
||||
alias EventWaitID = Handle!int;
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue