#!/usr/bin/env dub
/+ dub.sdl:
name "vibe_spawn"
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;
import (package) stdstd.(package) std.algorithmalgorithm.(module) std.algorithm.iterationThis is a submodule of std.algorithm.
It contains generic iteration algorithms.
Function Name Description cache Eagerly evaluates and caches another range's front. lazyCache Lazily evaluates and caches another range's front, unlike cache. cacheBidirectional As above, but also provides back and popBack. chunkBy chunkBy!((a,b) => a[1] == b[1])([[1, 1], [1, 2], [2, 2], [2, 1]]) returns a range containing 3 subranges: the first with just [1, 1]; the second with the elements [1, 2] and [2, 2]; and the third with just [2, 1]. cumulativeFold cumulativeFold!((a, b) => a + b)([1, 2, 3, 4]) returns a lazily-evaluated range containing the successive reduced values 1, 3, 6, 10. each each!writeln([1, 2, 3]) eagerly prints the numbers 1, 2 and 3 on their own lines. filter filter!(a => a > 0)([1, -1, 2, 0, -3]) iterates over elements 1 and 2. filterBidirectional Similar to filter, but also provides back and popBack at a small increase in cost. fold fold!((a, b) => a + b)([1, 2, 3, 4]) returns 10. group group([5, 2, 2, 3, 3]) returns a range containing the tuples tuple(5, 1), tuple(2, 2), and tuple(3, 2). joiner joiner(["hello", "world!"], "; ") returns a range that iterates over the characters "hello; world!". No new string is created - the existing inputs are iterated. map map!(a => a * 2)([1, 2, 3]) lazily returns a range with the numbers 2, 4, 6. mean Colloquially known as the average, mean([1, 2, 3]) returns 2. permutations Lazily computes all permutations using Heap's algorithm. reduce reduce!((a, b) => a + b)([1, 2, 3, 4]) returns 10. This is the old implementation of fold. splitWhen Lazily splits a range by comparing adjacent elements. splitter Lazily splits a range by a separator, element predicate or whitespace. substitute [1, 2].substitute(1, 0.1) returns [0.1, 2]. sum Same as fold, but specialized for accurate summation. uniq Iterates over the unique elements in a range, which is assumed sorted.
Source
std/algorithm/iteration.d
iteration : (alias template) vibe_spawn.splitter = std.algorithm.iteration.splitter(alias pred = "a == b", Flag keepSeparators = No.keepSeparators, Range, Separator)(Range r, Separator s) if (is(typeof(binaryFun!pred(r.front, s)) : bool) && (hasSlicing!Range && hasLength!Range || isNarrowString!Range) && (is(ElementType!Range : Separator) || !(isForwardRange!Separator && (hasLength!Separator || isNarrowString!Separator))))Lazily splits a range using an element or range as a separator.
Separator ranges can be any narrow string type or sliceable range type.
Two adjacent separators are considered to surround an empty element in
the split range. Use filter!(a => !a.empty) on the result to compress
empty elements.
The predicate is passed to binaryFun and accepts
any callable function that can be executed via pred(element, s).
Note
If splitting a string on whitespace and token compression is desired,
consider using the ``splitter(r) overload.
Constraints
The predicate pred needs to accept an element of r and the
separator s.
splitter;
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_spawn.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_spawn.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_spawn.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, (struct) vibe.core.core.TimerRepresents a timer.
Timer;
import (package) vibevibe.(package) vibe.corecore.(module) vibe.core.processFunctions and structures for dealing with subprocesses and pipes.
This module is modeled after std.process, but provides a fiber-aware
alternative to it. All blocking operations will yield the calling fiber
instead of blocking it.
process : (alias) vibe_spawn.pipeProcess = vibe.core.process.ProcessPipes vibe.core.process.pipeProcess(scope string[] args, std.process.Redirect redirect = Redirect.all, const(string[string]) env = cast(const(string[string]))null, vibe.core.process.Config config = Config(Flags.none, null, null), scope vibe.core.path.GenericPath!(PosixPathFormat) workDir = GenericPath(null)) @trustedEquivalent to std.process.pipeProcess``.
pipeProcess, (enum) std.process.RedirectFlags that can be passed to pipeProcess and pipeShell
to specify which of the child process' standard streams are redirected.
Use bitwise OR to combine flags.
Redirect;
import (package) vibevibe.(package) vibe.corecore.(module) vibe.core.streamGeneric stream interface used by several stream-like classes.
This module defines the basic (buffered) stream primitives. For concrete stream types, take a
look at the vibe.stream`` package. The vibe.stream.operations module contains additional
high-level operations on streams, such as reading streams by line or as a whole.
Note that starting with vibe-core 1.0.0, streams can be of either struct or class type.
Any APIs that take streams as a parameter should use a template type parameter that is tested
using the appropriate trait (e.g. isInputStream) instead of assuming the specific interface
type (e.g. InputStream).
stream : (enum) eventcore.driver.IOModeIOMode;
void void D main()main()
{
auto (local variable) vibe.core.process.ProcessPipes pipespipes = vibe.core.process.ProcessPipes vibe.core.process.pipeProcess(scope string[] args, std.process.Redirect redirect = Redirect.all, const(string[string]) env = cast(const(string[string]))null, vibe.core.process.Config config = Config(Flags.none, null, null), scope vibe.core.path.GenericPath!(PosixPathFormat) workDir = GenericPath(null)) @trustedEquivalent to std.process.pipeProcess``.
pipeProcess(["sh", "-c", "echo one; echo two; exec sleep 30"], (enum) std.process.RedirectFlags that can be passed to pipeProcess and pipeShell
to specify which of the child process' standard streams are redirected.
Use bitwise OR to combine flags.
Redirect.(enum value) std.process.Redirect.stdout = 2Redirect the standard input, output or error streams, respectively.
stdout);
bool (local variable) bool timedOuttimedOut = false;
(struct) vibe.core.core.TimerRepresents a timer.
Timer (local variable) vibe.core.core.Timer timertimer;
scope(exit) (local variable) vibe.core.core.Timer timertimer.void vibe.core.core.Timer.stop() nothrow @safeResets the timer and avoids any firing.
stop();
// Manual line framing and streaming
int (local variable) int linesSeenlinesSeen = 0;
(alias) object.string = stringstring (local variable) string pendingpending;
auto (local variable) vibe.core.task.Task readerreader = 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 {
ubyte[128] (local variable) ubyte[128] bufbuf;
while (!(local variable) vibe.core.process.ProcessPipes pipespipes.(field) vibe.core.process.PipeInputStream vibe.core.process.ProcessPipes.stdoutstdout.bool vibe.core.process.PipeInputStream.empty() @property @safeempty) {
const (local variable) const(ulong) nn = (local variable) vibe.core.process.ProcessPipes pipespipes.(field) vibe.core.process.PipeInputStream vibe.core.process.ProcessPipes.stdoutstdout.ulong vibe.core.process.PipeInputStream.read(scope ubyte[] dst, eventcore.driver.IOMode mode) @saferead((local variable) ubyte[128] bufbuf[], (enum) eventcore.driver.IOModeIOMode.(enum value) eventcore.driver.IOMode.once = 1Process as much as possible with a single call
once);
(local variable) string pendingpending ~= cast(const(char)[]) (local variable) ubyte[128] bufbuf[0 .. (local variable) const(ulong) nn];
import (package) stdstd.(module) std.stringString handling functions.
Category Functions Searching column indexOf indexOfAny indexOfNeither lastIndexOf lastIndexOfAny lastIndexOfNeither Comparison isNumeric Mutation capitalize Pruning and Filling center chomp chompPrefix chop detabber detab entab entabber leftJustify outdent rightJustify strip stripLeft stripRight wrap Substitution abbrev soundex soundexer succ tr translate Miscellaneous assumeUTF fromStringz lineSplitter representation splitLines toStringz Objects of types string, wstring, and dstring are value types and cannot be mutated element-by-element. For using mutation during building strings, use char[], wchar[], or dchar[]. The xxxstring types are preferable because they don't exhibit undesired aliasing, thus making code more robust.
The following functions are publicly imported:
Module Functions Publicly imported functions std.algorithm cmp, std,algorithm,comparison count, std,algorithm,searching endsWith, std,algorithm,searching startsWith, std,algorithm,searching std.array join, std,array replace, std,array replaceInPlace, std,array split, std,array empty, std,array std.format format, std,format sformat, std,format std.uni icmp, std,uni toLower, std,uni toLowerInPlace, std,uni toUpper, std,uni toUpperInPlace, std,uni There is a rich set of functions for string handling defined in other modules. Functions related to Unicode and ASCII are found in std.uni and std.ascii, respectively. Other functions that have a wider generality than just strings can be found in std.algorithm and std.range.
Source
std/string.d
string : (alias template) indexOf = std.string.indexOf(Range)(Range s, dchar c, CaseSensitive cs = Yes.caseSensitive) if (isInputRange!Range && isSomeChar!(ElementType!Range) && !isSomeString!Range)Searches for a character in a string or range.
Params:
s = string or InputRange of characters to search for `c` in
c = character to search for in `s`
startIdx = index to a well-formed code point in `s` to start
searching from; defaults to 0
cs = specifies whether comparisons are case-sensitive
(`Yes.caseSensitive`) or not (`No.caseSensitive`).
Returns:
If `c` is found in `s`, then the index of its first occurrence is
returned. If `c` is not found or `startIdx` is greater than or equal to
`s.length`, then -1 is returned. If the parameters are not valid UTF,
the result will still be either -1 or in the range [`startIdx` ..
`s.length`], but will not be reliable otherwise.
Throws:
If the sequence starting at `startIdx` does not represent a well-formed
code point, then a $(REF UTFException, std,utf) may be thrown.
See_Also: $(REF countUntil, std,algorithm,searching)
indexOf;
for (auto (local variable) long endend = (local variable) string pendingpending.long std.string.indexOf!char(scope const(char)[] s, dchar c, std.typecons.Flag!"caseSensitive" cs = Flag.yes) pure nothrow @nogc @safeSearches for a character in a string or range.
indexOf('\n'); end >= 0; end = pending.indexOf('\n')) {
auto (local variable) string lineline = (local variable) string pendingpending[0 .. (local variable) long endend];
(local variable) string pendingpending = (local variable) string pendingpending[(local variable) long endend + 1 .. $];
if ((local variable) string lineline.(field) ulong string.lengthlength) {
assert((local variable) string lineline == ((local variable) int linesSeenlinesSeen == 0 ? "one" : "two"));
void std.stdio.writeln!(string, string)(string __param_0, string __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("line: ", (local variable) string lineline);
++(local variable) int linesSeenlinesSeen;
if ((local variable) int linesSeenlinesSeen == 2) (local variable) vibe.core.core.Timer timertimer = vibe.core.core.Timer vibe.core.core.Timer.opAssign(vibe.core.core.Timer p) nothrow return ref @trustedsetTimer(100.msecs, () nothrow {
(local variable) bool timedOuttimedOut = true;
try (local variable) vibe.core.process.ProcessPipes pipespipes.(field) vibe.core.process.Process vibe.core.process.ProcessPipes.processprocess.void vibe.core.process.Process.kill() @safeKill the process.
By default on Linux this sends SIGTERM to the process.
kill(); 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 ee) { assert(false, (local variable) object.Exception ee.(field) string object.Throwable.msgA message describing the error.
msg); }
});
}
}
}
} 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 ee) { assert(false, (local variable) object.Exception ee.(field) string object.Throwable.msgA message describing the error.
msg); }
});
const (local variable) const(int) statusstatus = (local variable) vibe.core.process.ProcessPipes pipespipes.(field) vibe.core.process.Process vibe.core.process.ProcessPipes.processprocess.int vibe.core.process.Process.wait() @safeWait for the process to exit, allowing other fibers to continue in the
meantime.
wait();
(local variable) vibe.core.task.Task readerreader.void vibe.core.task.Task.join() @trustedjoin();
assert((local variable) int linesSeenlinesSeen == 2);
assert((local variable) string pendingpending.(field) ulong string.lengthlength == 0 && (local variable) const(int) statusstatus == -15);
assert((local variable) bool timedOuttimedOut);
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("exited: timedOut, signaled by 15");
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("end: timedOut, reap: reaped");
}