hosted/blocking
skip to the library navigationHosted targets only.
The hosted provider whose waiting operations block the thread, written once over platform/posix: the provider host, made by new, imported as blocking with no alias. It is what an ordinary hosted program imports.
| Call | What it does |
|---|---|
blocking.new() | The process's provider: a host handle that borrows nothing. |
blocking.over(space) | A provider that keeps its last errno in a space the caller declares. |
blocking.last_errno(host) | The errno number of the last failing call. |
blocking.last_signal(host) | The signal that ended the last child waited for. |
host supplies every concept of core/io, core/time and core/net: the shared I/O concepts and so world, directories, environment, programs, network, file_system, terminals, clock, wall_clock and entropy. It is also a fibre.scheduler that runs each task to its end before admit returns, as fibre.whole does, and so is no provider of fibre.turns: its calls block the thread.
It is built over a hosted/system handle, which new makes, and hands that handle everything that does not wait: opening and closing files, the standard streams' descriptors and the arguments, the environment, directories, the rest of the file system, terminals, entropy and the wall clock. What waits is its own: read, write and write_some, running programs, the network, and the monotonic clock with its sleep. A child is started by the system handle's start, which does not wait; reading and writing its pipes and waiting for it are this provider's. Both report through the system handle's one last-error cell, so last_errno says the same whichever of them failed. Its files are the system's: hosted/system's descriptor_of, file_of and socket_of convert them.
What the provider promises
| Call | Promise |
|---|---|
write | Writes the whole slice, or fails. Bytes written before a failure stay written. |
write_some | Makes one attempt and returns a positive count, which may be short. A failed attempt writes nothing. |
| either, on an empty slice | Succeeds without asking the system; write_some returns zero. |
open, read, write | Retried after a signal interrupts them only when the system guarantees the attempt made no progress: completed progress is never repeated. |
close | Consumes the file once, even when it fails, and is never retried blindly. |
same_file(left, right) | Follows symbolic links and recognises hard links. The left path must exist; a missing right path gives false, and any other failure is an error. The check is not atomic: the names must stay put until the open that follows. |
| the arguments | Begin after the program's name: neither this provider nor the memory world includes argv[0]. |
The network
network runs over platform/posix's sockets. A socket is a descriptor and a file of the provider like any other, so read and write take a connection.
- A write to a socket the provider made is a send, which raises no SIGPIPE beside a C handler on any system.
- A listener reuses its address.
- An IPv6 socket takes IPv6 alone on every system, which BSD does from the start and Linux does not.
- Up to 128 connections wait to be accepted.
Interruptions and partial results are handled for you:
- an interrupted call is made again;
- a connection a signal interrupted is waited out with
poll, and its outcome read from the socket; - an accept refused because its connection was reset before it was taken accepts the next;
- a send goes on after a short one until every byte is sent.
A send to a peer that has gone is disconnected, EPIPE or ECONNRESET kept as the last errno, and a write to it is io_failed with EPIPE. The process ignores SIGPIPE, so neither ends it.
The clock
| Call | On the hosted provider |
|---|---|
now | platform/posix's monotonic clock, in nanoseconds since the system started. |
sleep | Takes its deadline from the monotonic clock, and asks the system to sleep for what is left until that clock has reached it. |
A clock the system cannot read ends the program, since no hosted system fails to.
A sleep a signal interrupts, or the system ends early, sleeps on: it never returns before the deadline as now reads it.
Items
Functions 4
Also on this page
public host: type = blocking_value
Hosted implementation of all four I/O capabilities and so of io.world, of io.programs, net.network, the monotonic time.clock and fibre.scheduler, whose waits block the thread, and of every concept hosted/system supplies, which it hands the system's handle it is built over: io.directories, io.environment, io.file_system, io.terminals, io.entropy and time.wall_clock. A child is started by that handle's start, which does not wait (D479). A handle: copies share the process's descriptors, arguments and environment, and the last-error and last-signal cells they were made with. Its files are the system's, as hosted/system's descriptor_of and file_of give them; borrowed arguments and variables refer to process storage.
public space: type = system.space
The system's last-error and last-signal cells of the caller's own, hosted/system's space, for over.
public last_errno: (handle: host) -> (number: i32)
Return errno captured for the terminal failing provider call, as hosted/system's last_errno does: the cell is the system handle's, which this provider's own calls report through too. Zero means the handle's most recent call of any concept did not fail with an errno.
public last_signal: (handle: host) -> (number: i32)
Return the number of the signal that ended the child this handle's cell last saw end through io.wait, as hosted/system's last_signal does; zero when it exited with a code or none was waited for.
public new: () -> (handle: host)
Return a handle to the hosted provider whose waits block the thread, over a new hosted/system handle: the process's arguments, the three standard streams, descriptors 0, 1 and 2, and the process's last-error cell. Regular open-write operations create or truncate files; close regular files explicitly. The handle borrows nothing. Use over for a cell of the caller's own.
Calling this before the hosted entry has established the process's arguments traps, as hosted/system's new does.
Fill state and return a handle that records its last error there rather than in the process's cell, over hosted/system's over. It shares the process's arguments and descriptors like any other handle; calling this before any root exists traps, as new does.
Example program
The program prints the arguments blocking.new()'s provider lends, one to a line after its index. It then looks for a settings file that is not there and prints why it could not be opened, in failure.words' phrase and by blocking.last_errno's number, before going on with its defaults.
This complete program is one of the compiler's runtime tests. View source.
-- Print the arguments the program was given, one to a line after its -- index, then look for a settings file. When it cannot be opened the -- program says why, in the library's words and by the system's own error -- number, and goes on with its defaults. import core/failure import core/io import core/text import hosted/blocking public main: () -> (code: i32) = host := blocking.new() mut storage: [256]u8 = zeroed mut out := io.buffered_over(host, io.out(host), storage) defer io.flush(out) else none code = 1 count: usize = io.argument_count(host) io.format(out, "{} arguments\n", [any(addr count)]) else none for index in 0..<count do argument := io.argument_at(host, index) else (problem) return end io.format(out, "{}: {}\n", [any(addr index), any(addr argument)]) else none end for path: []u8 = "settings.conf" file := io.open_read(host, text.host_over(path)) else (problem) reason: []u8 = failure.words(problem) number: i32 = blocking.last_errno(host) io.format(out, "{}: {} (errno {}), so the defaults apply\n", [any(addr path), any(addr reason), any(addr number)]) else none code = 0 return end io.close(host, file) else none io.format(out, "{}: opened\n", [any(addr path)]) else none code = 0 end main
$ refine compile main.ldn -o system-arguments && ./system-arguments hello world 2 arguments 0: hello 1: world settings.conf: not found (errno 2), so the defaults apply