source-timer-leeway.dhover×189all
#!/usr/bin/env dub
/+ dub.sdl:
    name "gcd_source_timer_leeway"
    platforms "osx"
    targetPath "build"
+/
/**
 * GCD — timers are a source type, and `leeway` is a first-class parameter.
 *
 * `dispatch_source_set_timer(source, start, interval, leeway)` has no
 * equivalent in `timerfd`, `setitimer` or `EVFILT_TIMER` as most loops use it:
 * the fourth argument tells the kernel how much *later* than the deadline the
 * timer may fire, so unrelated timers across the whole system coalesce into one
 * wakeup. It lowers to kqueue's `NOTE_LEEWAY` (`DISPATCH_HAVE_TIMER_COALESCING`
 * in `src/event/event_config.h`); libdispatch clamps a leeway larger than half
 * the interval down to `interval / 2` (`_dispatch_timer_config_create`,
 * `src/source.c`).
 *
 * A leeway is a licence to be late, never to be early. This program arms a
 * repeating timer with a leeway equal to half its interval, records the arrival
 * time of each of five fires, and asserts that no fire landed before its
 * nominal deadline.
 *
 * Companion to the GCD deep-dive:
 * see docs/research/async-io/gcd/index.md § "Timers, leeway and coalescing".
 *
 * Run with: `dub run --single source-timer-leeway.d`
 *
 * Portability: macOS only (`platforms "osx"`).
 */
module 
(module) gcd_source_timer_leeway

GCD — timers are a source type, and leeway is a first-class parameter.

dispatch_source_set_timer(source, start, interval, leeway) has no equivalent in timerfd, setitimer or EVFILT_TIMER as most loops use it: the fourth argument tells the kernel how much later than the deadline the timer may fire, so unrelated timers across the whole system coalesce into one wakeup. It lowers to kqueue's NOTE_LEEWAY (DISPATCH_HAVE_TIMER_COALESCING in src/event/event_config.h); libdispatch clamps a leeway larger than half the interval down to interval / 2 (_dispatch_timer_config_create, src/source.c).

A leeway is a licence to be late, never to be early. This program arms a repeating timer with a leeway equal to half its interval, records the arrival time of each of five fires, and asserts that no fire landed before its nominal deadline.

Companion to the GCD deep-dive: see docs/research/async-io/gcd/index.md § "Timers, leeway and coalescing".

Run with: dub run --single source-timer-leeway.d

Portability

macOS only (platforms "osx").

gcd_source_timer_leeway
;
import
(package) core
core
.
(module) core.atomic

The atomic module provides basic support for lock-free concurrent programming.

Use the -preview=nosharedaccess compiler flag to detect unsafe individual read or write operations on shared data.

Source

core/atomic.d

Examples

int y = 2;
shared int x = y; // OK

//x++; // read modify write error
x.atomicOp!"+="(1); // OK
//y = x; // read error with preview flag
y = x.atomicLoad(); // OK
assert(y == 3);
//x = 5; // write error with preview flag
x.atomicStore(5); // OK
assert(x.atomicLoad() == 5);
@copyrightCopyright Sean Kelly 2005 - 2016.@licenseBoost License 1.0@authorsSean Kelly, Alex Rønne Petersen, Manu Evans
atomic
:
(alias template) gcd_source_timer_leeway.atomicLoad = core.atomic.atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val) if (!is(T == shared(U), U) && !is(T == shared(inout(U)), U) && !is(T == shared(const(U)), U))

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
,
(alias template) gcd_source_timer_leeway.atomicOp = core.atomic.atomicOp(string op, T, V1)(ref shared T val, V1 mod) if (__traits(compiles, mixin("*cast(T*)&val" ~ op ~ "mod")))

Performs the binary operation 'op' on val using 'mod' as the modifier.

@paramval The target variable.@parammod The modifier to apply.@returnsThe result of the operation.
atomicOp
,
(alias template) gcd_source_timer_leeway.atomicStore = core.atomic.atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval) if (!is(T == shared) && !is(V == shared))

Writes 'newval' into 'val'. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.rel, and MemoryOrder.seq.

@paramval The target variable.@paramnewval The value to store.
atomicStore
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdint

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html, stdint.h

Source

core/stdc/stdint.d

@copyrightCopyright Sean Kelly 2005 - 2018@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdint
: uintptr_t;
import
(package) core
core
.
(module) core.time

Module 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

@copyrightCopyright 2010 - 2012@licenseBoost License 1.0.@authorsJonathan M Davis and Kato Shoichi
time
:
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
, msecs, nsecs;
import
(package) std
std
.
(module) std.stdio
Category 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:

  1. The lowest layer is the operating system layer. The two main schemes are Windows and Posix.

  2. C's stdio.h which unifies the two operating system schemes.

  3. std.stdio, this module, unifies the various stdio.h implementations into a high level package for D programs.

Source

std/stdio.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Alex Rønne Petersen
stdio
:
(alias template) gcd_source_timer_leeway.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

Equivalent to writef(fmt, args, '\n').

writefln
,
(alias template) gcd_source_timer_leeway.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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
;
alias
(alias) gcd_source_timer_leeway.dispatch_queue_t = void*
dispatch_queue_t
= void*;
alias
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
= void*;
alias
(alias) gcd_source_timer_leeway.dispatch_semaphore_t = void*
dispatch_semaphore_t
= void*;
alias
(alias) gcd_source_timer_leeway.dispatch_function_t = extern (C) void function(void*) nothrow
dispatch_function_t
= extern (C) void function(void*) nothrow;
extern (C) nothrow @nogc { /// `DISPATCH_SOURCE_TYPE_TIMER` is `&_dispatch_source_type_timer`. extern __gshared const ubyte
(constant global) const(ubyte) gcd_source_timer_leeway._dispatch_source_type_timer

DISPATCH_SOURCE_TYPE_TIMER is &_dispatch_source_type_timer``.

_dispatch_source_type_timer
;
(alias) gcd_source_timer_leeway.dispatch_queue_t = void*
dispatch_queue_t
void* gcd_source_timer_leeway.dispatch_queue_create(const(char)* label, void* attr) nothrow @nogc
dispatch_queue_create
(const(char)*
(parameter) const(char)* label
label
, void*
(parameter) void* attr
attr
);
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
void* gcd_source_timer_leeway.dispatch_source_create(const(void)* type, ulong handle, ulong mask, void* queue) nothrow @nogc
dispatch_source_create
(const(void)*
(parameter) const(void)* type
type
, uintptr_t
(parameter) ulong handle
handle
,
uintptr_t
(parameter) ulong mask
mask
,
(alias) gcd_source_timer_leeway.dispatch_queue_t = void*
dispatch_queue_t
(parameter) void* queue
queue
);
void
void gcd_source_timer_leeway.dispatch_source_set_timer(void* source, ulong start, ulong interval, ulong leeway) nothrow @nogc
dispatch_source_set_timer
(
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
(parameter) void* source
source
, ulong
(parameter) ulong start
start
,
ulong
(parameter) ulong interval
interval
, ulong
(parameter) ulong leeway
leeway
);
void
void gcd_source_timer_leeway.dispatch_source_set_event_handler_f(void* source, extern (C) void function(void*) nothrow handler) nothrow @nogc
dispatch_source_set_event_handler_f
(
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
(parameter) void* source
source
,
(alias) gcd_source_timer_leeway.dispatch_function_t = extern (C) void function(void*) nothrow
dispatch_function_t
(parameter) extern (C) void function(void*) nothrow handler
handler
);
void
void gcd_source_timer_leeway.dispatch_source_set_cancel_handler_f(void* source, extern (C) void function(void*) nothrow handler) nothrow @nogc
dispatch_source_set_cancel_handler_f
(
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
(parameter) void* source
source
,
(alias) gcd_source_timer_leeway.dispatch_function_t = extern (C) void function(void*) nothrow
dispatch_function_t
(parameter) extern (C) void function(void*) nothrow handler
handler
);
void
void gcd_source_timer_leeway.dispatch_source_cancel(void* source) nothrow @nogc
dispatch_source_cancel
(
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
(parameter) void* source
source
);
void
void gcd_source_timer_leeway.dispatch_resume(void* object) nothrow @nogc
dispatch_resume
(void*
(parameter) void* object
object
);
void
void gcd_source_timer_leeway.dispatch_release(void* object) nothrow @nogc
dispatch_release
(void*
(parameter) void* object
object
);
ulong
ulong gcd_source_timer_leeway.dispatch_time(ulong when, long delta) nothrow @nogc
dispatch_time
(ulong
(parameter) ulong when
when
, long
(parameter) long delta
delta
);
(alias) gcd_source_timer_leeway.dispatch_semaphore_t = void*
dispatch_semaphore_t
void* gcd_source_timer_leeway.dispatch_semaphore_create(long value) nothrow @nogc
dispatch_semaphore_create
(long
(parameter) long value
value
);
long
long gcd_source_timer_leeway.dispatch_semaphore_wait(void* sema, ulong timeout) nothrow @nogc
dispatch_semaphore_wait
(
(alias) gcd_source_timer_leeway.dispatch_semaphore_t = void*
dispatch_semaphore_t
(parameter) void* sema
sema
, ulong
(parameter) ulong timeout
timeout
);
long
long gcd_source_timer_leeway.dispatch_semaphore_signal(void* sema) nothrow @nogc
dispatch_semaphore_signal
(
(alias) gcd_source_timer_leeway.dispatch_semaphore_t = void*
dispatch_semaphore_t
(parameter) void* sema
sema
);
} enum
(constant) ulong gcd_source_timer_leeway.DISPATCH_TIME_NOW = 0LU
DISPATCH_TIME_NOW
= 0UL;
enum
(constant) ulong gcd_source_timer_leeway.DISPATCH_TIME_FOREVER = 18446744073709551615LU
DISPATCH_TIME_FOREVER
= ~0UL;
enum
(constant) int gcd_source_timer_leeway.intervalMs = 20
intervalMs
= 20;
enum
(constant) int gcd_source_timer_leeway.fireBudget = 5
fireBudget
= 5;
struct
(struct) gcd_source_timer_leeway.Timer
Timer
{
(alias) gcd_source_timer_leeway.dispatch_source_t = void*
dispatch_source_t
(field) void* gcd_source_timer_leeway.Timer.source
source
;
(alias) gcd_source_timer_leeway.dispatch_semaphore_t = void*
dispatch_semaphore_t
(field) void* gcd_source_timer_leeway.Timer.finished
finished
;
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
(field) core.time.MonoTimeImpl!(ClockType.normal) gcd_source_timer_leeway.Timer.armedAt
armedAt
;
shared int
(field) shared(int) gcd_source_timer_leeway.Timer.fires
fires
;
shared long[
(constant) int gcd_source_timer_leeway.fireBudget = 5
fireBudget
]
(field) shared(long[5]) gcd_source_timer_leeway.Timer.arrivalsUsecs
arrivalsUsecs
;
} __gshared
(struct) gcd_source_timer_leeway.Timer
Timer
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
;
extern (C) void
void gcd_source_timer_leeway.onFire(void* context) nothrow
onFire
(void*
(parameter) void* context
context
) nothrow
{ const
(local variable) const(core.time.Duration) elapsed
elapsed
=
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
.
core.time.MonoTimeImpl!(ClockType.normal) core.time.MonoTimeImpl!(ClockType.normal).currTime() nothrow @nogc @property @trusted

The current time of the system's monotonic clock. This has no relation to the wall clock time, as the wall clock time can be adjusted (e.g. by NTP), whereas the monotonic clock always moves forward. The source of the monotonic time is system-specific.

On Windows, QueryPerformanceCounter is used. On Mac OS X, mach_absolute_time is used, while on other POSIX systems, clock_gettime is used.

Warning: On some systems, the monotonic clock may stop counting when the computer goes to sleep or hibernates. So, the monotonic clock may indicate less time than has actually passed if that occurs. This is known to happen on Mac OS X. It has not been tested whether it occurs on either Windows or Linux.

currTime
-
core.time.Duration core.time.MonoTimeImpl!(ClockType.normal).opBinary!"-"(core.time.MonoTimeImpl!(ClockType.normal) rhs) const pure nothrow @nogc @safe

Subtracting two MonoTimes results in a Duration representing the amount of time which elapsed between them.

The primary way that programs should time how long something takes is to do

MonoTime before = MonoTime.currTime;
// do stuff
MonoTime after = MonoTime.currTime;

// How long it took.
Duration timeElapsed = after - before;

or to use a wrapper (such as a stop watch type) which does that.

Warning: Because Duration is in hnsecs, whereas MonoTime is in system ticks, it's usually the case that this assertion will fail

auto before = MonoTime.currTime;
// do stuff
auto after = MonoTime.currTime;
auto timeElapsed = after - before;
assert(before + timeElapsed == after);

This is generally fine, and by its very nature, converting from system ticks to any type of seconds (hnsecs, nsecs, etc.) will introduce rounding errors, but if code needs to avoid any of the small rounding errors introduced by conversion, then it needs to use MonoTime's ticks property and keep all calculations in ticks rather than using Duration.

timer
.
(field) core.time.MonoTimeImpl!(ClockType.normal) gcd_source_timer_leeway.Timer.armedAt
armedAt
;
const
(local variable) const(int) n
n
=
int core.atomic.atomicOp!("+=", int, int)(ref shared(int) val, int mod) pure nothrow @nogc @safe

Performs the binary operation 'op' on val using 'mod' as the modifier.

@paramval The target variable.@parammod The modifier to apply.@returnsThe result of the operation.
atomicOp
!"+="(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) shared(int) gcd_source_timer_leeway.Timer.fires
fires
, 1);
if (
(local variable) const(int) n
n
<=
(constant) int gcd_source_timer_leeway.fireBudget = 5
fireBudget
)
void core.atomic.atomicStore!(MemoryOrder.seq, long, long)(ref shared(long) val, long newval) pure nothrow @nogc @trusted

Writes 'newval' into 'val'. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.rel, and MemoryOrder.seq.

@paramval The target variable.@paramnewval The value to store.
atomicStore
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) shared(long[5]) gcd_source_timer_leeway.Timer.arrivalsUsecs
arrivalsUsecs
[
(local variable) const(int) n
n
- 1],
(local variable) const(core.time.Duration) elapsed
elapsed
.
long core.time.Duration.total!"usecs"() const pure nothrow @nogc @property @safe

Returns the total number of the given units in this Duration. So, unlike split, it does not strip out the larger units.

Examples

assert(dur!"weeks"(12).total!"weeks" == 12);
assert(dur!"weeks"(12).total!"days" == 84);

assert(dur!"days"(13).total!"weeks" == 1);
assert(dur!"days"(13).total!"days" == 13);

assert(dur!"hours"(49).total!"days" == 2);
assert(dur!"hours"(49).total!"hours" == 49);

assert(dur!"nsecs"(2007).total!"hnsecs" == 20);
assert(dur!"nsecs"(2007).total!"nsecs" == 2000);
total
!"usecs");
if (
(local variable) const(int) n
n
>=
(constant) int gcd_source_timer_leeway.fireBudget = 5
fireBudget
)
void gcd_source_timer_leeway.dispatch_source_cancel(void* source) nothrow @nogc
dispatch_source_cancel
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
);
} extern (C) void
void gcd_source_timer_leeway.onCancel(void* context) nothrow
onCancel
(void*
(parameter) void* context
context
) nothrow
{
long gcd_source_timer_leeway.dispatch_semaphore_signal(void* sema) nothrow @nogc
dispatch_semaphore_signal
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.finished
finished
);
} int
int D main()
main
()
{ auto
(local variable) void* queue
queue
=
void* gcd_source_timer_leeway.dispatch_queue_create(const(char)* label, void* attr) nothrow @nogc
dispatch_queue_create
("dev.sparkles.research.gcd.timer", null);
scope (exit)
void gcd_source_timer_leeway.dispatch_release(void* object) nothrow @nogc
dispatch_release
(
(local variable) void* queue
queue
);
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.finished
finished
=
void* gcd_source_timer_leeway.dispatch_semaphore_create(long value) nothrow @nogc
dispatch_semaphore_create
(0);
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
=
void* gcd_source_timer_leeway.dispatch_source_create(const(void)* type, ulong handle, ulong mask, void* queue) nothrow @nogc
dispatch_source_create
(&
(constant global) const(ubyte) gcd_source_timer_leeway._dispatch_source_type_timer

DISPATCH_SOURCE_TYPE_TIMER is &_dispatch_source_type_timer``.

_dispatch_source_type_timer
, 0, 0,
(local variable) void* queue
queue
);
void gcd_source_timer_leeway.dispatch_source_set_event_handler_f(void* source, extern (C) void function(void*) nothrow handler) nothrow @nogc
dispatch_source_set_event_handler_f
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
, &
void gcd_source_timer_leeway.onFire(void* context) nothrow
onFire
);
void gcd_source_timer_leeway.dispatch_source_set_cancel_handler_f(void* source, extern (C) void function(void*) nothrow handler) nothrow @nogc
dispatch_source_set_cancel_handler_f
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
, &
void gcd_source_timer_leeway.onCancel(void* context) nothrow
onCancel
);
const
(local variable) const(long) intervalNs
intervalNs
=
(constant) int gcd_source_timer_leeway.intervalMs = 20
intervalMs
* 1_000_000L;
// Leeway == interval / 2 is the largest value libdispatch will honour for // this interval; anything bigger is clamped to exactly this. const
(local variable) const(long) leewayNs
leewayNs
=
(local variable) const(long) intervalNs
intervalNs
/ 2;
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) core.time.MonoTimeImpl!(ClockType.normal) gcd_source_timer_leeway.Timer.armedAt
armedAt
=
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
.
core.time.MonoTimeImpl!(ClockType.normal) core.time.MonoTimeImpl!(ClockType.normal).currTime() nothrow @nogc @property @trusted

The current time of the system's monotonic clock. This has no relation to the wall clock time, as the wall clock time can be adjusted (e.g. by NTP), whereas the monotonic clock always moves forward. The source of the monotonic time is system-specific.

On Windows, QueryPerformanceCounter is used. On Mac OS X, mach_absolute_time is used, while on other POSIX systems, clock_gettime is used.

Warning: On some systems, the monotonic clock may stop counting when the computer goes to sleep or hibernates. So, the monotonic clock may indicate less time than has actually passed if that occurs. This is known to happen on Mac OS X. It has not been tested whether it occurs on either Windows or Linux.

currTime
;
void gcd_source_timer_leeway.dispatch_source_set_timer(void* source, ulong start, ulong interval, ulong leeway) nothrow @nogc
dispatch_source_set_timer
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
,
ulong gcd_source_timer_leeway.dispatch_time(ulong when, long delta) nothrow @nogc
dispatch_time
(
(constant) ulong gcd_source_timer_leeway.DISPATCH_TIME_NOW = 0LU
DISPATCH_TIME_NOW
,
(local variable) const(long) intervalNs
intervalNs
),
(local variable) const(long) intervalNs
intervalNs
,
(local variable) const(long) leewayNs
leewayNs
);
void gcd_source_timer_leeway.dispatch_resume(void* object) nothrow @nogc
dispatch_resume
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
);
long gcd_source_timer_leeway.dispatch_semaphore_wait(void* sema, ulong timeout) nothrow @nogc
dispatch_semaphore_wait
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.finished
finished
,
(constant) ulong gcd_source_timer_leeway.DISPATCH_TIME_FOREVER = 18446744073709551615LU
DISPATCH_TIME_FOREVER
);
void gcd_source_timer_leeway.dispatch_release(void* object) nothrow @nogc
dispatch_release
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) void* gcd_source_timer_leeway.Timer.source
source
);
void std.stdio.writefln!(char, int, long)(in char[] fmt, int __param_1, long __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("interval = %d ms, leeway = %d ms",
(constant) int gcd_source_timer_leeway.intervalMs = 20
intervalMs
,
(local variable) const(long) leewayNs
leewayNs
/ 1_000_000);
void std.stdio.writeln!()() @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
();
void std.stdio.writeln!string(string __param_0) @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("fire deadline (ms) arrival (ms) lateness (ms)");
foreach (
(local variable) int i
i
; 0 ..
(constant) int gcd_source_timer_leeway.fireBudget = 5
fireBudget
)
{ const
(local variable) const(int) deadlineMs
deadlineMs
= (
(local variable) int i
i
+ 1) *
(constant) int gcd_source_timer_leeway.intervalMs = 20
intervalMs
;
const
(local variable) const(double) arrivalMs
arrivalMs
=
long core.atomic.atomicLoad!(MemoryOrder.seq, long)(ref return scope shared(const(long)) val) pure nothrow @nogc @trusted

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) shared(long[5]) gcd_source_timer_leeway.Timer.arrivalsUsecs
arrivalsUsecs
[
(local variable) int i
i
]) / 1000.0;
void std.stdio.writefln!(char, int, const(int), const(double), double)(in char[] fmt, int __param_1, const(int) __param_2, const(double) __param_3, double __param_4) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("%4d %13d %12.1f %13.1f",
(local variable) int i
i
+ 1,
(local variable) const(int) deadlineMs
deadlineMs
,
(local variable) const(double) arrivalMs
arrivalMs
,
(local variable) const(double) arrivalMs
arrivalMs
-
(local variable) const(int) deadlineMs
deadlineMs
);
// The contract: a leeway lets the kernel fire late, never early. A // 1 ms slack absorbs the clock read inside the handler itself. assert(
(local variable) const(double) arrivalMs
arrivalMs
+ 1.0 >=
(local variable) const(int) deadlineMs
deadlineMs
, "timer fired before its deadline");
} assert(
int core.atomic.atomicLoad!(MemoryOrder.seq, int)(ref return scope shared(const(int)) val) pure nothrow @nogc @trusted

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
(
(__gshared global) gcd_source_timer_leeway.Timer gcd_source_timer_leeway.timer
timer
.
(field) shared(int) gcd_source_timer_leeway.Timer.fires
fires
) >=
(constant) int gcd_source_timer_leeway.fireBudget = 5
fireBudget
, "timer under-delivered");
void std.stdio.writeln!()() @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
();
void std.stdio.writeln!string(string __param_0) @safe

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);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("leeway buys coalescing with other timers; it never moves a deadline earlier");
return 0; }