Initial version with sone partial Posix implementations.

This commit is contained in:
Sönke Ludwig 2016-01-11 21:33:49 +01:00
commit 2a926d87aa
13 changed files with 1566 additions and 0 deletions

162
source/eventcore/driver.d Normal file
View 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;