#!/usr/bin/env dub
/+ dub.sdl:
name "eh_callback_deadline"
dependency "sparkles:event-horizon" path="../../../../.."
platforms "linux"
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
+/
@system:
import (package) corecore.(module) core.timeModule containing core time functionality, such as Duration (which
represents a duration of time) or MonoTime (which represents a
timestamp of the system's monotonic clock).
Various functions take a string (or strings) to represent a unit of time
(e.g. convert!("days", "hours")(numDays)). The valid strings to use
with such functions are "years", "months", "weeks", "days", "hours",
"minutes", "seconds", "msecs" (milliseconds), "usecs" (microseconds),
"hnsecs" (hecto-nanoseconds - i.e. 100 ns) or some subset thereof. There
are a few functions that also allow "nsecs", but very little actually
has precision greater than hnsecs.
Symbol Description Types Duration Represents a duration of time of weeks or less (kept internally as hnsecs). (e.g. 22 days or 700 seconds). TickDuration DEPRECATED Represents a duration of time in system clock ticks, using the highest precision that the system provides. MonoTime Represents a monotonic timestamp in system clock ticks, using the highest precision that the system provides. Functions convert Generic way of converting between two time units. dur Allows constructing a Duration from the given time units with the given length. weeks days hours
minutes seconds msecs
usecs hnsecs nsecs |
Convenience aliases for dur. |
| abs | Returns the absolute value of a duration. |
From Duration
From TickDuration
From units
To Duration tickDuration.to, std,conv!Duration() dur!"msecs"(5) or 5.msecs()
| To TickDuration |
duration.to, std,conv!TickDuration() |
|
TickDuration.from!"msecs"(msecs) |
| To units |
duration.total!"days" |
tickDuration.msecs |
convert!("days", "msecs")(msecs) |
Source
core/time.d
time : msecs, seconds;
import (package) corecore.(package) core.stdcstdc.(module) core.stdc.errnoD header file for C99.
pubs.opengroup.org/onlinepubs/009695399/basedefs/errno.h.html, errno.h
Source
core/stdc/errno.d
errno : (alias constant) eh_callback_deadline.ECANCELED = int core.stdc.errno.ECANCELED = 125ECANCELED;
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) eh_callback_deadline.writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln;
import (package) sparklessparkles.(package) sparkles.event_horizonevent_horizon.(module) sparkles.event_horizon.loopTier A — the callback completion core (SPEC §5): submit(op, callback, ctx)
over one DbI backend. The loop owns the op-slot slab (buffer pinning,
kernel-stable operands, the cancellation state machine) and delivers
completions only inside runOnce — the DEFER_TASKRUN contract made
structural.
The loop is thread-affine and non-copyable: every member must be called from
the owning thread — except Waker.wake() (SPEC §5.6), the one off-thread
door, obtained via waker().
loop : (struct) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)DefaultLoop;
import (package) sparklessparkles.(package) sparkles.event_horizonevent_horizon.(module) sparkles.event_horizon.opPortable operation vocabulary: typed op descriptors, the user_data token
discipline, the op-slot slab with its lifetime state machine, and the
completion shape (SPEC §4). This module is portable — it imports no backend
and never sees an SQE; backend-specific lowering lives in
sparkles.event_horizon.backend.*.
op : (struct) sparkles.event_horizon.op.CompletionWhat a tier-A callback receives. Passed by ref: the callback may
move(done.buf) to keep the buffer; otherwise the loop recycles it to its
origin after the callback returns.
Completion, (struct) sparkles.event_horizon.op.OpHandlePublic, copyable reference to an in-flight op — the target of
cancellation and detach (SPEC §4.2, §5.1).
OpHandle;
struct (struct) eh_callback_deadline.StateState
{
(struct) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)DefaultLoop* (field) @system sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)* eh_callback_deadline.State.looploop;
(struct) sparkles.event_horizon.op.OpHandlePublic, copyable reference to an in-flight op — the target of
cancellation and detach (SPEC §4.2, §5.1).
OpHandle (field) @system sparkles.event_horizon.op.OpHandle eh_callback_deadline.State.operationoperation;
bool (field) @system bool eh_callback_deadline.State.deadlineFireddeadlineFired, (field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen, (field) @system bool eh_callback_deadline.State.cleanedcleaned;
}
void void eh_callback_deadline.cleaned(void* context, ref sparkles.event_horizon.op.Completion done) nothrow @nogc @systemcleaned(void* (parameter) void* contextcontext, ref (struct) sparkles.event_horizon.op.CompletionWhat a tier-A callback receives. Passed by ref: the callback may
move(done.buf) to keep the buffer; otherwise the loop recycles it to its
origin after the callback returns.
Completion (parameter) sparkles.event_horizon.op.Completion donedone) nothrow @nogc
{
auto (local variable) eh_callback_deadline.State* statestate = cast((struct) eh_callback_deadline.StateState*) (parameter) void* contextcontext;
assert((parameter) sparkles.event_horizon.op.Completion donedone.(field) int sparkles.event_horizon.op.Completion.resraw result: >= 0 payload or -errno
res == 0 && (local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen);
(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.cleanedcleaned = true;
}
void void eh_callback_deadline.interrupted(void* context, ref sparkles.event_horizon.op.Completion done) nothrow @nogc @systeminterrupted(void* (parameter) void* contextcontext, ref (struct) sparkles.event_horizon.op.CompletionWhat a tier-A callback receives. Passed by ref: the callback may
move(done.buf) to keep the buffer; otherwise the loop recycles it to its
origin after the callback returns.
Completion (parameter) sparkles.event_horizon.op.Completion donedone) nothrow @nogc
{
auto (local variable) eh_callback_deadline.State* statestate = cast((struct) eh_callback_deadline.StateState*) (parameter) void* contextcontext;
assert((parameter) sparkles.event_horizon.op.Completion donedone.bool sparkles.event_horizon.op.Completion.isFinal() const pure nothrow @nogc @safefalse while a multishot op will post further completions.
isFinal && (parameter) sparkles.event_horizon.op.Completion donedone.(field) int sparkles.event_horizon.op.Completion.resraw result: >= 0 payload or -errno
res == -(constant) int core.stdc.errno.ECANCELED = 125ECANCELED);
assert((local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.deadlineFireddeadlineFired && !(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen);
(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen = true;
assert((local variable) eh_callback_deadline.State* statestate.(field) @system sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)* eh_callback_deadline.State.looploop.expected.Expected!(OpHandle, IoError, NoGcHook) sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).submitAfter(core.time.Duration rel, void function(void* ctx, ref sparkles.event_horizon.op.Completion done) nothrow @nogc cb, void* ctx = null) nothrow @nogc @safeArms a relative timer (in-ring TIMEOUT, SPEC §5.3); the callback
fires with res == 0 on expiry.
submitAfter(5.msecs, &void eh_callback_deadline.cleaned(void* context, ref sparkles.event_horizon.op.Completion done) nothrow @nogc @systemcleaned, (parameter) void* contextcontext).bool expected.Expected!(sparkles.event_horizon.op.OpHandle, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue);
}
void void eh_callback_deadline.deadline(void* context, ref sparkles.event_horizon.op.Completion done) nothrow @nogc @systemdeadline(void* (parameter) void* contextcontext, ref (struct) sparkles.event_horizon.op.CompletionWhat a tier-A callback receives. Passed by ref: the callback may
move(done.buf) to keep the buffer; otherwise the loop recycles it to its
origin after the callback returns.
Completion (parameter) sparkles.event_horizon.op.Completion donedone) nothrow @nogc
{
auto (local variable) eh_callback_deadline.State* statestate = cast((struct) eh_callback_deadline.StateState*) (parameter) void* contextcontext;
assert((parameter) sparkles.event_horizon.op.Completion donedone.(field) int sparkles.event_horizon.op.Completion.resraw result: >= 0 payload or -errno
res == 0 && !(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen);
(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.deadlineFireddeadlineFired = true;
assert(!(local variable) eh_callback_deadline.State* statestate.(field) @system sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)* eh_callback_deadline.State.looploop.expected.Expected!(void, IoError, NoGcHook) sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).cancel(sparkles.event_horizon.op.OpHandle h) nothrow @nogc @safeRequests cancellation — fire-and-forget (SPEC §8.5): the target's own
callback later observes -ECANCELED (or the real result, if completion
won the race). The slot and its pinned buffer stay alive until that
terminal completion, always. Cancelling an already-completed handle is
a no-op, and so is repeating a request.
Guaranteed on a driven loop: a request that cannot be submitted
right now (the one reserved internal cancel slot is busy, or the backend
queue is full) is queued, not refused — the target enters
cancelQueued on the loop's pending set and is retried at every drive
(before the wait, after each dispatch batch, and when the internal
cancel completes). Backpressure is therefore never an error here; the
only failure is a hard backend fault, which reaches the fatal hook.
cancel((local variable) eh_callback_deadline.State* statestate.(field) @system sparkles.event_horizon.op.OpHandle eh_callback_deadline.State.operationoperation).bool expected.Expected!(void, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasError!()() const pure nothrow @nogc @property @safeChecks if Expected has error
hasError);
// cancel() is not completion: context and buffers must remain alive.
assert(!(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen && !(local variable) eh_callback_deadline.State* statestate.(field) @system bool eh_callback_deadline.State.cleanedcleaned);
}
void void D main() @systemmain()
{
(struct) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)DefaultLoop (local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop;
assert(!(struct) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator)DefaultLoop.expected.Expected!(void, IoError, NoGcHook) sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).create(out sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) loop, in sparkles.event_horizon.loop.LoopConfig cfg = LoopConfig(BackendConfig(256u, 0u, cast(ubyte)0u, cast(ubyte)0u), 0u, & defaultFatalHook)) nothrow @nogc @safeOut-parameter factory (SPEC §9.1: IoResult cannot return a
non-copyable owner by value): backend setup → capability probe (the
hard-error semantics of SPEC §3.4) → slab allocation. All-or-nothing.
create((local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop).noreturn sparkles.event_horizon.loop.defaultFatalHook(in sparkles.base.io.errors.IoError why) nothrow @nogc @trustedThe default FatalHook: raw write(2) of a static message plus the
errno, then abort().
hasError, "no completion backend");
scope(exit) (local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop.void sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).destroy() nothrow @nogc @safeStructured teardown; the scope discipline (M5) guarantees the
precondition at higher tiers. An armed waker (SPEC §5.6) is loop
infrastructure, not work — destroy disarms it itself. A queued or
in-flight cancellation is work: its target is live, so the first
precondition already covers the pending set and the reserved slot.
destroy();
(struct) eh_callback_deadline.StateState (local variable) eh_callback_deadline.State statestate = (struct) eh_callback_deadline.StateState(&(local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop);
auto (local variable) expected.Expected!(OpHandle, IoError, NoGcHook) operationoperation = (local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop.expected.Expected!(OpHandle, IoError, NoGcHook) sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).submitAfter(core.time.Duration rel, void function(void* ctx, ref sparkles.event_horizon.op.Completion done) nothrow @nogc cb, void* ctx = null) nothrow @nogc @safeArms a relative timer (in-ring TIMEOUT, SPEC §5.3); the callback
fires with res == 0 on expiry.
submitAfter(10.seconds, &void eh_callback_deadline.interrupted(void* context, ref sparkles.event_horizon.op.Completion done) nothrow @nogc @systeminterrupted, &(local variable) eh_callback_deadline.State statestate);
assert((local variable) expected.Expected!(OpHandle, IoError, NoGcHook) operationoperation.bool expected.Expected!(sparkles.event_horizon.op.OpHandle, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue);
(local variable) eh_callback_deadline.State statestate.(field) @system sparkles.event_horizon.op.OpHandle eh_callback_deadline.State.operationoperation = (local variable) expected.Expected!(OpHandle, IoError, NoGcHook) operationoperation.inout(sparkles.event_horizon.op.OpHandle) expected.Expected!(sparkles.event_horizon.op.OpHandle, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).value!()() inout pure nothrow @nogc @property ref @safeReturns the expected value if there is one.
With default Abort hook, it asserts when there is no value.
It calls hook's onAccessEmptyValue otherwise.
It returns T.init when hook doesn't provide onAccessEmptyValue.
value;
assert((local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop.expected.Expected!(OpHandle, IoError, NoGcHook) sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).submitAfter(core.time.Duration rel, void function(void* ctx, ref sparkles.event_horizon.op.Completion done) nothrow @nogc cb, void* ctx = null) nothrow @nogc @safeArms a relative timer (in-ring TIMEOUT, SPEC §5.3); the callback
fires with res == 0 on expiry.
submitAfter(50.msecs, &void eh_callback_deadline.deadline(void* context, ref sparkles.event_horizon.op.Completion done) nothrow @nogc @systemdeadline, &(local variable) eh_callback_deadline.State statestate).bool expected.Expected!(sparkles.event_horizon.op.OpHandle, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasValue!()() const pure nothrow @nogc @property @safeChecks if Expected has value
hasValue);
assert(!(local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop.expected.Expected!(void, IoError, NoGcHook) sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).run() nothrow @nogc @safeRuns until stop() or until drained (no live user/timer ops — an
armed waker alone does not keep ``run() alive; SPEC §5.6).
run().bool expected.Expected!(void, sparkles.base.io.errors.IoError, sparkles.base.text.errors.NoGcHook).hasError!()() const pure nothrow @nogc @property @safeChecks if Expected has error
hasError);
assert((local variable) sparkles.event_horizon.loop.EventLoop!(UringBackend, Mallocator) looploop.uint sparkles.event_horizon.loop.EventLoop!(sparkles.event_horizon.backend.uring.UringBackend, std.experimental.allocator.mallocator.Mallocator).inFlight() const pure nothrow @nogc @safeUser and timer ops currently in flight (an armed waker is excluded —
infrastructure, not work; SPEC §5.6).
inFlight == 0 && (local variable) eh_callback_deadline.State statestate.(field) @system bool eh_callback_deadline.State.terminalSeenterminalSeen && (local variable) eh_callback_deadline.State statestate.(field) @system bool eh_callback_deadline.State.cleanedcleaned);
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("sleep returned: ECANCELED");
void std.stdio.writeln!(string, bool)(string __param_0, bool __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("timed out: ", (local variable) eh_callback_deadline.State statestate.(field) @system bool eh_callback_deadline.State.deadlineFireddeadlineFired);
void std.stdio.writeln!(string, bool)(string __param_0, bool __param_1) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("cleaned up: ", (local variable) eh_callback_deadline.State statestate.(field) @system bool eh_callback_deadline.State.cleanedcleaned);
}