#!/usr/bin/env dub
/+ dub.sdl:
name "vibe_deadline"
dependency "vibe-core" version="2.14.0"
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
platforms "linux"
+/
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) 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) vibe_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) vibevibe.(package) vibe.corecore.(module) vibe.core.coreThis module contains the core functionality of the vibe.d framework.
core : (alias template) vibe_deadline.runTask = vibe.core.core.runTask(ARGS...)(void delegate(ARGS) nothrow @safe task, auto ref ARGS args)Runs a new asynchronous task.
task will be called synchronously from within the vibeRunTask call. It will
continue to run until vibeYield() or any of the I/O or wait functions is
called.
Note that the maximum size of all args must not exceed maxTaskParameterSize.
runTask, (alias) vibe_deadline.setTimer = vibe.core.core.Timer vibe.core.core.setTimer(core.time.Duration timeout, void delegate() nothrow @safe callback, bool periodic = false) nothrow @safeCreates a new timer, that will fire callback after timeout
Timers can be be separated into two categories: one-off or periodic.
One-off timers fire only once, after a specific amount of time,
while periodic timer fire at a regular interval.
One-off_timers:
One-off timers can be used for performing a task after a specific delay,
or to schedule a time without interrupting the currently running code.
For example, the following is a way to emulate a 'schedule' primitive,
a way to schedule a task without starting it immediately (unlike runTask):
void handleRequest (scope HTTPServerRequest req, scope HTTPServerResponse res) {
Payload payload = parse(req);
if (payload.isValid())
// Don't immediately yield, finish processing the data and the query
setTimer(0.msecs, () => sendToPeers(payload));
process(payload);
res.writeVoidBody();
}
In this example, the server delays the network communication that
will be performed by sendToPeers until after the request is fully
processed, ensuring the client doesn't wait more than the actual processing
time for the response.
Periodic timers
Periodic timers will trigger for the first time after timeout,
then at best every timeout period after this. Periodic timers may be
explicitly stopped by calling the Timer.stop() method on the return value
of this function.
As timer are non-preemtive (see the "Preemption" section), user code does
not need to compensate for time drift, as the time spent in the function
will not affect the frequency, unless the function takes longer to complete
than the timer.
Preemption
Like other events in Vibe.d, timers are non-preemptive, meaning that
the currently executing function will not be interrupted to let a timer run.
This is usually not a problem in server applications, as any blocking code
will be easily noticed (the server will stop to handle requests), but might
come at a surprise in code that doesn't handle request.
If this is a problem, the solution is usually to either explicitly give
control to the event loop (by calling yield) or ensuring operations are
asynchronous (e.g. call functions from vibe.core.file instead of std.file).
Reentrancy
The event loop guarantees that the same timer will never be called more than
once at a time. Hence, functions run on a timer do not need to be re-entrant,
even if they execute for longer than the timer frequency.
setTimer, (alias) vibe_deadline.sleep = void vibe.core.core.sleep(core.time.Duration timeout) @safeSuspends the execution of the calling task for the specified amount of time.
Note that other tasks of the same thread will continue to run during the
wait time, in contrast to core.thread.Thread.sleep``, which shouldn't be
used in vibe.d applications.
Repeated sleep
As this method creates a new Timer every time, it is not recommended to
use it in a tight loop. For functions that calls sleep frequently,
it is preferable to instantiate a single Timer and reuse it,
as shown in the following example:
void myPollingFunction () {
Timer waiter = createTimer(null); // Create a re-usable timer
while (true) {
// Your awesome code goes here
timer.rearm(timeout, false);
timer.wait();
}
}
sleep, (alias) vibe_deadline.sleepUninterruptible = void vibe.core.core.sleepUninterruptible(core.time.Duration timeout) nothrow @safeSuspends the execution of the calling task an an uninterruptible manner.
This function behaves the same as sleep, except that invoking
Task.interrupt on the calling task will not result in an
InterruptException being thrown from sleepUninterruptible. Instead,
if any, a later interruptible wait state will throw the exception.
sleepUninterruptible;
import (package) vibevibe.(package) vibe.corecore.(module) vibe.core.taskContains interfaces and enums for evented I/O drivers.
task : (class) vibe.core.task.InterruptExceptionException that is thrown by Task.interrupt.
InterruptException;
void void D main()main()
{
bool (local variable) bool timedOuttimedOut = false;
bool (local variable) bool cleanedUpcleanedUp = false;
auto (local variable) vibe.core.task.Task tt = vibe.core.task.Task vibe.core.core.runTask!()(void delegate() nothrow @safe task) nothrow @safeRuns a new asynchronous task.
task will be called synchronously from within the vibeRunTask call. It will
continue to run until vibeYield() or any of the I/O or wait functions is
called.
Note that the maximum size of all args must not exceed maxTaskParameterSize.
runTask(() nothrow {
try
{
void vibe.core.core.sleep(core.time.Duration timeout) @safeSuspends the execution of the calling task for the specified amount of time.
Note that other tasks of the same thread will continue to run during the
wait time, in contrast to core.thread.Thread.sleep``, which shouldn't be
used in vibe.d applications.
Repeated sleep
As this method creates a new Timer every time, it is not recommended to
use it in a tight loop. For functions that calls sleep frequently,
it is preferable to instantiate a single Timer and reuse it,
as shown in the following example:
void myPollingFunction () {
Timer waiter = createTimer(null); // Create a re-usable timer
while (true) {
// Your awesome code goes here
timer.rearm(timeout, false);
timer.wait();
}
}
Examples
import vibe.core.core : sleep;
import vibe.core.log : logInfo;
import core.time : msecs;
void test()
{
logInfo("Sleeping for half a second...");
sleep(500.msecs);
logInfo("Done sleeping.");
}
sleep(10.seconds);
try 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: ok"); catch ((class) object.ExceptionThe base class of all errors that are safe to catch and handle.
In principle, only thrown objects derived from this class are safe to catch
inside a catch block. Thrown objects not derived from Exception
represent runtime errors that should not be caught, as certain runtime
guarantees may not hold, making it unsafe to continue program execution.
Examples
bool gotCaught;
try
{
throw new Exception("msg");
}
catch (Exception e)
{
gotCaught = true;
assert(e.msg == "msg");
}
assert(gotCaught);
Exception (local variable) object.Exception errorerror) { assert(false, (local variable) object.Exception errorerror.(field) string object.Throwable.msgA message describing the error.
msg); }
}
catch ((class) vibe.core.task.InterruptExceptionException that is thrown by Task.interrupt.
InterruptException)
{
try 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: InterruptException"); catch ((class) object.ExceptionThe base class of all errors that are safe to catch and handle.
In principle, only thrown objects derived from this class are safe to catch
inside a catch block. Thrown objects not derived from Exception
represent runtime errors that should not be caught, as certain runtime
guarantees may not hold, making it unsafe to continue program execution.
Examples
bool gotCaught;
try
{
throw new Exception("msg");
}
catch (Exception e)
{
gotCaught = true;
assert(e.msg == "msg");
}
assert(gotCaught);
Exception (local variable) object.Exception errorerror) { assert(false, (local variable) object.Exception errorerror.(field) string object.Throwable.msgA message describing the error.
msg); }
(local variable) bool timedOuttimedOut = true;
// Cleanup: must use uninterruptible sleep to avoid re-interruption
void vibe.core.core.sleepUninterruptible(core.time.Duration timeout) nothrow @safeSuspends the execution of the calling task an an uninterruptible manner.
This function behaves the same as sleep, except that invoking
Task.interrupt on the calling task will not result in an
InterruptException being thrown from sleepUninterruptible. Instead,
if any, a later interruptible wait state will throw the exception.
sleepUninterruptible(5.msecs);
(local variable) bool cleanedUpcleanedUp = true;
}
catch ((class) object.ExceptionThe base class of all errors that are safe to catch and handle.
In principle, only thrown objects derived from this class are safe to catch
inside a catch block. Thrown objects not derived from Exception
represent runtime errors that should not be caught, as certain runtime
guarantees may not hold, making it unsafe to continue program execution.
Examples
bool gotCaught;
try
{
throw new Exception("msg");
}
catch (Exception e)
{
gotCaught = true;
assert(e.msg == "msg");
}
assert(gotCaught);
Exception (local variable) object.Exception errorerror) { assert(false, (local variable) object.Exception errorerror.(field) string object.Throwable.msgA message describing the error.
msg); }
});
// Arm timeout timer
auto (local variable) vibe.core.core.Timer timertimer = vibe.core.core.Timer vibe.core.core.setTimer(core.time.Duration timeout, void delegate() nothrow @safe callback, bool periodic = false) nothrow @safeCreates a new timer, that will fire callback after timeout
Timers can be be separated into two categories: one-off or periodic.
One-off timers fire only once, after a specific amount of time,
while periodic timer fire at a regular interval.
One-off_timers:
One-off timers can be used for performing a task after a specific delay,
or to schedule a time without interrupting the currently running code.
For example, the following is a way to emulate a 'schedule' primitive,
a way to schedule a task without starting it immediately (unlike runTask):
void handleRequest (scope HTTPServerRequest req, scope HTTPServerResponse res) {
Payload payload = parse(req);
if (payload.isValid())
// Don't immediately yield, finish processing the data and the query
setTimer(0.msecs, () => sendToPeers(payload));
process(payload);
res.writeVoidBody();
}
In this example, the server delays the network communication that
will be performed by sendToPeers until after the request is fully
processed, ensuring the client doesn't wait more than the actual processing
time for the response.
Periodic timers
Periodic timers will trigger for the first time after timeout,
then at best every timeout period after this. Periodic timers may be
explicitly stopped by calling the Timer.stop() method on the return value
of this function.
As timer are non-preemtive (see the "Preemption" section), user code does
not need to compensate for time drift, as the time spent in the function
will not affect the frequency, unless the function takes longer to complete
than the timer.
Preemption
Like other events in Vibe.d, timers are non-preemptive, meaning that
the currently executing function will not be interrupted to let a timer run.
This is usually not a problem in server applications, as any blocking code
will be easily noticed (the server will stop to handle requests), but might
come at a surprise in code that doesn't handle request.
If this is a problem, the solution is usually to either explicitly give
control to the event loop (by calling yield) or ensuring operations are
asynchronous (e.g. call functions from vibe.core.file instead of std.file).
Reentrancy
The event loop guarantees that the same timer will never be called more than
once at a time. Hence, functions run on a timer do not need to be re-entrant,
even if they execute for longer than the timer frequency.
Examples
void printTime()
@safe nothrow {
import std.datetime;
logInfo("The time is: %s", Clock.currTime());
}
void test()
{
import vibe.core.core;
// start a periodic timer that prints the time every second
setTimer(1.seconds, toDelegate(&printTime), true);
}
setTimer(50.msecs, () nothrow {
(local variable) vibe.core.task.Task tt.void vibe.core.task.Task.interrupt() nothrow @trustedinterrupt();
});
scope (exit) (local variable) vibe.core.core.Timer timertimer.void vibe.core.core.Timer.stop() nothrow @safeResets the timer and avoids any firing.
stop();
(local variable) vibe.core.task.Task tt.void vibe.core.task.Task.join() @trustedjoin();
assert((local variable) bool timedOuttimedOut);
assert((local variable) bool cleanedUpcleanedUp);
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) bool timedOuttimedOut);
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) bool cleanedUpcleanedUp);
}