0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 02:02:38 +01:00

ircd: Add various comments / documentations.

This commit is contained in:
Jason Volk 2018-12-19 12:24:16 -08:00
parent 0017a942e2
commit b4910319e0
3 changed files with 67 additions and 21 deletions

View file

@ -48,3 +48,10 @@ standard include group which includes any wrapping to hide SpiderMonkey.
- MAPI include group `<ircd/mapi.h>` is the standard header group for modules.
This group is an extension to the standard include group but has specific
tools for pluggable modules which are not part of the libircd core.
#### Invocation
> `libircd` is **not thread-safe**. It does not protect exposed interfaces with
locks. Embedders must access `libircd` from a single thread.
Initialize the library with a call to `ircd::init()`.

View file

@ -5,31 +5,36 @@ This directory contains definitions and linkage for `libircd`
The purpose of `libircd` is to facilitate the execution of a server which
handles requests from end-users. The library hosts a set of pluggable modules
which may introduce the actual application features (or the "business logic")
of the server. These additional modules are found in the `modules/` directory;
of the server.
##### libircd can be embedded in your application with very minimal overhead.
Linking to libircd from your executable allows you to customize and extend the
functionality of the server and have control over its execution, or, simply use
library routines provided by the library without any daemonization.
##### libircd runs only one server at a time.
Keeping with the spirit of simplicity of the original architecture, `libircd`
continues to be a "singleton" object which uses globals and keeps actual server
state in the library itself. In other words, **only one IRC daemon can exist
within a process's address space at a time.** Whether or not this was a pitfall
of the original design, it has emerged over the decades as a very profitable
decision for making IRCd an accessible open source internet project.
> The executable linking and invoking `libircd` may be referred to as the
"embedding" or just the "executable" interchangably in this documentation.
##### libircd is single-threaded✝
This methodology ensures there is an _uninterrupted_, _uncontended_,
_predictable_ execution. If there are periods of execution which are
computationally intense like parsing, hashing, cryptography, etc: this is
absorbed in lieu of thread synchronization and bus contention. Scaling this
system is done through running multiple independent instances which
synchronize with application logic.
The design of `libircd` is fully-asynchronous, single-thread-oriented. No code
in the library _blocks_ the process. All operations are conducted on top of
a single `boost::asio::io_service` which must be supplied by the executable
linking to `libircd`. That `io_service` must be orchestrated by the executable
at its discretion; typically the embedder's call to `ios.run()` is the only
place the process will _block_.
> Applications are limited by one or more of the following bounds:
- Computing: program is limited by the efficiency of the CPU over time.
- Space: program is limited by the space available for its dataset.
- I/O: program is limited by external events, disks, and networks.
`libircd` is dominated by the **I/O bound**. Its design is heavily optimized
for this assumption with its single-thread orientation. This methodology
ensures there is an _uninterrupted_, _uncontended_, _predictable_ execution
which is easy for developers to reason about intuitively with
sequential-consistency in a cooperative coroutine model.
If there are periods of execution which are computationally intense like
parsing, hashing, cryptography, etc: this is absorbed in lieu of thread
synchronization and bus contention. This system achieves scale through running
multiple independent instances which synchronize at the application-logic
level.
✝ However, don't start assuming a truly threadless execution for the entire
address space. If there is ever a long-running background computation or a call
@ -48,6 +53,21 @@ easy to follow.
✝ If there are certain cases where we don't want a stack to linger which may
jeopardize the c10k'ness of the daemon the asynchronous pattern is still used.
##### libircd can be embedded in your application with very minimal overhead.
Linking to libircd from your executable allows you to customize and extend the
functionality of the server and have control over its execution, or, simply use
library routines provided by the library without any daemonization.
##### libircd runs only one server at a time.
Keeping with the spirit of simplicity of the original architecture, `libircd`
continues to be a "singleton" object which uses globals and keeps actual server
state in the library itself. In other words, **only one IRC daemon can exist
within a process's address space at a time.** Whether or not this was a pitfall
of the original design, it has emerged over the decades as a very profitable
decision for making IRCd an accessible open source internet project.
##### libircd leverages formal grammars
We utilize the `boost::spirit` system of parsing and printing through formal grammars,

View file

@ -672,6 +672,13 @@ ircd::fs::read(const string_view &path,
return read(fd, bufs, opts);
}
/// Read from file descriptor fd into buffers. The number of bytes read into
/// the buffers is returned. By default (via read_opts.all) this call will
/// loop internally until the buffers are full or EOF. To allow for a partial
/// read(), disable read_opts.all. Note that to maintain alignments (i.e when
/// direct-io or for special files read_opts.all must be false). By default
/// (via read_opts.interruptible) this call can throw if the syscall was
/// interrupted before reading any bytes.
size_t
ircd::fs::read(const fd &fd,
const mutable_buffers &bufs,
@ -700,6 +707,12 @@ ircd::fs::read(const fd &fd,
return ret;
}
/// Lowest-level read() call. This call only conducts a single operation
/// (no looping) and can return a partial read(). It does have branches
/// for various read_opts. The arguments involve `struct ::iovec` which
/// we do not expose to the ircd.h API; thus this function is internal to
/// ircd::fs. There is no reason to use this function in lieu of the public
/// fs::read() suite.
size_t
ircd::fs::read(const fd &fd,
const const_iovec_view &iov,
@ -941,6 +954,12 @@ ircd::fs::write(const fd &fd,
return off;
}
/// Lowest-level write() call. This call only conducts a single operation
/// (no looping) and can return early with a partial write(). It does have
/// branches for various write_opts. The arguments involve `struct ::iovec`
/// which we do not expose to the ircd.h API; thus this function is internal to
/// ircd::fs. There is no reason to use this function in lieu of the public
/// fs::read() suite.
size_t
ircd::fs::write(const fd &fd,
const const_iovec_view &iov,