mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 08:12:37 +01:00
doc: Update architecture summary.
This commit is contained in:
parent
f6992ca3e1
commit
0d523f95e3
1 changed files with 27 additions and 69 deletions
|
@ -4,25 +4,19 @@
|
||||||
|
|
||||||
##### Single-threaded✝
|
##### Single-threaded✝
|
||||||
|
|
||||||
The design of `libircd` is fully-asynchronous, single-thread-oriented. No code
|
The design of `libircd` is fully-asynchronous, oriented around a single-thread
|
||||||
in the library _blocks_ the process. All operations are conducted on top of
|
event-loop. No code in the library _blocks_ the process. All operations are
|
||||||
a single `boost::asio::io_service` which must be supplied by the executable
|
conducted on top of a single `boost::asio::io_service` which must be supplied
|
||||||
linking to `libircd`. That `io_service` must be orchestrated by the executable
|
by the executable linking to `libircd`. That `io_service` must be run by the
|
||||||
at its discretion; typically the embedder's call to `ios.run()` is the only
|
executable at its discretion; typically the embedder's call to `ios.run()` is
|
||||||
place the process will _block_.
|
the only place the process will _block_.
|
||||||
|
|
||||||
> Generally, applications are limited by one or more of the following bounds:
|
The single-threaded approach ensures there is an _uninterrupted_, _uncontended_,
|
||||||
> Computing, Memory (Space), Memory (Peripheral I/O)
|
_predictable_ execution which is easy for developers to reason about intuitively
|
||||||
>
|
with sequential-consistency. This is ideal for the I/O-bound application being
|
||||||
> `libircd` is dominated by the **I/O bound**.
|
facilitated. If there are periods of execution which are computationally intense
|
||||||
|
like parsing, hashing, cryptography, etc: this is absorbed in lieu of thread
|
||||||
Our effort is rooted in the above assumption. The single-threaded approach
|
synchronization and bus contention.
|
||||||
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
|
This system achieves scale through running multiple independent instances which
|
||||||
synchronize at the application-logic level through passing the application's own
|
synchronize at the application-logic level through passing the application's own
|
||||||
|
@ -37,14 +31,12 @@ but it is heterogeneous.
|
||||||
##### Introduces userspace threading
|
##### Introduces userspace threading
|
||||||
|
|
||||||
IRCd presents an interface introducing stackful coroutines, a.k.a. userspace
|
IRCd presents an interface introducing stackful coroutines, a.k.a. userspace
|
||||||
context switching, a.k.a. green threads, a.k.a. fibers. The library avoids callbacks
|
context switching, a.k.a. green threads, a.k.a. fibers. The library avoids
|
||||||
as the way to break up execution when waiting for events. Instead, we harken back
|
callbacks as the way to break up execution when waiting for events. Instead, we
|
||||||
to the simple old ways of synchronous programming where control flow and data are
|
harken back to the simple old ways of synchronous programming where control
|
||||||
easy to follow.
|
flow and data are 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
|
||||||
If there are certain cases where we don't want a stack to linger which may
|
asynchronous pattern is still used (this is a hybrid system).
|
||||||
jeopardize the c10k'ness of the daemon the asynchronous pattern is still used,
|
|
||||||
thus this is a hybrid system.
|
|
||||||
|
|
||||||
Consider coroutines like "macro-ops" and asynchronous callbacks like
|
Consider coroutines like "macro-ops" and asynchronous callbacks like
|
||||||
"micro-ops." The pattern tends to use a coroutine to perform a large and
|
"micro-ops." The pattern tends to use a coroutine to perform a large and
|
||||||
|
@ -53,15 +45,7 @@ approach relegates the asynchronous callback pattern to simple tasks contained
|
||||||
within specific units which require scale, encapsulating the complexity away
|
within specific units which require scale, encapsulating the complexity away
|
||||||
from the rest of the project.
|
from the rest of the project.
|
||||||
|
|
||||||
##### Can be embedded in your application with very minimal overhead.
|
##### Runs only one server at a time
|
||||||
|
|
||||||
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. Users of
|
|
||||||
the library should never pay for what they don't use. The library should also
|
|
||||||
minimize conflicts with other libraries sharing the address space.
|
|
||||||
|
|
||||||
##### Runs only one server at a time.
|
|
||||||
|
|
||||||
Keeping with the spirit of simplicity of the original architecture, `libircd`
|
Keeping with the spirit of simplicity of the original architecture, `libircd`
|
||||||
continues to be a "singleton" object which uses globals and keeps actual server
|
continues to be a "singleton" object which uses globals and keeps actual server
|
||||||
|
@ -70,38 +54,12 @@ 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
|
of the original design, it has emerged over the decades as a very profitable
|
||||||
decision for making IRCd an accessible open source internet project.
|
decision for making IRCd an accessible open source internet project.
|
||||||
|
|
||||||
##### Leverages formal grammars
|
##### Formal grammars, RTTI, exceptions
|
||||||
|
|
||||||
We utilize the `boost::spirit` system of parsing and printing through formal grammars,
|
We utilize the `boost::spirit` system of parsing and printing through
|
||||||
rather than writing our own parsers manually. In addition, we build several tools
|
compile-time formal grammars, rather than writing our own parsers manually.
|
||||||
on top of such formal devices like a type-safe format string library acting as a
|
In addition, we build several tools on top of such formal devices like a
|
||||||
drop-in for `::sprintf()`, but accepting objects like `std::string` without `.c_str()`
|
type-safe format string library acting as a drop-in for `::sprintf()`, but
|
||||||
and prevention of outputting unprintable/unwanted characters that may have been
|
accepting objects like `std::string` without `.c_str()` and prevention of
|
||||||
injected into the system somewhere prior.
|
outputting unprintable/unwanted characters that may have been injected into
|
||||||
|
the system somewhere prior.
|
||||||
##### Modular design
|
|
||||||
|
|
||||||
`libircd` is designed specifically as a shared object library. The purpose of its
|
|
||||||
shared'ness is to facilitate IRCd's modular design: IRCd ships with many other
|
|
||||||
shared objects which introduce the "business logic" and features of the daemon. If
|
|
||||||
`libircd` was not a shared object, every single module would have to include large
|
|
||||||
amounts of duplicate code drawn from the static library. This would be a huge drag
|
|
||||||
on both compilation and the runtime performance.
|
|
||||||
|
|
||||||
```
|
|
||||||
|-------------|
|
|
||||||
---------------------- | | < ---- (module)
|
|
||||||
| | | |
|
|
||||||
| User's executable | <---- | libircd | < ---- (module)
|
|
||||||
| | | |
|
|
||||||
---------------------- | | < ---- (module)
|
|
||||||
|-------------|
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
The user (which we may also refer to as the "embedder" elsewhere in
|
|
||||||
documentation) only deals directly with `libircd` and not the modules.
|
|
||||||
`libircd` is generally loaded with its symbols bound globally in the executable
|
|
||||||
and on most platforms cannot be unloaded (or even loaded) manually and has not
|
|
||||||
been tested to do so. As an aside, we do not summarily dismiss the idea of
|
|
||||||
reload capability and would like to see it made possible.
|
|
||||||
|
|
Loading…
Reference in a new issue