mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-06-23 00:01:19 -04:00
Compare commits
543 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
8f7f82d2c1 | ||
|
d3cb04a67e | ||
|
c78db1a757 | ||
|
4a19b2eea9 | ||
|
fdd2593e33 | ||
|
c39449a631 | ||
|
f195295e3d | ||
|
17665689f5 | ||
|
f26d70d642 | ||
|
730033c0f1 | ||
|
cc0274dd2f | ||
|
b971fa1cca | ||
|
2d9e24a67f | ||
|
ae0eaa2dfd | ||
|
681400c18e | ||
|
b41d4d8a49 | ||
|
9b939abedd | ||
|
61f738df51 | ||
|
eb8fe3ef82 | ||
|
debe35621e | ||
|
dd13303a4a | ||
|
216ccff845 | ||
|
a65fd2e612 | ||
|
f8c9441852 | ||
|
8364428147 | ||
|
d2a3e21bc4 | ||
|
424f5e8c96 | ||
|
89019ddd3d | ||
|
534f89cf0e | ||
|
9ca440ac5c | ||
|
e2dc1d79e5 | ||
|
0c414327d1 | ||
|
0f6b65dea2 | ||
|
cc2cd3da32 | ||
|
d47b5e29f7 | ||
|
c2d314b930 | ||
|
33d4e01a30 | ||
|
c45978252a | ||
|
37840760b1 | ||
|
8cb86a703e | ||
|
12721820e4 | ||
|
32e501a198 | ||
|
a21b507de8 | ||
|
54df8fdd62 | ||
|
2cd09925d0 | ||
|
642bdbef7e | ||
|
574afc103a | ||
|
17562f24fe | ||
|
8ef76f06bf | ||
|
77d881014d | ||
|
e32331a835 | ||
|
3e67f7d4cb | ||
|
3b2a67966e | ||
|
2c5eb612db | ||
|
ab12b0b77c | ||
|
c023b2e750 | ||
|
687017078a | ||
|
2146c8a181 | ||
|
7d718405a6 | ||
|
d834d7391f | ||
|
d26184dbf7 | ||
|
73f913c108 | ||
|
62c1925dfe | ||
|
b126756eb8 | ||
|
3c93b4405c | ||
|
bd2c92e7ba | ||
|
a0cb744256 | ||
|
49c9774ee3 | ||
|
d3f30696c2 | ||
|
c1c2d634de | ||
|
7c9396ef19 | ||
|
58aa3f6663 | ||
|
b8a99fa036 | ||
|
b128edce66 | ||
|
3be614e86f | ||
|
321bc093b4 | ||
|
1776925870 | ||
|
94ab6cb65f | ||
|
c53d897cbd | ||
|
f2ce0c26ed | ||
|
7608cbaa60 | ||
|
911ccc8f6a | ||
|
12530ebeca | ||
|
14ae3cfee3 | ||
|
6ae124ecc5 | ||
|
34b650bd47 | ||
|
240e04f761 | ||
|
15f2047323 | ||
|
9bbd4e0108 | ||
|
edfe8debb2 | ||
|
f3f24738c4 | ||
|
ce30c9a270 | ||
|
feb8d11d91 | ||
|
82dcca77bf | ||
|
ed9c4a5574 | ||
|
ebf7fa0230 | ||
|
5e6618168c | ||
|
fb731b5161 | ||
|
e48f6114b1 | ||
|
7b58999f51 | ||
|
6309314933 | ||
|
ef415fbdfe | ||
|
31ee72e25a | ||
|
ca121eea64 | ||
|
6ee8ab97b8 | ||
|
261b583c5b | ||
|
ec576100ef | ||
|
57c02073ee | ||
|
e5444c0f8b | ||
|
4f3ec08ef5 | ||
|
332adbd514 | ||
|
d33f8c2d57 | ||
|
02fbb947e8 | ||
|
6dcc452a7e | ||
|
c2f22d85eb | ||
|
1cbcda0ce1 | ||
|
59814f61b1 | ||
|
c3a43003bc | ||
|
a4bd5d79c4 | ||
|
b9a0c20c2c | ||
|
301b479fa6 | ||
|
f9ba4caf3d | ||
|
3adce92e8a | ||
|
f5232a0c17 | ||
|
db8672b737 | ||
|
250affff67 | ||
|
43bd3b852e | ||
|
7b781b56b6 | ||
|
82c47a25b2 | ||
|
91ca880220 | ||
|
2f6a5790ba | ||
|
2c005eddaf | ||
|
666c5236d7 | ||
|
6b5a5366c6 | ||
|
717af4433e | ||
|
bf7348497c | ||
|
ca4767bc96 | ||
|
17b976f37c | ||
|
77c111814f | ||
|
e9864b96fb | ||
|
d979cc09fc | ||
|
a9e552fafe | ||
|
11ab66c2e7 | ||
|
299c033a9a | ||
|
14f7dddf44 | ||
|
913b501bd7 | ||
|
017bfd8c03 | ||
|
b1808e6656 | ||
|
d42bf6446c | ||
|
92a21c6ce5 | ||
|
e433e7498e | ||
|
964ed27305 | ||
|
07878b7f59 | ||
|
87d6a990af | ||
|
5052181006 | ||
|
6dcc5e2027 | ||
|
c4cb2737d5 | ||
|
e48c5e9b81 | ||
|
0776a7d60a | ||
|
4a91a679e1 | ||
|
d9a7e20a2b | ||
|
41e6e46cf4 | ||
|
80dd943f80 | ||
|
b68d396787 | ||
|
5497bdda48 | ||
|
da4f6c3978 | ||
|
1c8c759f09 | ||
|
c502574915 | ||
|
f4386bb5bc | ||
|
ffe4920127 | ||
|
09c282d1e8 | ||
|
ccf1ba770d | ||
|
122c3b1be9 | ||
|
71faca6414 | ||
|
f06f4a4ff2 | ||
|
464a5623b0 | ||
|
8d6e6bab83 | ||
|
cfafb22fb6 | ||
|
81bce87e3f | ||
|
4856fc430d | ||
|
2aaea3f48e | ||
|
d338f8bc61 | ||
|
cbb6ece7b2 | ||
|
c9db164b8b | ||
|
c42de1e493 | ||
|
b942dde3b3 | ||
|
19c43d7153 | ||
|
fbe8a71cb8 | ||
|
ca1d239507 | ||
|
c6807267d2 | ||
|
5e014fcd17 | ||
|
c88c58e835 | ||
|
4db993d8d6 | ||
|
69b115054c | ||
|
21e05a834a | ||
|
0751f02e6b | ||
|
a26c3ebccc | ||
|
538d3840c5 | ||
|
d2410e51d5 | ||
|
b388d67aa4 | ||
|
211279e8dc | ||
|
997f34949f | ||
|
ffe69561d2 | ||
|
efad0145a1 | ||
|
fc7c541d7d | ||
|
8a71a90c9a | ||
|
5ab8302ce7 | ||
|
bdc42827c5 | ||
|
cd6f4dfee6 | ||
|
1d45280f96 | ||
|
eb64c46f85 | ||
|
fc930ca77e | ||
|
da975f06bf | ||
|
c286d1047d | ||
|
cea0546c4c | ||
|
c7c2f72e6f | ||
|
9537ca1810 | ||
|
cf4da1a369 | ||
|
bc1e231b64 | ||
|
d618731781 | ||
|
00bcf7c79c | ||
|
3c8b2c81df | ||
|
6e6ae312e8 | ||
|
c721a076c7 | ||
|
9e1872c10c | ||
|
ddcf89983d | ||
|
5a11ea6df2 | ||
|
60e67472e3 | ||
|
e96c444d66 | ||
|
ee51b04408 | ||
|
c6067a9059 | ||
|
8da6a7d7f1 | ||
|
669c2e86c0 | ||
|
121f5051ab | ||
|
434fb81e14 | ||
|
8ff3fb135f | ||
|
23a1a84a13 | ||
|
5b127ad26a | ||
|
69c622fa01 | ||
|
6a85a11fc7 | ||
|
4db6533fa6 | ||
|
9158f45b88 | ||
|
4347a22a16 | ||
|
e45a9a1442 | ||
|
166118bfe7 | ||
|
fa5bc53726 | ||
|
082bf00ccc | ||
|
482d247694 | ||
|
bcee2e804d | ||
|
1ef8ad4913 | ||
|
7c94ccbd28 | ||
|
f169082a47 | ||
|
e14ebca077 | ||
|
9256754fe8 | ||
|
9e445f19a1 | ||
|
afb83bf1fa | ||
|
1938ce5ad0 | ||
|
f1be218b26 | ||
|
d8da454b2c | ||
|
7c4a3adc6e | ||
|
602e1d8ae3 | ||
|
b741881d74 | ||
|
3fde20c16c | ||
|
10ed8df8fd | ||
|
137399aa6d | ||
|
19c42eb7a4 | ||
|
d667d4fa95 | ||
|
ad7149dc29 | ||
|
9d5aadc3eb | ||
|
610b4c0653 | ||
|
51f33d4539 | ||
|
387fb6d2b9 | ||
|
c8abd7ca78 | ||
|
286a1b743d | ||
|
b184cb4b3b | ||
|
1bba7b156a | ||
|
f340d92a79 | ||
|
5b3578a428 | ||
|
ec6e82b1f1 | ||
|
d8f4884e99 | ||
|
6083d1d867 | ||
|
490873e79a | ||
|
325bcbd494 | ||
|
f37f37d748 | ||
|
31629a17c8 | ||
|
e948fa7877 | ||
|
d5ebfd496a | ||
|
0d2c8f5907 | ||
|
432e1031b3 | ||
|
ad0c9122a7 | ||
|
1b2ea52620 | ||
|
561a92c33b | ||
|
1493f01779 | ||
|
24571692f1 | ||
|
38a9d93620 | ||
|
f81880d293 | ||
|
b755d9e41f | ||
|
90af8f755a | ||
|
57d08881dc | ||
|
bb474070bb | ||
|
95c91c061c | ||
|
47f4d2034c | ||
|
5d8a48c20d | ||
|
95a58dc711 | ||
|
355f8dabf2 | ||
|
5fabef0fd7 | ||
|
e5a0e54bc3 | ||
|
5c5aa23df3 | ||
|
e10e176da3 | ||
|
7bb7c2b59b | ||
|
3fe575538d | ||
|
d29cf2e4ca | ||
|
b3b3c9fd3e | ||
|
406efc8ff9 | ||
|
f69ba326ec | ||
|
733f71f3a4 | ||
|
7251db6a1b | ||
|
38d97996dc | ||
|
57ace76003 | ||
|
fc68c00ac6 | ||
|
cc19aa1606 | ||
|
b4b3540694 | ||
|
bd4cf9fec1 | ||
|
091316a0e6 | ||
|
1c891a45cf | ||
|
c87893cf05 | ||
|
75c27bf50e | ||
|
d063513ddf | ||
|
35b93c0c2e | ||
|
dcf8624cde | ||
|
767f90d964 | ||
|
3e49036b63 | ||
|
43308adfe2 | ||
|
da958b6d81 | ||
|
6d286e82fb | ||
|
8c79ca833c | ||
|
6d782081d2 | ||
|
148f8cd3cb | ||
|
a6c0be9aff | ||
|
feeeac9e55 | ||
|
d262afbb37 | ||
|
cc400c27b1 | ||
|
264a7d0751 | ||
|
99ee95172e | ||
|
dbcbd64882 | ||
|
ce83e85327 | ||
|
5f171313ff | ||
|
85adab31bc | ||
|
081e7549ba | ||
|
687ebf99a6 | ||
|
1437b238a6 | ||
|
73ce323948 | ||
|
9cf5f35063 | ||
|
bd77643795 | ||
|
75ce40e26b | ||
|
0325b6742c | ||
|
d47d5779b3 | ||
|
ac99f3162c | ||
|
0453510d5a | ||
|
c0b2cd0c4c | ||
|
ccf147474e | ||
|
739cb87f97 | ||
|
349a41c716 | ||
|
b879f87b84 | ||
|
8fa37d51f5 | ||
|
bf25e24f9d | ||
|
81325ebae7 | ||
|
9793ae03f7 | ||
|
bce6a871b8 | ||
|
92c16d9405 | ||
|
bc8bd22f39 | ||
|
0b18c3c060 | ||
|
3d96450533 | ||
|
1cd01b5218 | ||
|
188dc9ae6d | ||
|
addef140c3 | ||
|
f959c72504 | ||
|
a407535606 | ||
|
41c3a2baa4 | ||
|
21c6a54200 | ||
|
7c984b7f0a | ||
|
c1e3acabe1 | ||
|
d3068fedc9 | ||
|
7e9c4c038b | ||
|
55b71cb28a | ||
|
42ea36b8ea | ||
|
1cf3f2c733 | ||
|
950b1a881e | ||
|
702299d956 | ||
|
439e53862a | ||
|
cab124d5e0 | ||
|
b5b5de777f | ||
|
bc16038285 | ||
|
357a8f7169 | ||
|
393ec686e3 | ||
|
9a9c02ba08 | ||
|
e5b57fab32 | ||
|
f3d70518fa | ||
|
695499e214 | ||
|
fa934d09c2 | ||
|
106ea8a797 | ||
|
46105436d2 | ||
|
7fe1080e94 | ||
|
0917e26e3e | ||
|
40d758b362 | ||
|
ec54ccb9e7 | ||
|
4bd46b5e84 | ||
|
a9e2943a92 | ||
|
e6092958a7 | ||
|
cf6ba07b45 | ||
|
29d41d4023 | ||
|
df197a82ce | ||
|
7ea93f2bc3 | ||
|
0c28312081 | ||
|
86501ab97f | ||
|
21b7f12322 | ||
|
a92f329ff2 | ||
|
fdc396126f | ||
|
5ba047f25d | ||
|
170f7e4244 | ||
|
543d77be5a | ||
|
f55c105f8a | ||
|
180c44dab1 | ||
|
e8bb91c1a6 | ||
|
24e6238e6d | ||
|
2f0425edee | ||
|
92f416f0e8 | ||
|
2a1478b695 | ||
|
45c9a50641 | ||
|
fc9960e138 | ||
|
b274000728 | ||
|
2fdd4cc712 | ||
|
0fb95cdf1b | ||
|
0a8762af4b | ||
|
dfb50bf01d | ||
|
9831ed81c6 | ||
|
b5d56f7acd | ||
|
14e0bde730 | ||
|
8ce7edecb6 | ||
|
aa4ae98d62 | ||
|
9656b89ffa | ||
|
4fac85f8b0 | ||
|
1277485f9b | ||
|
e605f06c29 | ||
|
72f9d77642 | ||
|
cdaa323983 | ||
|
233cf01006 | ||
|
39179a2f4e | ||
|
c1f47f805e | ||
|
50558576b6 | ||
|
244581bcce | ||
|
2f9ebe1955 | ||
|
bcc49970cf | ||
|
83b764cf96 | ||
|
3c7277f220 | ||
|
7c625fa7c3 | ||
|
609b13c2dd | ||
|
d051d31257 | ||
|
19701cb7f8 | ||
|
dd66ff981e | ||
|
10486fe2eb | ||
|
38cc9d5b46 | ||
|
6d95b9e37d | ||
|
fb9225778a | ||
|
02f6954348 | ||
|
3ae2925cfe | ||
|
bee7d1675a | ||
|
4c6f020e9c | ||
|
8d005fff87 | ||
|
a4305b200a | ||
|
0a96e92880 | ||
|
2a0c5acf06 | ||
|
3b309e8066 | ||
|
f7fa3ad69b | ||
|
2c365aa911 | ||
|
2c4a01b29e | ||
|
5ffe8019f5 | ||
|
6b557ed40b | ||
|
b70b4b6064 | ||
|
37ec03459b | ||
|
1353ee067e | ||
|
0f0d4072cc | ||
|
de3153c6bf | ||
|
a48368c3ee | ||
|
970833b393 | ||
|
d10a720134 | ||
|
16ec3592e8 | ||
|
d105bd31a3 | ||
|
56da38f4f4 | ||
|
3e8f8d689d | ||
|
fb97c16cf6 | ||
|
0bec10cd86 | ||
|
eef510c7d8 | ||
|
9d968dc893 | ||
|
39c981b03f | ||
|
1b198cc539 | ||
|
0f1bea6f53 | ||
|
b0f80ccaff | ||
|
569ac31a1c | ||
|
146d246f23 | ||
|
8118c1f500 | ||
|
0a4b3f98e8 | ||
|
8164a1385c | ||
|
35f4be5a59 | ||
|
08edcc107f | ||
|
75762976da | ||
|
2c90835cdb | ||
|
6939cd1803 | ||
|
4cc9e1360e | ||
|
eab55876f3 | ||
|
36c970fb62 | ||
|
741ea5a8f6 | ||
|
dba1d7890b | ||
|
cda2efc6c3 | ||
|
3f3aab4338 | ||
|
4b58f8b53f | ||
|
a696a23742 | ||
|
e2eeba0ec4 | ||
|
3b0ae1352f | ||
|
e19bc4a912 | ||
|
49267689ef | ||
|
e1e7cbe6b3 | ||
|
d30f20908e | ||
|
fd33336786 | ||
|
76ffd669ef | ||
|
14fd63a5c8 | ||
|
554179071b | ||
|
27cf787c09 | ||
|
e858a8cfd7 | ||
|
e332fdbfec | ||
|
4f0b331a8d | ||
|
4a15c8e2b7 | ||
|
45efcc4a57 | ||
|
32a30889b8 | ||
|
0ca5355385 | ||
|
f9b292452c | ||
|
1c95a7395e | ||
|
53b35c0418 | ||
|
3eb6806160 | ||
|
5b63eb3eb5 | ||
|
be59066fda | ||
|
4ce67773e7 | ||
|
3a6505fb0f |
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# To work around MDX issues
|
||||
README.md text eol=lf
|
||||
CHANGES.md whitespace=-blank-at-eol
|
66
.github/workflows/main.yml
vendored
Normal file
66
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
name: Main workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
ocaml-compiler:
|
||||
- 5.2.x
|
||||
local-packages:
|
||||
- eio eio_posix eio_main
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use OCaml ${{ matrix.ocaml-compiler }}
|
||||
uses: ocaml/setup-ocaml@v2
|
||||
with:
|
||||
ocaml-compiler: ${{ matrix.ocaml-compiler }}
|
||||
opam-local-packages:
|
||||
opam-disable-sandboxing: true
|
||||
|
||||
- run: opam --cli=2.1 pin -yn --with-version=dev .
|
||||
- run: opam install ${{ matrix.local-packages }} --deps-only --with-test
|
||||
- run: opam install ${{ matrix.local-packages }} --with-test
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set-up OCaml
|
||||
uses: ocaml/setup-ocaml@v2
|
||||
with:
|
||||
opam-pin: false
|
||||
opam-depext: false
|
||||
ocaml-compiler: ocaml.5.2.0,ocaml-option-mingw
|
||||
opam-repositories: |
|
||||
dra27: https://github.com/dra27/opam-repository.git#windows-5.0
|
||||
normal: https://github.com/ocaml/opam-repository.git
|
||||
# --with-version=dev is not available, and --with-test also tries running tests for packages (like MDX) which fail...
|
||||
- run: |
|
||||
opam pin -yn eio.dev .
|
||||
opam pin -yn eio_windows.dev .
|
||||
opam pin -yn eio_main.dev .
|
||||
opam install eio eio_windows eio_main --deps-only --with-test
|
||||
- run: opam exec -- dune build
|
||||
- run: opam exec -- dune runtest
|
||||
- run: opam exec -- dune exec -- ./examples/net/main.exe
|
||||
- run: opam exec -- dune exec -- ./examples/fs/main.exe
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build the Docker image
|
||||
run: docker build .
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
_build
|
||||
_opam
|
||||
.ocamlformat
|
||||
.*.swp
|
||||
*.install
|
||||
|
571
CHANGES.md
571
CHANGES.md
@ -1,3 +1,574 @@
|
||||
## v1.2
|
||||
|
||||
Changes:
|
||||
|
||||
- Make `fork_action.h` a public header (@patricoferris #769, reviewed by @talex5).
|
||||
Allows other libraries to add new actions.
|
||||
|
||||
- Record trace event when spawning processes (@talex5 #749).
|
||||
Spawning a subprocess can take a long time in some cases, so show it clearly in the traces.
|
||||
|
||||
- Eio_unix.Net: make some return types more polymorphic (@talex5 #744).
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Preserve backtraces in `fork_daemon` (@talex5 #779).
|
||||
|
||||
- Eio.Path: always use "/" as separator (@talex5 #743).
|
||||
|
||||
Linux backend:
|
||||
|
||||
- Allow `alloc_fixed_or_wait` to be cancelled (@talex5 #753).
|
||||
|
||||
- Avoid triggering a (harmless) TSan warning (@talex5 #754, reported by @avsm).
|
||||
|
||||
Windows backend:
|
||||
|
||||
- Unregister FDs on cancel (@talex5 #756).
|
||||
Fixes `exception Unix.Unix_error(Unix.ENOTSOCK, "select", "")`.
|
||||
|
||||
- Work around problems in `Unix.getaddrinfo` (@talex5 #780).
|
||||
Fixes e.g. `No addresses found for host name "127.0.0.1"`.
|
||||
|
||||
- Group `ECONNABORTED` with other connection reset errors (@talex5 #783).
|
||||
|
||||
- Check `has_symlink` for tests (@create2000 #771, reviewed by @patricoferris and @talex5).
|
||||
|
||||
- Improve `openat` error handling (@talex5 #742, reported by @kentookura).
|
||||
Fixes `exception Unix.Unix_error(Unix.ENOENT, "openat", "")`.
|
||||
|
||||
Documentation:
|
||||
|
||||
- examples/fs: show how to read files while scanning (@talex5 #745).
|
||||
|
||||
- Add example to `Buf_read.seq` documentation (@talex5 #739, requested by @darrenldl and @rizo).
|
||||
|
||||
Build and test:
|
||||
|
||||
- Fix tests on OpenBSD (@talex5 #782).
|
||||
|
||||
- Add advice about using AI for code generation (@patricoferris #765, reviewed by @avsm and @talex5).
|
||||
|
||||
- Minor code cleanups (@talex5 #755).
|
||||
|
||||
- Define `struct clone_args` for linux-lts versions that don't have it (@copy #741, reviewed by @talex5).
|
||||
|
||||
- eio_linux: refactor fixed buffer code (@talex5 #752).
|
||||
|
||||
## v1.1
|
||||
|
||||
New features:
|
||||
|
||||
- Add `Eio.Path.symlink` (@patricoferris #715, reviewed by @talex5).
|
||||
|
||||
- Add `Eio.Pool.use ~never_block` (@SGrondin #657, reviewed by @talex5).
|
||||
|
||||
- Add `Eio_unix.Net.import_socket_listening` (@alyssais #733).
|
||||
|
||||
- Add `Eio.Time.Timeout.sleep` (@talex5 #726).
|
||||
|
||||
Documentation:
|
||||
|
||||
- Add `examples/fs` showing how to walk a directory tree (@talex5 #730).
|
||||
|
||||
- README: explain that `read_all` reads until shutdown (@talex5 #717, reported by @Wenke-D).
|
||||
|
||||
- Use long dash in README title (@lucperkins #718).
|
||||
|
||||
Linux backend:
|
||||
|
||||
- Require Linux >= 5.15 (@talex5 #720, reviewed by @SGrondin and @avsm).
|
||||
Removes a work-around that required checking whether every flow was a tty.
|
||||
|
||||
- Don't call submit immediately before wait (@talex5 #728).
|
||||
This is slightly faster and makes the traces clearer.
|
||||
|
||||
- Don't record submit events when there's nothing to submit (@talex5 #729).
|
||||
Makes the traces a bit clearer.
|
||||
|
||||
- Split flow into its own file (@talex5 #727).
|
||||
|
||||
- Add work-around for signals race (@talex5 #734).
|
||||
|
||||
POSIX backend:
|
||||
|
||||
- Add `_BSD_SOURCE` flag to fix build on OpenBSD (@prgbln #722).
|
||||
|
||||
- Fix sandboxed path resolution on OpenBSD (@jebrosen #723, reviewed by @talex5).
|
||||
OpenBSD uses `ELOOP` when opening a symlink with `O_NOFOLLOW`.
|
||||
|
||||
Build and test:
|
||||
|
||||
- Benchmarks: record uname, Eio backend, and number of cores (@talex5 #719).
|
||||
|
||||
- Update to MDX 2.4.1 for OCaml 5.2 (@talex5 #712).
|
||||
|
||||
## v1.0
|
||||
|
||||
New features:
|
||||
|
||||
- Add `Eio_unix.Cap` module to enable Capsicum mode (@talex5 #697, reviewed by @SGrondin).
|
||||
|
||||
- eio_linux: expose more functions in the `Low_level` module (@talex5 #705, reviewed by @SGrondin).
|
||||
Add all the functions used by other parts of eio_linux (`openat`, `mkdir`, `read_link`, `unlink`, `rename` and `pipe`).
|
||||
Tidied the API up a bit too:
|
||||
- `mkdir_beneath` is now just `mkdir`.
|
||||
- `statx_confined` is now just `statx`.
|
||||
- `open_dir` is gone; the single user now calls `openat` directly.
|
||||
|
||||
Documentation:
|
||||
|
||||
- Add README documentation for `Eio.Executor_pool` (@SGrondin @talex5 #707, reviewed by @Sudha247).
|
||||
|
||||
- eio_linux: remove logging (@talex5 #708, requested by @clecat).
|
||||
There were only two remaining uses of Logs, neither of which has proved useful.
|
||||
|
||||
Build:
|
||||
|
||||
- Add upper-bound on MDX (@talex5 #706).
|
||||
The new version attempts to execute included blocks.
|
||||
|
||||
- Fix tests to pass with both old and new Kcas (@polytypic #704).
|
||||
|
||||
- Make posix `open_beneath` test idempotent (@SGrondin #703).
|
||||
|
||||
- Executor_pool: mention requested weight in error message (@talex5 #702, reported by @yawaramin).
|
||||
|
||||
## v0.15
|
||||
|
||||
New features:
|
||||
|
||||
- eio_posix: use directory FDs instead of realpath (@talex5 #694 #696, reviewed by @SGrondin).
|
||||
Using realpath was an old hack from the libuv days and subject to races. It was also slow.
|
||||
|
||||
- Keep pool of systhreads for blocking operations (@SGrondin @talex5 #681).
|
||||
This is much faster than creating a new thread for each operation.
|
||||
It mainly benefits the eio_posix backend, as that uses lots of systhreads.
|
||||
|
||||
- Make `Switch.on_release` thread-safe (@talex5 #684, requested by @art-w and @clecat).
|
||||
This allows resource pools to be shared between domains easily.
|
||||
|
||||
- Add `Eio.Path.read_link` (@talex5 #686).
|
||||
|
||||
- Add `Eio_unix.Fd.is_open` (@talex5 #690).
|
||||
|
||||
- Include backtrace in systhread errors (@talex5 #688, reviewed by @SGrondin).
|
||||
Also, add `Eio.Exn.empty_backtrace` as a convenience.
|
||||
|
||||
- eio.mock: add tracing support to mock backend (@talex5 #687).
|
||||
|
||||
- Improve tracing (@talex5 #675 #683 #676, reviewed by @SGrondin).
|
||||
Update tracing section of README and trace more things
|
||||
(`run_in_systhread`, `close`, `submit`, `traceln`, cancellation and domain spawning).
|
||||
|
||||
Documentation:
|
||||
|
||||
- Link to verification work in docs (@talex5 #682).
|
||||
|
||||
- Add more trace diagrams to README (@talex5 #698).
|
||||
|
||||
- Adjust COC contacts (@polytypic #685, reviewed by @Sudha247).
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- eio_linux: retry `openat2` on `EAGAIN` (@talex5 #693, reviewed by @SGrondin).
|
||||
|
||||
- eio_posix and eio_windows: check for IO periodically (@talex5 #674).
|
||||
|
||||
- Handle EPERM when trying to initialise uring (@talex5 #691).
|
||||
This can happen when using a Docker container.
|
||||
|
||||
Build and tests:
|
||||
|
||||
- Benchmark `Eio_unix.run_in_systhread` (@talex5 #678, reviewed by @SGrondin).
|
||||
|
||||
- Enable lintcstubs for `Eio_unix.Private` too (@talex5 #689).
|
||||
|
||||
- Stat benchmark: report cleanup time and optimise (@talex5 #692).
|
||||
|
||||
- Make benchmarks start faster (@talex5 #673).
|
||||
|
||||
- Update build for new eio-trace CLI (@talex5 #699).
|
||||
|
||||
- Expect opam-repo-ci tests to fail on macos (@talex5 #672).
|
||||
|
||||
## v0.14
|
||||
|
||||
New features / API changes:
|
||||
|
||||
- Add `Eio.Executor_pool` (@SGrondin #639, reviewed by @talex5).
|
||||
Provides an easy way to distribute jobs across domains.
|
||||
|
||||
- Add `Fiber.first ~combine` and `Fiber.n_any` (@SGrondin @talex5 #587).
|
||||
Allows keeping both results in the case where multiple fibers succeed.
|
||||
|
||||
- Add `Eio_mock.Backend.run_full` with auto-advancing mock clock (@talex5 #644, reviewed by @SGrondin).
|
||||
Simplifies testing of code using clocks.
|
||||
|
||||
- Add `Buf_write.printf` (@SGrondin @talex5 #655).
|
||||
|
||||
- Add `Net.listening_addr` (@mefyl #555, reviewed by @patricoferris @talex5).
|
||||
Useful to get the socket's address if the OS assigns it.
|
||||
|
||||
- Add `Promise.try_resolve` (@talex5 #646).
|
||||
|
||||
- Remove `Cancel_hook_failed` exception (@talex5 #640).
|
||||
Didn't seem to be used and broke dscheck.
|
||||
|
||||
Tracing:
|
||||
|
||||
- Improve tracing (@TheLortex @patricoferris @talex5 #656).
|
||||
Trace cancellation contexts and OS operations, and simplify API.
|
||||
|
||||
- Add labels to switches (@talex5 #661, reviewed by @SGrondin).
|
||||
|
||||
- `Fiber.all`: use the parent fiber (@talex5 #665, reviewed by @SGrondin).
|
||||
Cleans up the traces a bit.
|
||||
|
||||
Performance:
|
||||
|
||||
- Faster and simpler `Lf_queue` (@talex5 #647, based on work by @polytypic).
|
||||
|
||||
- Optimise `Flow.copy` with `Buf_read.as_flow` (@talex5 #663, reviewed by @SGrondin, reported by @leostera).
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fix handling of very long IO vectors (@talex5 #653, reported by @Cjen1).
|
||||
|
||||
- eio_posix: use `caml_enter_blocking_section` in more places (@talex5 #654, reviewed by @SGrondin).
|
||||
|
||||
- eio_posix: work around `caml_unix_alloc_sockaddr` bug (@talex5 #651).
|
||||
|
||||
- Remove default backtrace from `Switch.fail` (@talex5 #664).
|
||||
|
||||
Documentation:
|
||||
|
||||
- Organise eio.mli better (@talex5 #667).
|
||||
|
||||
- Fix quoting of quotes in process error messages (@talex5 #666, reviewed by @SGrondin).
|
||||
|
||||
- Mention Path module in File and Fs documentation (@talex5 #659, requested by @clecat).
|
||||
|
||||
- Minor documentation updates (@SGrondin @talex5 #670).
|
||||
|
||||
Build / internals:
|
||||
|
||||
- Allow closing synchronous streams (@talex5 #641, reviewed by @SGrondin).
|
||||
This isn't currently exposed in the public interface.
|
||||
|
||||
- Fix non-idempotent tests (@SGrondin #662).
|
||||
|
||||
- eio_windows: add explicit fmt dependency (@talex5 #643).
|
||||
|
||||
## v0.13
|
||||
|
||||
New features / API changes:
|
||||
|
||||
- Add `Flow.read_all` (@SGrondin #596, reviewed by @talex5 @rbjorklin).
|
||||
|
||||
- Add `Path.stat` (@patricoferris @talex5 @avsm #617 #618 #624 #620, reviewed by @SGrondin).
|
||||
|
||||
- Add `Path.rmtree` (@talex5 #627 #628, reviewed by @SGrondin).
|
||||
|
||||
- Add `Path.mkdirs` and `Path.split` (@patricoferris @talex5 #625).
|
||||
|
||||
- Add `Eio.File.{seek,sync,truncate}` (@talex5 #626).
|
||||
|
||||
- Add `Eio.Path.{kind,is_file,is_directory}` (@patricoferris @talex5 #623, reviewed by @avsm).
|
||||
|
||||
- Switch from CTF to OCaml 5.1 runtime events (@TheLortex @patricoferris @talex5 #634 #635, reviewed by @avsm).
|
||||
This is a minimal initial version.
|
||||
|
||||
Documentation:
|
||||
|
||||
- Document `File.Stat` record fields (@avsm @talex5 #621).
|
||||
|
||||
- Update README section about `env` (@talex5 #614, reported by @jonsterling).
|
||||
|
||||
Build and test changes:
|
||||
|
||||
- Add `File.stat` benchmark (@talex5 #616).
|
||||
|
||||
- Add `Path.stat` benchmark (@patricoferris @talex5 #630).
|
||||
|
||||
- eio_linux: mark as only available on Linux (@talex5 #629).
|
||||
|
||||
- Make MDX tests idempotent (@SGrondin #601, reviewed by @talex5).
|
||||
|
||||
- Allow trailing whitespace in CHANGES.md (@talex5 #632).
|
||||
|
||||
- Update minimum OCaml version to 5.1 (@talex5 #631).
|
||||
|
||||
- Generate prototypes for C stubs from ml files (@talex5 #615).
|
||||
|
||||
- Don't try to compile uring support on centos 7 (@talex5 #638, reported by @zenfey).
|
||||
|
||||
## v0.12
|
||||
|
||||
New features / API changes:
|
||||
|
||||
- Replace objects with variants (@talex5 @patricoferris #553 #605 #608, reviewed by @avsm).
|
||||
Some potential users found object types confusing, so we now use an alternative scheme for OS resources.
|
||||
For users of the resources, the only thing that changes is the types:
|
||||
|
||||
- Instead of taking an argument of type `#foo`, you should now take `_ foo`.
|
||||
- Instead of returning a value of type `foo`, you should now return `foo_ty Eio.Resource.t`.
|
||||
|
||||
To provide your own implementation of an interface, you now provide a module rather than an object.
|
||||
For example, to provide your own source flow, use `Eio.Flow.Pi.source (module My_source)`.
|
||||
|
||||
If you want to define your own interfaces, see the `Eio.Resource` module documentation.
|
||||
|
||||
- Add `Eio.Pool` (@talex5 @darrenldl #602, reviewed by @patricoferris).
|
||||
A lock-free pool of resources. This is similar to `Lwt_pool`.
|
||||
|
||||
- Add `Eio.Lazy` (@talex5 #609, reviewed by @SGrondin).
|
||||
If one fiber tries to force a lazy value while another is already doing it,
|
||||
this will wait for the first one to finish rather than raising an exception (as `Stdlib.Lazy` does).
|
||||
|
||||
- Add `Eio.Path.native` (@talex5 #603, reviewed by @patricoferris).
|
||||
This is useful when interacting with non-Eio libraries, for spawning sub-processes, and for displaying paths to users.
|
||||
|
||||
- Add `Flow.single_write` (@talex5 #598).
|
||||
|
||||
- Add `Eio.Flow.Pi.simple_copy` (@talex5 #611).
|
||||
Provides an easy way to implement the `copy` operation when making your own sink.
|
||||
|
||||
- Eio_unix: add FD passing (@talex5 #522).
|
||||
Allows opening a file and passing the handle over a Unix-domain socket.
|
||||
|
||||
- Add `Process.run ?is_success` to control definition of success (@SGrondin #586, reviewed by @talex5).
|
||||
|
||||
- Add `Eio_mock.Domain_manager` (@talex5 #610).
|
||||
This mock domain manager runs everything in a single domain, allowing tests to remain deterministic.
|
||||
|
||||
- Add `Eio.Debug.with_trace_prefix` (@talex5 #610).
|
||||
Allows prefixing all `traceln` output. The mock domain manager uses this to indicate which fake domain is running.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fork actions must not allocate (@talex5 #593).
|
||||
When using multiple domains, child processes could get stuck if they forked while another domain held the malloc lock.
|
||||
|
||||
- eio_posix: ignore some errors writing to the wake-up pipe (@talex5 #600).
|
||||
If the pipe is full or closed, the wake-up should simply be ignored.
|
||||
|
||||
Build/test fixes:
|
||||
|
||||
- Fix some MDX problems on Windows (@polytypic #597).
|
||||
|
||||
- The README depends on kcas (@talex5 #606).
|
||||
|
||||
- Clarify configuration for lib_eio_linux and enable tests on other arches (@dra27 #592).
|
||||
|
||||
- eio_linux tests: skip fixed buffer test if not available (@talex5 #604).
|
||||
|
||||
- eio_windows: update available line to win32 (@talex5 #588 #591).
|
||||
|
||||
|
||||
## v0.11
|
||||
|
||||
New features / API changes:
|
||||
|
||||
- Extend `Eio.Condition` API (@talex5 #563).
|
||||
- `loop_no_mutex` is a simpler and more efficient way to way for a condition.
|
||||
- `register_immediate` allows integration with other IO libraries.
|
||||
|
||||
- Expose `Eio.Stdenv.backend_id` (@bord-o #560, reviewed by @talex5).
|
||||
Useful in tests to report which backend is being used.
|
||||
|
||||
- Remove deprecated features (@talex5 #552, reviewed by @avsm).
|
||||
These were all already marked as deprecated in v0.10 and are now gone completely:
|
||||
- `Fiber.fork_sub`
|
||||
- `Eio_unix.{FD,Ipaddr,socketpair,getnameinfo}`
|
||||
- `Eio_linux.{FD,get_fd,get_fd_opt}`
|
||||
- `Eio_posix.Low_level.Fd`
|
||||
|
||||
- Allow calling `close` more than once (@talex5 #547, requested by @anmonteiro, reviewed by @patricoferris, @avsm).
|
||||
|
||||
- Add `close` to socket type (@talex5 #549).
|
||||
Simplifies the type signatures a bit by avoiding having to mention this everywhere.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- Fix handling of empty path strings (@talex5 #569, reported by @SGrondin).
|
||||
Using "" instead of "." in some places resulted in an error.
|
||||
|
||||
- eio_posix: fix update to watched FDs on cancel (@talex5 #574, reported and reviewed by @quernd).
|
||||
Cancelling the last watcher of an FD didn't remove it from the set passed to `poll`,
|
||||
which could result in constant wake-ups.
|
||||
|
||||
- eio_posix: fix `pread` at end-of-file (@talex5 #581, reported by @SGrondin).
|
||||
It tried to return 0 instead of `End_of_file`, triggering an assertion.
|
||||
|
||||
- eio_posix: don't reap non-Eio child processes (@talex5 #562).
|
||||
This allows spawning processes with e.g. the stdlib or Lwt
|
||||
(but see https://github.com/ocaml-multicore/lwt_eio/pull/19 for Lwt support).
|
||||
|
||||
- Preserve backtraces across `Domain_manager.run` (@talex5 #571).
|
||||
See https://github.com/ocaml/ocaml/issues/12362.
|
||||
|
||||
- Correct the backend selection for Cygwin (@dra27 #557).
|
||||
Use `eio_posix`, not `eio_windows` in this case.
|
||||
|
||||
Other changes:
|
||||
|
||||
- Simplify dune files with dune 3.9's `build_if` (@talex5 #582).
|
||||
|
||||
- Remove `Waiters` from `Eio_core` (@talex5 #567).
|
||||
`Eio.Switch` no longer uses this so it can finally be removed.
|
||||
|
||||
- Use `Fmt.Dump.signal` to format signals (@talex5, @MisterDA #543).
|
||||
|
||||
Documentation:
|
||||
|
||||
- Add some notes about thread-safety in the documentation (@talex5 #568).
|
||||
|
||||
## v0.10
|
||||
|
||||
New features / API changes:
|
||||
|
||||
- Add `Eio.Process` for cross-platform subprocess support (@patricoferris @talex5 #499, reviewed by @anmonteiro @avsm @haesbaert).
|
||||
|
||||
- Add `Eio_unix.Net module` (@talex5 #516, reviewed by @avsm).
|
||||
The Unix network APIs have been cleaned up and moved here, and some missing datagram operations have been added.
|
||||
`send` now takes an iovec, not just a single buffer.
|
||||
|
||||
- Add support for domain local await (@polytypic @talex5 #494 #503).
|
||||
Allows sharing e.g. kcas data-structures across Eio and Domainslib domains.
|
||||
|
||||
- Add initial eio_windows backend (@patricoferris @talex5 #497 #530 #511 #523 #509, reviewed by @avsm @polytypic).
|
||||
|
||||
- Remove eio_luv backend (@talex5 #485).
|
||||
It was only used on Windows, and has been replaced by eio_windows.
|
||||
|
||||
- Unify `Eio_linux.FD` and `Eio_posix.Fd` as `Eio_unix.Fd` (@talex5 #491).
|
||||
Now that eio_luv is gone, there is no need for different backends to have different types for wrapped file descriptors.
|
||||
|
||||
- Move `Eio.Stdenv.t` to `Eio_unix.Stdenv.base` (@talex5 #498).
|
||||
Note that the rest of `Eio.Stdenv` is still there; only the definition of a full Unix-like environment has moved.
|
||||
|
||||
- Deprecation cleanups (@talex5 #508).
|
||||
Removed some APIs that were already marked as deprecated in Eio 0.8.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- eio_linux: fall back to `fork` if `clone3` is unavailable (@talex5 #524, reported by @smondet, reviewed by @avsm).
|
||||
Docker's default security policy blocks `clone3`.
|
||||
|
||||
- Don't call `accept_fork`'s error handler on cancellation (@talex5 #520).
|
||||
This isn't an error and should not be reported.
|
||||
|
||||
- Fix `eio_unix_is_blocking` C stub (@patricoferris #505, reviewed by @talex5).
|
||||
|
||||
- Fix `Condition.await bug` when cancelling (@polytypic @talex5 #487).
|
||||
|
||||
- Buf_write: fix flush returning too early (@talex5 #539, reported by @cometkim).
|
||||
|
||||
- Ignore `ENOTCONN` errors on socket shutdown (@avsm #533, reported by @patricoferris, reviewed by @talex5).
|
||||
|
||||
Documentation:
|
||||
|
||||
- Link to developer meetings information (@talex5 @Sudha247 #515).
|
||||
|
||||
- Adopt OCaml Code of Conduct (@Sudha247 #501).
|
||||
|
||||
- Add README links to Meio and Lambda Capabilities blog post (@talex5 #496).
|
||||
|
||||
- Document mirage `Ipaddr` conversion (@RyanGibb @patricoferris @talex5 #492).
|
||||
|
||||
- Document how to use Domainslib from Eio (@talex5 #489, reviewed by @polytypic @patricoferris).
|
||||
|
||||
Other changes:
|
||||
|
||||
- Run benchmarks with current-bench (@Sudha247 @talex5 #500).
|
||||
|
||||
- Fix MDX tests on OCaml 5.1 (@talex5 #526).
|
||||
|
||||
- Add stress test for spawning processes (@talex5 #519).
|
||||
This was an attempt to track down the https://github.com/ocaml/ocaml/issues/12253 signals bug.
|
||||
|
||||
- `Eio.Process.pp_status` should be polymorphic (@talex5 #518).
|
||||
|
||||
- eio_posix: probe for existence of some flags (@talex5 #507, reported by @hannesm).
|
||||
FreeBSD 12 didn't have `O_DSYNC`. Also, add `O_RESOLVE_BENEATH` and `O_PATH` if available.
|
||||
|
||||
- Fix race in ctf tests (@talex5 #493).
|
||||
|
||||
## v0.9
|
||||
|
||||
New features:
|
||||
|
||||
- Add eio_posix backend (@talex5 @haesbaert #448 #477, reviewed by @avsm @patricoferris @polytypic).
|
||||
This replaces eio_luv on all platforms except Windows (which will later switch to its own backend). It is a lot faster, provides access to more modern features (such as `openat`), and can safely share OS resources between domains.
|
||||
|
||||
- Add subprocess support (@patricoferris @talex5 #461 #464 #472, reviewed by @haesbaert @avsm).
|
||||
This is the low-level API support for eio_linux and eio_posix. A high-level cross-platform API will be added in the next release.
|
||||
|
||||
- Add `Fiber.fork_seq` (@talex5 #460, reviewed by @avsm).
|
||||
This is a light-weight alternative to using a single-producer, single-consumer, 0-capacity stream, similar to a Python generator function.
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- eio_linux: make it safe to share FDs across domains (@talex5 #440, reviewed by @haesbaert).
|
||||
It was previously not safe to share file descriptors between domains because if one domain used an FD just as another was closing it, and the FD got reused, then the original operation could act on the wrong file.
|
||||
|
||||
- eio_linux: release uring if Linux is too old (@talex5 #476).
|
||||
Avoids a small resource leak.
|
||||
|
||||
- eio_linux: improve error handling creating pipes and sockets (@talex5 #474, spotted by @avsm).
|
||||
If we get an error (e.g. too many FDs) then report it to the calling fiber, instead of exiting the event loop.
|
||||
|
||||
- eio_linux: wait for uring to finish before exiting (@talex5 #470, reviewed by @avsm).
|
||||
If the main fiber raised an exception then it was possible to exit while a cancellation operation was still in progress.
|
||||
|
||||
- eio_main: make `EIO_BACKEND` handling more uniform (@talex5 #447).
|
||||
Previously this environment variable was only used on Linux. Now all platforms check it.
|
||||
|
||||
- Tell dune about `EIO_BACKEND` (@talex5 #442).
|
||||
If this changes, dune needs to re-run the tests.
|
||||
|
||||
- eio_linux: add some missing close-on-execs (@talex5 #441).
|
||||
|
||||
- eio_linux: `read_exactly` fails to update file offset (@talex5 #438).
|
||||
|
||||
- Work around dune `enabled_if` bug on non-Linux systems (@polytypic #475, reviewed by @talex5).
|
||||
|
||||
- Use raw system call of `getrandom` for glibc versions before 2.25 (@zenfey #482).
|
||||
|
||||
Documentation:
|
||||
|
||||
- Add `HACKING.md` with hints for working on Eio (@talex5 #443, reviewed by @avsm @polytypic).
|
||||
|
||||
- Improve worker pool example (@talex5 #454).
|
||||
|
||||
- Add more Conditions documentation (@talex5 #436, reviewed by @haesbaert).
|
||||
This adds a discussion of conditions to the README and provides examples using them to handle signals.
|
||||
|
||||
- Condition: fix the example in the docstring (@avsm #468).
|
||||
|
||||
Performance:
|
||||
|
||||
- Add a network benchmark using an HTTP-like protocol (@talex5 #478, reviewed by @avsm @patricoferris).
|
||||
|
||||
- Add a benchmark for reading from `/dev/zero` (@talex5 #439).
|
||||
|
||||
Other changes:
|
||||
|
||||
- Add CI for macOS (@talex5 #452).
|
||||
|
||||
- Add tests for `pread`, `pwrite` and `readdir` (@talex5 #451).
|
||||
|
||||
- eio_linux: split into multiple files (@talex5 #465 #466, reviewed by @avsm).
|
||||
|
||||
- Update Dockerfile (@talex5 #471).
|
||||
|
||||
- Use dune.3.7.0 (@patricoferris #457).
|
||||
|
||||
- Mint exclusive IDs across domains (@TheLortex #480, reported by @haesbaert, reviewed by @talex5).
|
||||
The tracing currently only works with a single domain anyway, but this will change when OCaml 5.1 is released.
|
||||
|
||||
|
||||
## v0.8.1
|
||||
|
||||
Some build fixes:
|
||||
|
14
CODE_OF_CONDUCT.md
Normal file
14
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Code of Conduct
|
||||
|
||||
This project has adopted the [OCaml Code of Conduct](https://github.com/ocaml/code-of-conduct/blob/main/CODE_OF_CONDUCT.md).
|
||||
|
||||
# Enforcement
|
||||
|
||||
This project follows the OCaml Code of Conduct
|
||||
[enforcement policy](https://github.com/ocaml/code-of-conduct/blob/main/CODE_OF_CONDUCT.md#enforcement).
|
||||
|
||||
To report any violations, please contact:
|
||||
|
||||
* Patrick Ferris <patrick [at] sirref [dot] org>
|
||||
* Sudha Parimala <sudha [at] tarides [dot] com>
|
||||
* Thomas Leonard <thomasleonard [at] tarides [dot] com>
|
@ -1,15 +1,16 @@
|
||||
FROM ocaml/opam:debian-11-ocaml-5.0
|
||||
FROM ocaml/opam:debian-11-ocaml-5.2
|
||||
# Make sure we're using opam-2.1:
|
||||
RUN sudo ln -sf /usr/bin/opam-2.1 /usr/bin/opam
|
||||
# Ensure opam-repository is up-to-date:
|
||||
RUN cd opam-repository && git pull -q origin 08040ecbbbbb284606becd80c642a51ae1b6d7e1 && opam update
|
||||
RUN cd opam-repository && git pull -q origin 97de3378749cf8d2d70a5d710d310e5cc17c9dea && opam update
|
||||
# Install utop for interactive use:
|
||||
RUN opam install utop fmt
|
||||
# Install Eio's dependencies (adding just the opam files first to help with caching):
|
||||
RUN mkdir eio
|
||||
WORKDIR eio
|
||||
COPY *.opam ./
|
||||
RUN opam install --deps-only .
|
||||
RUN opam pin --with-version=dev . -yn
|
||||
RUN opam install --deps-only eio_main eio_linux eio
|
||||
# Build Eio:
|
||||
COPY . ./
|
||||
RUN opam install .
|
||||
RUN opam install eio_main
|
||||
|
149
HACKING.md
Normal file
149
HACKING.md
Normal file
@ -0,0 +1,149 @@
|
||||
## Installing Eio from Git
|
||||
|
||||
If you want to run the latest development version from Git, run these commands:
|
||||
|
||||
```
|
||||
git clone https://github.com/ocaml-multicore/eio.git
|
||||
cd eio
|
||||
opam pin -yn .
|
||||
opam install eio_main
|
||||
```
|
||||
|
||||
## Layout of the code
|
||||
|
||||
`lib_eio/core` contains the core logic about fibers, promises, switches, etc.
|
||||
`lib_eio` extends this with e.g. streams, buffered readers, buffered writers,
|
||||
and a load of types for OS resources (files, networks, etc).
|
||||
|
||||
There is one directory for each backend (e.g. `eio_linux`).
|
||||
Each backend provides a scheduler that integrates with a particular platform,
|
||||
and implements some or all of the cross-platform resource APIs.
|
||||
For example, `eio_linux` implements the network interface using `io_uring` to send data.
|
||||
|
||||
`lib_main` just selects an appropriate backend for the current system.
|
||||
|
||||
## Writing a backend
|
||||
|
||||
It's best to start by reading `lib_eio/mock/backend.ml`, which implements a mock backend with no actual IO.
|
||||
You can then read one of the real backends to see how to integrate this with the OS.
|
||||
|
||||
Most backends are built in two layers:
|
||||
|
||||
- A "low-level" module directly wraps the platform's own API, just adding support for suspending fibers for concurrency
|
||||
and basic safety features (such wrapping `Unix.file_descr` to prevent use-after-close races).
|
||||
|
||||
- An implementation of the cross-platform API (as defined in the `eio` package) that uses the low-level API internally.
|
||||
This should ensure that errors are reported using the `Eio.Io` exception.
|
||||
|
||||
`eio_posix` is the best one to look at first:
|
||||
|
||||
- `lib_eio_posix/sched.ml` is similar to the mock scheduler, but extended to interact with the OS kernel.
|
||||
- `lib_eio_posix/low_level.ml` provides fairly direct wrappers of the standard POSIX functions,
|
||||
but using `sched.ml` to suspend and resume instead of blocking the whole domain.
|
||||
- `lib_eio_posix/net.ml` implements the cross-platform API using the low-level API.
|
||||
For example, it converts Eio network addresses to Unix ones.
|
||||
Likewise, `fs.ml` implements the cross-platform file-system APIs, etc.
|
||||
- `lib_eio_posix/eio_posix.ml` provides the main `run` function.
|
||||
It runs the scheduler, passing to the user's `main` function an `env` object for the cross-platform API functions.
|
||||
|
||||
When writing a backend, it's best to write the main loop in OCaml rather than delegate that to a C function.
|
||||
Some particular things to watch out for:
|
||||
|
||||
- If a system call returns `EINTR`, you must switch back to OCaml
|
||||
(`caml_leave_blocking_section`) so that the signal can be handled. Some C
|
||||
libraries just restart the function immediately and this will break signal
|
||||
handling (on systems that have signals).
|
||||
|
||||
- If C code installs a signal handler, it *must* use the alt stack (`SA_ONSTACK`).
|
||||
Otherwise, signals handlers will run on the fiber stack, which is too small and will result in memory corruption.
|
||||
|
||||
- Effects cannot be performed over a C function.
|
||||
So, if the user installs an effect handler and then calls a C mainloop, and the C code invokes a callback,
|
||||
the callback cannot use the effect handler.
|
||||
This isn't a problem for Eio itself (Eio's effect handler is installed inside the mainloop),
|
||||
but it can break programs using effects in other ways.
|
||||
|
||||
## Tests
|
||||
|
||||
Eio has tests in many places...
|
||||
|
||||
### Cross-platform unit tests
|
||||
|
||||
These are in the top-level `tests` directory.
|
||||
They are run against whichever backend `Eio_main.run` selects, and therefore must get the same result for all backends.
|
||||
|
||||
### Concurrency primitives
|
||||
|
||||
`lib_eio/tests` tests some internal data structures, such as the lock-free cells abstraction.
|
||||
The `.md` files in that directory provide a simple walk-through to demonstrate the basic operation,
|
||||
while `lib_eio/tests/dscheck` uses [dscheck][] to perform exhaustive testing of all atomic interleavings.
|
||||
|
||||
At the time of writing, dscheck has some performance problems that make it unusable by default, so
|
||||
you must use the version in https://github.com/ocaml-multicore/dscheck/pull/22 instead.
|
||||
|
||||
### Benchmarks
|
||||
|
||||
The `bench` directory contains various speed tests.
|
||||
`make bench` is a convenient way to run all of them.
|
||||
This is useful to check for regressions.
|
||||
|
||||
If you want to contibute an optimisation, please add a benchmark so that we can measure the improvement.
|
||||
If you are changing something, make sure the benchmark doesn't get significantly worse.
|
||||
|
||||
### Stress and fuzz testing
|
||||
|
||||
The `fuzz` directory uses afl-fuzz to search for bugs.
|
||||
|
||||
Using it properly requires an instrumented version of the OCaml compiler
|
||||
(see https://v2.ocaml.org/manual/afl-fuzz.html for instructions).
|
||||
The `dune` build rules don't use afl-fuzz; they just do a few random tests and then stop.
|
||||
|
||||
To run e.g. the `fuzz_buf_read` tests with afl-fuzz:
|
||||
|
||||
```
|
||||
mkdir input
|
||||
date > input/seed
|
||||
afl-fuzz -m 1000 -i input -o output ./_build/default/fuzz/fuzz_buf_read.exe @@
|
||||
```
|
||||
|
||||
- `Fork server handshake failed` indicates that you are not using an AFL-enabled version of OCaml.
|
||||
- `The current memory limit (75.0 MB) is too restrictive` means you forgot to use `-m`.
|
||||
|
||||
The `stress` directory contains stress tests (that try to trigger races by brute force).
|
||||
|
||||
### Backend-specific tests
|
||||
|
||||
There are also backend-specific tests, e.g.
|
||||
|
||||
- `lib_eio_linux/tests`
|
||||
- `lib_eio_luv/tests`
|
||||
|
||||
Use these for tests that only make sense for one platform.
|
||||
|
||||
### Formal verification
|
||||
|
||||
Some parts of Eio have been formally verified:
|
||||
|
||||
- https://github.com/addap/master-thesis/tree/main/documents [[video](https://discuss.ocaml.org/t/video-verifying-an-effect-based-cooperative-concurrency-scheduler-in-iris-by-adrian-dapprich/13825)]
|
||||
- https://github.com/clef-men/zebre/tree/main/theories/eio
|
||||
|
||||
## Code formatting
|
||||
|
||||
Eio's code is indented using ocp-indent.
|
||||
When making PRs, please do not apply other formatting tools to existing code unrelated to your PR.
|
||||
Try to avoid making unnecessary changes; this makes review harder and clutters up the Git history.
|
||||
`ocamlformat` may be useful to get badly messed up code to a baseline unformatted state,
|
||||
from which human formatting can be added where needed.
|
||||
|
||||
## AI-generated Code
|
||||
|
||||
Contributing to Eio should not be done _solely_ using "AI tools" such as ChatGPT. This is for a few reasons:
|
||||
|
||||
1. **It obfuscates how you think**. Purely AI-generated code tells us little about how you think and the problems you might be having. This makes it harder to provide good feedback on PRs and issues.
|
||||
2. **It is often more work to review**. Particularly for the OCaml ecosystem and libraries like Eio, it seems that these tools are not very good and generate a lot of believable code that is in actual fact completely wrong. PR comments and the code submitted with them can say completely different things.
|
||||
3. **It is a grey area for licensing**. Models like ChatGPT have been trained on lots of code with different licenses and has been known to simply copy code as an answer to a prompt. We would like to avoid this headache as best we can.
|
||||
|
||||
Use AI tools, if you wish, to help you understand OCaml and Eio. Do not offload all of the work of a PR or a comment to these tools.
|
||||
|
||||
[dscheck]: https://github.com/ocaml-multicore/dscheck
|
||||
|
24
Makefile
24
Makefile
@ -1,27 +1,25 @@
|
||||
.PHONY: all bench
|
||||
.PHONY: all bench stress
|
||||
|
||||
all:
|
||||
dune build @runtest @all
|
||||
|
||||
bench:
|
||||
dune exec -- ./bench/bench_condition.exe
|
||||
dune exec -- ./bench/bench_buf_read.exe
|
||||
dune exec -- ./bench/bench_mutex.exe
|
||||
dune exec -- ./bench/bench_yield.exe
|
||||
dune exec -- ./bench/bench_promise.exe
|
||||
dune exec -- ./bench/bench_stream.exe
|
||||
dune exec -- ./bench/bench_semaphore.exe
|
||||
dune exec -- ./bench/bench_cancel.exe
|
||||
dune exec -- ./lib_eio_linux/tests/bench_noop.exe
|
||||
dune exec -- ./bench/main.exe
|
||||
|
||||
test_luv:
|
||||
rm -rf _build
|
||||
EIO_BACKEND=luv dune runtest
|
||||
test_posix:
|
||||
EIO_BACKEND=posix dune runtest
|
||||
|
||||
dscheck:
|
||||
dune exec -- ./lib_eio/tests/dscheck/test_condition.exe
|
||||
dune exec -- ./lib_eio/tests/dscheck/test_rcfd.exe
|
||||
dune exec -- ./lib_eio/tests/dscheck/test_sync.exe
|
||||
dune exec -- ./lib_eio/tests/dscheck/test_semaphore.exe
|
||||
dune exec -- ./lib_eio/tests/dscheck/test_cells.exe
|
||||
|
||||
stress:
|
||||
dune exec -- ./stress/stress_proc.exe
|
||||
dune exec -- ./stress/stress_semaphore.exe
|
||||
dune exec -- ./stress/stress_release.exe
|
||||
|
||||
docker:
|
||||
docker build -t eio .
|
||||
|
14
bench.Dockerfile
Normal file
14
bench.Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
FROM ocaml/opam:debian-11-ocaml-5.2
|
||||
# Make sure we're using opam-2.1:
|
||||
RUN sudo ln -sf /usr/bin/opam-2.1 /usr/bin/opam
|
||||
# Ensure opam-repository is up-to-date:
|
||||
RUN cd opam-repository && git pull -q origin 97de3378749cf8d2d70a5d710d310e5cc17c9dea && opam update
|
||||
# Install Eio's dependencies (adding just the opam files first to help with caching):
|
||||
RUN mkdir eio
|
||||
WORKDIR eio
|
||||
COPY *.opam ./
|
||||
RUN opam pin --with-version=dev . -yn
|
||||
RUN opam install eio_main yojson
|
||||
# Build the benchmarks:
|
||||
COPY . ./
|
||||
RUN opam exec -- dune build ./bench
|
@ -1,8 +1,7 @@
|
||||
module R = Eio.Buf_read
|
||||
|
||||
let test_data = String.init 100_000_000 (fun _ -> 'x')
|
||||
|
||||
let () =
|
||||
let run _env =
|
||||
let test_data = String.make 100_000_000 'x' in
|
||||
let r = R.of_string test_data in
|
||||
let t0 = Unix.gettimeofday () in
|
||||
let i = ref 0 in
|
||||
@ -10,7 +9,10 @@ let () =
|
||||
while true do
|
||||
assert (R.any_char r = 'x');
|
||||
incr i
|
||||
done
|
||||
done;
|
||||
assert false
|
||||
with End_of_file ->
|
||||
let t1 = Unix.gettimeofday () in
|
||||
Eio.traceln "Read %d bytes in %.3fs" !i (t1 -. t0)
|
||||
let time = t1 -. t0 in
|
||||
let bytes_per_second = float (String.length test_data) /. time in
|
||||
[Metric.create "any_char" (`Float bytes_per_second) "bytes/s" "Parsing a long string one character at a time"]
|
||||
|
@ -20,8 +20,12 @@ let run_bench ?domain_mgr ~clock () =
|
||||
| Some dm -> Eio.Domain_manager.run dm (fun () -> run_sender stream)
|
||||
| None -> run_sender stream
|
||||
in
|
||||
let name str =
|
||||
match domain_mgr with
|
||||
| Some _ -> str ^ "/separate domains"
|
||||
| None -> str ^ "/single domain"
|
||||
in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
try
|
||||
Switch.run (fun sw ->
|
||||
@ -39,17 +43,17 @@ let run_bench ?domain_mgr ~clock () =
|
||||
let t1 = Eio.Time.now clock in
|
||||
let time_total = t1 -. t0 in
|
||||
let time_per_iter = time_total /. float n_iters in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
Printf.printf "%11b, %7.2f, %13.4f\n%!" (domain_mgr <> None) (1e9 *. time_per_iter) (prom /. float n_iters)
|
||||
Metric.create
|
||||
(name "take-first")
|
||||
(`Float (1e9 *. time_per_iter)) "ns"
|
||||
"Time to take from one of two streams"
|
||||
|
||||
let main ~domain_mgr ~clock =
|
||||
Printf.printf "use_domains, ns/iter, promoted/iter\n%!";
|
||||
run_bench ~clock ();
|
||||
run_bench ~domain_mgr ~clock ()
|
||||
let m1 = run_bench ~clock () in
|
||||
let m2 = run_bench ~domain_mgr ~clock () in
|
||||
[m1; m2]
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main
|
||||
~domain_mgr:(Eio.Stdenv.domain_mgr env)
|
||||
~clock:(Eio.Stdenv.clock env)
|
||||
|
@ -14,7 +14,6 @@ let run_publisher cond v =
|
||||
Eio.Condition.broadcast cond
|
||||
done
|
||||
|
||||
|
||||
let run_consumer cond v =
|
||||
try
|
||||
while true do
|
||||
@ -36,8 +35,12 @@ let run_bench ?domain_mgr ~clock () =
|
||||
| Some dm -> Eio.Domain_manager.run dm (fun () -> run_consumer cond v)
|
||||
| None -> run_consumer cond v
|
||||
in
|
||||
let name str =
|
||||
match domain_mgr with
|
||||
| Some _ -> str ^ "_domain"
|
||||
| None -> str
|
||||
in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
for _ = 1 to n_iters do
|
||||
Fiber.all [
|
||||
@ -49,17 +52,14 @@ let run_bench ?domain_mgr ~clock () =
|
||||
let t1 = Eio.Time.now clock in
|
||||
let time_total = t1 -. t0 in
|
||||
let time_per_iter = time_total /. float n_iters in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
Printf.printf "%11b, %7.2f, %13.4f\n%!" (domain_mgr <> None) (1e3 *. time_per_iter) (prom /. float n_iters)
|
||||
Metric.create (name "broadcast") (`Float (1e3 *. time_per_iter)) "ms" "Time to signal a new value"
|
||||
|
||||
let main ~domain_mgr ~clock =
|
||||
Printf.printf "use_domains, ms/iter, promoted/iter\n%!";
|
||||
let main ~domain_mgr ~clock = [
|
||||
run_bench ~clock ();
|
||||
run_bench ~domain_mgr ~clock ()
|
||||
run_bench ~domain_mgr ~clock ();
|
||||
]
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main
|
||||
~domain_mgr:(Eio.Stdenv.domain_mgr env)
|
||||
~clock:(Eio.Stdenv.clock env)
|
||||
|
44
bench/bench_copy.ml
Normal file
44
bench/bench_copy.ml
Normal file
@ -0,0 +1,44 @@
|
||||
(* A client opens a connection to an echo service and sends a load of data via it. *)
|
||||
|
||||
open Eio.Std
|
||||
|
||||
let chunk_size = 1 lsl 16
|
||||
let n_chunks = 10000
|
||||
let n_bytes = n_chunks * chunk_size
|
||||
|
||||
let run_client sock =
|
||||
Fiber.both
|
||||
(fun () ->
|
||||
let chunk = Cstruct.create chunk_size in
|
||||
for _ = 1 to n_chunks do
|
||||
Eio.Flow.write sock [chunk]
|
||||
done;
|
||||
Eio.Flow.shutdown sock `Send
|
||||
)
|
||||
(fun () ->
|
||||
let chunk = Cstruct.create chunk_size in
|
||||
for _ = 1 to n_chunks do
|
||||
Eio.Flow.read_exact sock chunk
|
||||
done
|
||||
)
|
||||
|
||||
let time name service =
|
||||
Switch.run ~name @@ fun sw ->
|
||||
let client_sock, server_sock = Eio_unix.Net.socketpair_stream ~sw () in
|
||||
let t0 = Unix.gettimeofday () in
|
||||
Fiber.both
|
||||
(fun () -> service server_sock)
|
||||
(fun () -> run_client client_sock);
|
||||
let t1 = Unix.gettimeofday () in
|
||||
let time = t1 -. t0 in
|
||||
let bytes_per_second = float n_bytes /. time in
|
||||
traceln "%s: %.2f MB/s" name (bytes_per_second /. 1024. /. 1024.);
|
||||
Metric.create name (`Float bytes_per_second) "bytes/s" (name ^ " Flow.copy")
|
||||
|
||||
let run _env =
|
||||
[
|
||||
time "default" (fun sock -> Eio.Flow.copy sock sock);
|
||||
time "buf_read" (fun sock ->
|
||||
let r = Eio.Buf_read.of_flow sock ~initial_size:(64 * 1024) ~max_size:(64 * 1024) |> Eio.Buf_read.as_flow in
|
||||
Eio.Flow.copy r sock);
|
||||
]
|
38
bench/bench_fd.ml
Normal file
38
bench/bench_fd.ml
Normal file
@ -0,0 +1,38 @@
|
||||
open Eio.Std
|
||||
|
||||
let time label len fn =
|
||||
let t0 = Unix.gettimeofday () in
|
||||
fn ();
|
||||
let t1 = Unix.gettimeofday () in
|
||||
Metric.create
|
||||
label
|
||||
(`Float (float len /. (t1 -. t0) /. (2. ** 30.))) "GB/s"
|
||||
"Reading from /dev/zero using a single FD"
|
||||
|
||||
let main ~domain_mgr zero =
|
||||
let iters = 100_000 in
|
||||
let len = 64 * 1024 in
|
||||
let n_fibers = 4 in
|
||||
let n_domains = 4 in
|
||||
let buf = Cstruct.create len in
|
||||
let run1 () =
|
||||
for _ = 1 to iters do Eio.Flow.read_exact zero buf done
|
||||
in
|
||||
[time "fibers:1" (iters * len) run1;
|
||||
time (Fmt.str "fibers:%d" n_fibers) (iters * n_fibers * len) (fun () ->
|
||||
Switch.run @@ fun sw ->
|
||||
for _ = 1 to n_fibers do
|
||||
Fiber.fork ~sw run1
|
||||
done
|
||||
);
|
||||
time (Fmt.str "domains:%d" n_domains) (iters * n_domains * len) (fun () ->
|
||||
Switch.run @@ fun sw ->
|
||||
for _ = 1 to n_domains do
|
||||
Fiber.fork ~sw (fun () -> Eio.Domain_manager.run domain_mgr run1)
|
||||
done
|
||||
)]
|
||||
|
||||
let ( / ) = Eio.Path.( / )
|
||||
|
||||
let run env =
|
||||
Eio.Path.with_open_in (env#fs / "/dev/zero") (main ~domain_mgr:env#domain_mgr)
|
26
bench/bench_fstat.ml
Normal file
26
bench/bench_fstat.ml
Normal file
@ -0,0 +1,26 @@
|
||||
open Eio.Std
|
||||
|
||||
let ( / ) = Eio.Path.( / )
|
||||
|
||||
let n_stat = 100000
|
||||
|
||||
let run_fiber file =
|
||||
for _ = 1 to n_stat do
|
||||
let info = (Eio.File.stat file).kind in
|
||||
assert (info = `Regular_file)
|
||||
done
|
||||
|
||||
let run env =
|
||||
Eio.Path.with_open_out ~create:(`If_missing 0o600) (env#cwd / "test-stat") @@ fun file ->
|
||||
[1; 10] |> List.map (fun par ->
|
||||
let t0 = Unix.gettimeofday () in
|
||||
Switch.run (fun sw ->
|
||||
for _ = 1 to par do
|
||||
Fiber.fork ~sw (fun () -> run_fiber file)
|
||||
done
|
||||
);
|
||||
let t1 = Unix.gettimeofday () in
|
||||
let stat_per_s = float (n_stat * par) /. (t1 -. t0) in
|
||||
let label = Printf.sprintf "n=%d fibers=%d" n_stat par in
|
||||
Metric.create label (`Float stat_per_s) "stat/s" "Call fstat on an open file"
|
||||
)
|
107
bench/bench_http.ml
Normal file
107
bench/bench_http.ml
Normal file
@ -0,0 +1,107 @@
|
||||
(* A multi-domain server handles HTTP-like requests from many clients running across multiple domains. *)
|
||||
|
||||
open Eio.Std
|
||||
|
||||
(* Note: this is not a real HTTP parser! *)
|
||||
let key_char = function
|
||||
| 'A'..'Z' | 'a'..'z' | '-' -> true
|
||||
| _ -> false
|
||||
|
||||
let parse_headers r =
|
||||
let len = ref (-1) in
|
||||
let rec aux () =
|
||||
let key = Eio.Buf_read.take_while key_char r in
|
||||
if key = "" then Eio.Buf_read.string "\r\n" r
|
||||
else (
|
||||
Eio.Buf_read.char ':' r;
|
||||
let value = Eio.Buf_read.line r in
|
||||
if key = "Content-Length" then len := int_of_string (String.trim value);
|
||||
aux ()
|
||||
)
|
||||
in
|
||||
aux ();
|
||||
!len
|
||||
|
||||
let handle_connection conn _addr =
|
||||
Eio.Buf_write.with_flow conn @@ fun w ->
|
||||
let rec requests r =
|
||||
let _req = Eio.Buf_read.line r in
|
||||
let len = parse_headers r in
|
||||
let body = Eio.Buf_read.take len r in
|
||||
let response = body ^ " / received" in
|
||||
Eio.Buf_write.string w "HTTP/1.1 200 OK\r\n";
|
||||
Eio.Buf_write.string w (Printf.sprintf "Content-Length: %d\r\n" (String.length response));
|
||||
Eio.Buf_write.string w "\r\n";
|
||||
Eio.Buf_write.string w response;
|
||||
if not (Eio.Buf_read.at_end_of_input r) then requests r
|
||||
in
|
||||
Eio.Buf_read.parse_exn requests conn ~max_size:max_int
|
||||
|
||||
let run_client ~n_requests id conn =
|
||||
let total = ref 0 in
|
||||
let r = Eio.Buf_read.of_flow conn ~max_size:max_int in
|
||||
Eio.Buf_write.with_flow conn @@ fun w ->
|
||||
for i = 1 to n_requests do
|
||||
let msg = Printf.sprintf "%s / request %d" id i in
|
||||
Eio.Buf_write.string w "POST / HTTP/1.1\r\n";
|
||||
Eio.Buf_write.string w "Host: localhost:8085\r\n";
|
||||
Eio.Buf_write.string w "User-Agent: bench_server\r\n";
|
||||
Eio.Buf_write.string w "Connection: keep-alive\r\n";
|
||||
Eio.Buf_write.string w (Printf.sprintf "Content-Length: %d\r\n" (String.length msg));
|
||||
Eio.Buf_write.string w "\r\n";
|
||||
Eio.Buf_write.string w msg;
|
||||
let status = Eio.Buf_read.line r in
|
||||
assert (status = "HTTP/1.1 200 OK");
|
||||
let len = parse_headers r in
|
||||
let body = Eio.Buf_read.take len r in
|
||||
assert (body = msg ^ " / received");
|
||||
incr total
|
||||
done;
|
||||
!total
|
||||
|
||||
let main net domain_mgr ~n_client_domains ~n_server_domains ~n_connections_per_domain ~n_requests_per_connection =
|
||||
let total = Atomic.make 0 in
|
||||
let t0 = Unix.gettimeofday () in
|
||||
Switch.run ~name:"main" (fun sw ->
|
||||
let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, 8085) in
|
||||
let backlog = n_connections_per_domain * n_client_domains in
|
||||
let server_socket = Eio.Net.listen ~reuse_addr:true ~backlog ~sw net addr in
|
||||
Fiber.fork_daemon ~sw (fun () ->
|
||||
Eio.Net.run_server server_socket handle_connection
|
||||
~additional_domains:(domain_mgr, n_server_domains - 1)
|
||||
~on_error:raise
|
||||
);
|
||||
for domain = 1 to n_client_domains do
|
||||
Fiber.fork ~sw (fun () ->
|
||||
Eio.Domain_manager.run domain_mgr (fun () ->
|
||||
Switch.run ~name:"client-domain" @@ fun sw ->
|
||||
for i = 1 to n_connections_per_domain do
|
||||
Fiber.fork ~sw (fun () ->
|
||||
let id = Printf.sprintf "domain %d / conn %d" domain i in
|
||||
let conn = Eio.Net.connect ~sw net addr in
|
||||
let requests = run_client ~n_requests:n_requests_per_connection id conn in
|
||||
ignore (Atomic.fetch_and_add total requests : int)
|
||||
)
|
||||
done
|
||||
)
|
||||
)
|
||||
done
|
||||
);
|
||||
let t1 = Unix.gettimeofday () in
|
||||
(* Fmt.pr "clients, servers, requests, requests/s@."; *)
|
||||
let requests = n_connections_per_domain * n_client_domains * n_requests_per_connection in
|
||||
assert (requests = Atomic.get total);
|
||||
let req_per_s = float requests /. (t1 -. t0) in
|
||||
Metric.create
|
||||
(Printf.sprintf "requests:%d client-domains:%d server-domains:%d" requests n_client_domains n_server_domains)
|
||||
(`Float req_per_s) "requests/s" "Request rate of a HTTP client/server system"
|
||||
|
||||
let run env =
|
||||
let metrics =
|
||||
main env#net env#domain_mgr
|
||||
~n_client_domains:4
|
||||
~n_server_domains:4
|
||||
~n_connections_per_domain:25
|
||||
~n_requests_per_connection:1000
|
||||
in
|
||||
[metrics]
|
@ -2,7 +2,7 @@ open Eio.Std
|
||||
|
||||
let v = ref 0
|
||||
|
||||
let run_sender ~iters_per_thread mutex =
|
||||
let run_worker ~iters_per_thread mutex =
|
||||
for _ = 1 to iters_per_thread do
|
||||
Eio.Mutex.lock mutex;
|
||||
let x = !v in
|
||||
@ -16,16 +16,15 @@ let run_sender ~iters_per_thread mutex =
|
||||
let run_bench ~domain_mgr ~clock ~use_domains ~iters_per_thread ~threads =
|
||||
let mutex = Eio.Mutex.create () in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
Switch.run (fun sw ->
|
||||
for _ = 1 to threads do
|
||||
Fiber.fork ~sw (fun () ->
|
||||
if use_domains then (
|
||||
Eio.Domain_manager.run domain_mgr @@ fun () ->
|
||||
run_sender ~iters_per_thread mutex
|
||||
run_worker ~iters_per_thread mutex
|
||||
) else (
|
||||
run_sender ~iters_per_thread mutex
|
||||
run_worker ~iters_per_thread mutex
|
||||
)
|
||||
)
|
||||
done
|
||||
@ -35,24 +34,21 @@ let run_bench ~domain_mgr ~clock ~use_domains ~iters_per_thread ~threads =
|
||||
let time_total = t1 -. t0 in
|
||||
let n_iters = iters_per_thread * threads in
|
||||
let time_per_iter = time_total /. float n_iters in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
Printf.printf "%11b, %12d, %8d, %8.2f, %13.4f\n%!" use_domains n_iters threads (1e9 *. time_per_iter) (prom /. float n_iters)
|
||||
Metric.create
|
||||
(Printf.sprintf "iterations=%d threads=%d" n_iters threads)
|
||||
(`Float (1e9 *. time_per_iter)) "ns" "Time to update a shared counter"
|
||||
|
||||
let main ~domain_mgr ~clock =
|
||||
Printf.printf "use_domains, iters/thread, threads, ns/iter, promoted/iter\n%!";
|
||||
[false, 1_000_000, 1;
|
||||
false, 1_000_000, 2;
|
||||
false, 100_000, 8;
|
||||
true, 100_000, 1;
|
||||
true, 10_000, 2;
|
||||
true, 10_000, 8]
|
||||
|> List.iter (fun (use_domains, iters_per_thread, threads) ->
|
||||
run_bench ~domain_mgr ~clock ~use_domains ~iters_per_thread ~threads
|
||||
)
|
||||
|> List.map (fun (use_domains, iters_per_thread, threads) ->
|
||||
run_bench ~domain_mgr ~clock ~use_domains ~iters_per_thread ~threads)
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main
|
||||
~domain_mgr:(Eio.Stdenv.domain_mgr env)
|
||||
~clock:(Eio.Stdenv.clock env)
|
||||
|
@ -52,8 +52,11 @@ let bench_resolved ~clock ~n_iters =
|
||||
t := !t + Promise.await p;
|
||||
done;
|
||||
let t1 = Eio.Time.now clock in
|
||||
Printf.printf "Reading a resolved promise: %.3f ns\n%!" (1e9 *. (t1 -. t0) /. float n_iters);
|
||||
assert (!t = n_iters)
|
||||
assert (!t = n_iters);
|
||||
Metric.create
|
||||
"read-resolved"
|
||||
(`Float (1e9 *. (t1 -. t0) /. float n_iters)) "ns"
|
||||
"Time to read a resolved promise"
|
||||
|
||||
let maybe_spin v fn =
|
||||
if v then Fiber.first spin fn
|
||||
@ -62,7 +65,6 @@ let maybe_spin v fn =
|
||||
let run_bench ~domain_mgr ~spin ~clock ~use_domains ~n_iters =
|
||||
let init_p, init_r = Promise.create () in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
Fiber.both
|
||||
(fun () ->
|
||||
@ -79,23 +81,28 @@ let run_bench ~domain_mgr ~spin ~clock ~use_domains ~n_iters =
|
||||
let t1 = Eio.Time.now clock in
|
||||
let time_total = t1 -. t0 in
|
||||
let time_per_iter = time_total /. float n_iters in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
let domains = Printf.sprintf "%b/%b" use_domains spin in
|
||||
Printf.printf "%11s, %8d, %8.2f, %13.4f\n%!" domains n_iters (1e9 *. time_per_iter) (prom /. float n_iters)
|
||||
let domains_label =
|
||||
if use_domains then
|
||||
if spin then "with-spin"
|
||||
else "without-spin"
|
||||
else "no"
|
||||
in
|
||||
Metric.create
|
||||
(Printf.sprintf "iterations:%d domains:%s" n_iters domains_label)
|
||||
(`Float (1e9 *. time_per_iter)) "ns"
|
||||
"Time to round-trip a request/reply"
|
||||
|
||||
let main ~domain_mgr ~clock =
|
||||
bench_resolved ~clock ~n_iters:(10_000_000);
|
||||
Printf.printf "domains/spin, n_iters, ns/iter, promoted/iter\n%!";
|
||||
[false, false, 1_000_000;
|
||||
let resolved = bench_resolved ~clock ~n_iters:(10_000_000) in
|
||||
let metrics = [false, false, 1_000_000;
|
||||
true, true, 100_000;
|
||||
true, false, 100_000]
|
||||
|> List.iter (fun (use_domains, spin, n_iters) ->
|
||||
|> List.map (fun (use_domains, spin, n_iters) ->
|
||||
run_bench ~domain_mgr ~spin ~clock ~use_domains ~n_iters
|
||||
)
|
||||
) in
|
||||
resolved :: metrics
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main
|
||||
~domain_mgr:(Eio.Stdenv.domain_mgr env)
|
||||
~clock:(Eio.Stdenv.clock env)
|
||||
|
@ -36,29 +36,27 @@ let run_bench ~domain_mgr ~clock ~use_domains ~n_iters ~n_resources =
|
||||
)
|
||||
in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
Fiber.all (List.init n_workers (Fun.const run));
|
||||
let t1 = Eio.Time.now clock in
|
||||
let time_total = t1 -. !t0 in
|
||||
let time_per_iter = time_total /. float n_iters in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
Printf.printf "%11b, %8d, %11d, %8.2f, %13.4f\n%!" use_domains n_iters n_resources (1e9 *. time_per_iter) (prom /. float n_iters)
|
||||
Metric.create
|
||||
(Printf.sprintf "iterations:%d resources:%d" n_iters n_resources)
|
||||
(`Float (1e9 *. time_per_iter)) "ns"
|
||||
"Time to acquire a semaphore, yeild, and release it"
|
||||
|
||||
let main ~domain_mgr ~clock =
|
||||
Printf.printf "use_domains, n_iters, resources, ns/iter, promoted/iter\n%!";
|
||||
[false, 100_000, 2;
|
||||
false, 100_000, 3;
|
||||
false, 100_000, 4;
|
||||
true, 10_000, 2;
|
||||
true, 10_000, 3;
|
||||
true, 10_000, 4]
|
||||
|> List.iter (fun (use_domains, n_iters, n_resources) ->
|
||||
|> List.map (fun (use_domains, n_iters, n_resources) ->
|
||||
run_bench ~domain_mgr ~clock ~use_domains ~n_iters ~n_resources
|
||||
)
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main
|
||||
~domain_mgr:(Eio.Stdenv.domain_mgr env)
|
||||
~clock:(Eio.Stdenv.clock env)
|
||||
|
152
bench/bench_stat.ml
Normal file
152
bench/bench_stat.ml
Normal file
@ -0,0 +1,152 @@
|
||||
open Eio.Std
|
||||
|
||||
module Path = Eio.Path
|
||||
|
||||
let () = Random.init 3
|
||||
|
||||
let ( / ) = Eio.Path.( / )
|
||||
|
||||
module Bench_dir = struct
|
||||
type t =
|
||||
| Dir of { name : string; perm : int; children : t list }
|
||||
| File of { name : string; size : int64; perm : int; }
|
||||
|
||||
let get_name = function Dir { name; _ } | File { name; _ } -> name
|
||||
|
||||
let get_children = function
|
||||
| Dir { children; _ } -> children
|
||||
| File _ -> invalid_arg "Files don't have children"
|
||||
|
||||
let compare a b = String.compare (get_name a) (get_name b)
|
||||
|
||||
let rec sort = function
|
||||
| Dir ({ children; _ } as v) ->
|
||||
let c = List.map sort children in
|
||||
let c = List.stable_sort compare c in
|
||||
Dir { v with children = c }
|
||||
| File _ as f -> f
|
||||
|
||||
let rec size = function
|
||||
| Dir { children; _ } ->
|
||||
List.fold_left (fun acc v -> acc + size v) 0 children
|
||||
| File _ -> 1
|
||||
|
||||
let rec pp ppf = function
|
||||
| Dir { name; perm; children } ->
|
||||
if children = [] then Fmt.pf ppf "dir %s (0o%o)" name perm else
|
||||
Fmt.pf ppf "@[<v2>dir %s (0o%o)@ %a@]" name perm Fmt.(list ~sep:Fmt.cut pp) children
|
||||
| File { name; size; perm } ->
|
||||
Fmt.pf ppf "file %s (0o%o) %Lu" name perm size
|
||||
|
||||
let make fs t =
|
||||
let rec aux iter fs = function
|
||||
| Dir { name; perm; children } ->
|
||||
let dir = fs / name in
|
||||
Path.mkdir ~perm dir;
|
||||
iter (aux List.iter dir) children
|
||||
| File { name; size; perm } ->
|
||||
let buf = Cstruct.create (Int64.to_int size) in
|
||||
Path.with_open_out ~create:(`If_missing perm) (fs / name) (fun oc ->
|
||||
Eio.Flow.write oc [ buf ]
|
||||
)
|
||||
in
|
||||
aux Fiber.List.iter fs t
|
||||
end
|
||||
|
||||
let with_tmp_dir ~fs prefix suffix fn =
|
||||
Switch.run @@ fun sw ->
|
||||
let dir = fs / Filename.temp_dir prefix suffix in
|
||||
Switch.on_release sw (fun () -> Path.rmtree dir);
|
||||
fn dir
|
||||
|
||||
let bench_stat root =
|
||||
let rec aux level dir =
|
||||
let { Eio.File.Stat.kind; perm; size; _ } = Path.stat ~follow:false dir in
|
||||
match kind with
|
||||
| `Directory ->
|
||||
let items = Path.read_dir dir in
|
||||
let map = if level > 3 then List.map else Fiber.List.map ?max_fibers:None in
|
||||
let children = items |> map (fun f -> aux (level + 1) (dir / f)) in
|
||||
let name = Path.native_exn dir |> Filename.basename in
|
||||
Bench_dir.Dir { name; perm; children }
|
||||
| `Regular_file ->
|
||||
let name = Path.native_exn dir |> Filename.basename in
|
||||
File { name; perm; size = Optint.Int63.to_int64 size }
|
||||
| _ -> assert false
|
||||
in
|
||||
aux 1 root
|
||||
|
||||
let file name = Bench_dir.File { name; perm = 0o644; size = 128L }
|
||||
let dir name children = Bench_dir.Dir { name; perm = 0o700; children }
|
||||
|
||||
let random_bench_dir ~n ~levels =
|
||||
if levels < 1 then invalid_arg "Levels should be >= 1";
|
||||
let rec loop root = function
|
||||
| 1 -> (
|
||||
match root with
|
||||
| Bench_dir.Dir d ->
|
||||
let leaf_files = List.init n (fun i -> file (Fmt.str "test-file-%i-%i" 1 i)) in
|
||||
Bench_dir.Dir { d with children = leaf_files }
|
||||
| _ -> failwith "Root is always expected to be a directory"
|
||||
)
|
||||
| level ->
|
||||
match root with
|
||||
| Bench_dir.Dir d ->
|
||||
let files = List.init n (fun i -> file (Fmt.str "test-file-%i-%i" level i)) in
|
||||
let dirs = List.init n (fun i -> dir (Fmt.str "test-dir-%i-%i" level i) []) in
|
||||
let dirs = List.map (fun dir -> loop dir (level - 1)) dirs in
|
||||
Bench_dir.Dir { d with children = dirs @ files }
|
||||
| _ -> failwith "Root is always expected to be directory"
|
||||
in
|
||||
loop (dir "root" []) levels
|
||||
|
||||
let run_bench ~n ~levels ~root ~clock =
|
||||
let dir = random_bench_dir ~levels ~n |> Bench_dir.sort in
|
||||
traceln "Going to create %i files and directories" (Bench_dir.size dir);
|
||||
let create_time =
|
||||
let t0 = Eio.Time.now clock in
|
||||
Bench_dir.make root dir;
|
||||
let t1 = Eio.Time.now clock in
|
||||
t1 -. t0
|
||||
in
|
||||
traceln "Created in %.2f s" create_time;
|
||||
let bench () =
|
||||
Gc.full_major ();
|
||||
let stat0 = Gc.stat () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
let res = bench_stat root in
|
||||
let t1 = Eio.Time.now clock in
|
||||
let stat1 = Gc.stat () in
|
||||
match Bench_dir.sort res with
|
||||
| Dir { children = [ dir' ]; _ } ->
|
||||
assert (dir = dir');
|
||||
let time_total = t1 -. t0 in
|
||||
let minor_total = stat1.minor_words -. stat0.minor_words in
|
||||
let major_total = stat1.major_words -. stat0.major_words in
|
||||
time_total, minor_total, major_total
|
||||
| _ -> failwith "Stat not the same as the spec"
|
||||
in
|
||||
let time, minor, major = bench () in
|
||||
traceln "Statted in %.2f s" time;
|
||||
let remove_time =
|
||||
let t0 = Eio.Time.now clock in
|
||||
let root = root / "root" in
|
||||
Eio.Path.read_dir root |> Fiber.List.iter (fun item -> Eio.Path.rmtree (root / item));
|
||||
Eio.Path.rmdir root;
|
||||
let t1 = Eio.Time.now clock in
|
||||
t1 -. t0
|
||||
in
|
||||
traceln "Removed in %.2f s" remove_time;
|
||||
[
|
||||
Metric.create "create-time" (`Float (1e3 *. create_time)) "ms" (Fmt.str "Time to create %i files and directories" (Bench_dir.size dir));
|
||||
Metric.create "stat-time" (`Float (1e3 *. time)) "ms" (Fmt.str "Time to stat %i files and directories" (Bench_dir.size dir));
|
||||
Metric.create "stat-minor" (`Float (1e-3 *. minor)) "kwords" (Fmt.str "Minor words allocated to stat %i files and directories" (Bench_dir.size dir));
|
||||
Metric.create "stat-major" (`Float (1e-3 *. major)) "kwords" (Fmt.str "Major words allocated %i files and directories" (Bench_dir.size dir));
|
||||
Metric.create "remove-time" (`Float (1e3 *. remove_time)) "ms" "Time to remove everything";
|
||||
]
|
||||
|
||||
let run env =
|
||||
let fs = Eio.Stdenv.fs env in
|
||||
let clock = Eio.Stdenv.clock env in
|
||||
with_tmp_dir ~fs "eio-bench-" "-stat" @@ fun root ->
|
||||
run_bench ~n:20 ~levels:4 ~root ~clock
|
@ -44,7 +44,6 @@ let run_bench ~domain_mgr ~clock ~n_send_domains ~n_iters ~capacity =
|
||||
n_iters * n_sender_fibers * n_senders
|
||||
in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
Switch.run (fun sw ->
|
||||
let run_sender () = run_sender ~n_fibers:n_sender_fibers ~n_iters stream in
|
||||
@ -68,25 +67,24 @@ let run_bench ~domain_mgr ~clock ~n_send_domains ~n_iters ~capacity =
|
||||
assert (total = expected_total);
|
||||
let time_total = t1 -. t0 in
|
||||
let time_per_iter = time_total /. float n_iters_total in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
Printf.printf "%14d, %8d, %8d, %7.2f, %13.4f\n%!" n_send_domains n_iters_total capacity (1e9 *. time_per_iter) (prom /. float n_iters_total)
|
||||
Metric.create
|
||||
(Printf.sprintf "sender-domains:%d iterations:%d capacity:%d" n_send_domains n_iters capacity)
|
||||
(`Float (1e9 *. time_per_iter)) "ns"
|
||||
"Time to transmit one item over the stream"
|
||||
|
||||
let main ~domain_mgr ~clock =
|
||||
Printf.printf "n_send_domains, n_iters, capacity, ns/iter, promoted/iter\n%!";
|
||||
[0, 100_000;
|
||||
1, 100_000;
|
||||
2, 100_000;
|
||||
4, 100_000;
|
||||
]
|
||||
|> List.iter (fun (n_send_domains, n_iters) ->
|
||||
[0; 1; 100] |> List.iter (fun capacity ->
|
||||
|> List.concat_map (fun (n_send_domains, n_iters) ->
|
||||
[0; 1; 100] |> List.map (fun capacity ->
|
||||
run_bench ~domain_mgr ~clock ~n_send_domains ~n_iters ~capacity
|
||||
)
|
||||
)
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main
|
||||
~domain_mgr:(Eio.Stdenv.domain_mgr env)
|
||||
~clock:(Eio.Stdenv.clock env)
|
||||
|
76
bench/bench_systhread.ml
Normal file
76
bench/bench_systhread.ml
Normal file
@ -0,0 +1,76 @@
|
||||
(* Measure the overhead of [Eio_unix.run_in_systhread]. *)
|
||||
|
||||
open Eio.Std
|
||||
|
||||
let n_iters = 1000
|
||||
|
||||
let do_syscall () = ignore (Unix.getuid () : int)
|
||||
|
||||
let work () =
|
||||
for _ = 1 to n_iters do
|
||||
Eio_unix.run_in_systhread do_syscall
|
||||
done
|
||||
|
||||
(* Return the average time for one call to [getuid]. *)
|
||||
let run_domain ~fibers =
|
||||
let t0 = Unix.gettimeofday () in
|
||||
Switch.run ~name:"run_domain" (fun sw ->
|
||||
for _ = 1 to fibers do
|
||||
Fiber.fork ~sw work
|
||||
done
|
||||
);
|
||||
let t1 = Unix.gettimeofday () in
|
||||
(t1 -. t0) /. float n_iters
|
||||
|
||||
let time ~domain_mgr ~baseline ~domains ~fibers =
|
||||
let overhead t = t /. baseline in
|
||||
let name = Printf.sprintf "domains:%d fibers:%d" domains fibers in
|
||||
(* Work-around for https://github.com/ocaml/ocaml/issues/12948 *)
|
||||
let main_done, set_main_done = Promise.create () in
|
||||
Switch.run ~name @@ fun sw ->
|
||||
let times =
|
||||
List.init (domains - 1) (fun _ ->
|
||||
Fiber.fork_promise ~sw (fun () ->
|
||||
Eio.Domain_manager.run domain_mgr (fun () ->
|
||||
let r = run_domain ~fibers in
|
||||
Promise.await main_done;
|
||||
r
|
||||
)
|
||||
)
|
||||
)
|
||||
in
|
||||
let my_time = run_domain ~fibers in
|
||||
Promise.resolve set_main_done (); (* Allow Domain.join to be called *)
|
||||
let times =
|
||||
my_time :: List.map Promise.await_exn times
|
||||
|> List.map (fun t -> t *. 1e6)
|
||||
in
|
||||
traceln "%s" name;
|
||||
times |> List.iteri (fun i t ->
|
||||
traceln "%d: %.2f us (%.1f times slower)" i t (overhead t)
|
||||
);
|
||||
let avg = (List.fold_left (+.) 0. times) /. float domains in
|
||||
Metric.create name (`Float avg) "us" name
|
||||
|
||||
let run env =
|
||||
let domain_mgr = env#domain_mgr in
|
||||
let baseline =
|
||||
Eio.Private.Trace.with_span "baseline" @@ fun () ->
|
||||
let t0 = Unix.gettimeofday () in
|
||||
for _ = 1 to n_iters do
|
||||
do_syscall ()
|
||||
done;
|
||||
let t1 = Unix.gettimeofday () in
|
||||
((t1 -. t0) /. float n_iters) *. 1e6
|
||||
in
|
||||
traceln "baseline (no systhreads): %.2f us" baseline;
|
||||
let results =
|
||||
[
|
||||
time ~domains:1 ~fibers:1;
|
||||
time ~domains:1 ~fibers:2;
|
||||
time ~domains:1 ~fibers:4;
|
||||
time ~domains:4 ~fibers:1;
|
||||
]
|
||||
|> List.map (fun f -> f ~domain_mgr ~baseline)
|
||||
in
|
||||
Metric.create "blocking" (`Float baseline) "us" "baseline" :: results
|
@ -1,13 +1,11 @@
|
||||
open Eio.Std
|
||||
|
||||
let n_fibers = [1; 2; 3; 4; 5; 10; 20; 30; 40; 50; 100; 500; 1000; 10000]
|
||||
let n_fibers = [1; 2; (* 3; 4; 5; 10; 20; 30; 40; 50; *) 100; 500; 1000; 10000]
|
||||
|
||||
let main ~clock =
|
||||
Printf.printf "n_fibers, ns/iter, promoted/iter\n%!";
|
||||
n_fibers |> List.iter (fun n_fibers ->
|
||||
n_fibers |> List.map (fun n_fibers ->
|
||||
let n_iters = 1000000 / n_fibers in
|
||||
Gc.full_major ();
|
||||
let _minor0, prom0, _major0 = Gc.counters () in
|
||||
let t0 = Eio.Time.now clock in
|
||||
Switch.run (fun sw ->
|
||||
for _ = 1 to n_fibers do
|
||||
@ -22,11 +20,10 @@ let main ~clock =
|
||||
let time_total = t1 -. t0 in
|
||||
let n_total = n_fibers * n_iters in
|
||||
let time_per_iter = time_total /. float n_total in
|
||||
let _minor1, prom1, _major1 = Gc.counters () in
|
||||
let prom = prom1 -. prom0 in
|
||||
Printf.printf "%8d, % 7.2f, % 13.4f\n%!" n_fibers (1e9 *. time_per_iter) (prom /. float n_total)
|
||||
Metric.create
|
||||
(Printf.sprintf "fibers:%d" n_fibers)
|
||||
(`Float (1e9 *. time_per_iter)) "ns" "Time to yield"
|
||||
)
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
let run env =
|
||||
main ~clock:(Eio.Stdenv.clock env)
|
||||
|
12
bench/dune
12
bench/dune
@ -1,4 +1,8 @@
|
||||
(executables
|
||||
(names bench_stream bench_promise bench_semaphore bench_yield bench_cancel bench_mutex
|
||||
bench_buf_read bench_condition)
|
||||
(libraries eio_main))
|
||||
; This should be an executable, but dune won't let us associate non-installed executables
|
||||
; to packages, so we use this work-around.
|
||||
(test
|
||||
(name main)
|
||||
(package eio_main)
|
||||
(deps ./main.exe)
|
||||
(action (progn)) ; Don't run as a test
|
||||
(libraries eio_main yojson))
|
||||
|
63
bench/main.ml
Normal file
63
bench/main.ml
Normal file
@ -0,0 +1,63 @@
|
||||
open Eio.Std
|
||||
|
||||
let benchmarks = [
|
||||
"Promise", Bench_promise.run;
|
||||
"Cancel", Bench_cancel.run;
|
||||
"Buf_read", Bench_buf_read.run;
|
||||
"Condition", Bench_condition.run;
|
||||
"Fiber.yield", Bench_yield.run;
|
||||
"Mutex", Bench_mutex.run;
|
||||
"Semaphore", Bench_semaphore.run;
|
||||
"Stream", Bench_stream.run;
|
||||
"HTTP", Bench_http.run;
|
||||
"Eio_unix.Fd", Bench_fd.run;
|
||||
"File.stat", Bench_fstat.run;
|
||||
"Path.stat", Bench_stat.run;
|
||||
"Flow.copy", Bench_copy.run;
|
||||
"Eio_unix.run_in_systhread", Bench_systhread.run;
|
||||
]
|
||||
|
||||
let usage_error () =
|
||||
let names = List.map fst benchmarks in
|
||||
Fmt.epr "Usage: main.exe [%a]@." Fmt.(list ~sep:(any " | ") string) names;
|
||||
exit 1
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
traceln "Using %s backend" env#backend_id;
|
||||
let benchmarks =
|
||||
match Array.to_list Sys.argv with
|
||||
| [_] -> benchmarks
|
||||
| [_; name] ->
|
||||
begin match List.assoc_opt name benchmarks with
|
||||
| Some run -> [name, run]
|
||||
| None ->
|
||||
Fmt.epr "Unknown benchmark %S@." name;
|
||||
usage_error ()
|
||||
end
|
||||
| _ -> usage_error ()
|
||||
in
|
||||
let run (name, fn) =
|
||||
traceln "Running %s..." name;
|
||||
let metrics = fn env in
|
||||
`Assoc [
|
||||
"name", `String name;
|
||||
"metrics", `List metrics;
|
||||
]
|
||||
in
|
||||
(* The benchmark machine runs an old Docker that blocks pidfd_open *)
|
||||
(* let uname = Eio.Process.parse_out env#process_mgr Eio.Buf_read.take_all ["uname"; "-a"] in *)
|
||||
let uname =
|
||||
let ch = Unix.open_process_in "uname -a" in
|
||||
let x = input_line ch in
|
||||
close_in ch;
|
||||
x
|
||||
in
|
||||
Fmt.pr "%a@." (Yojson.Safe.pretty_print ~std:true) @@ `Assoc [
|
||||
"config", `Assoc [
|
||||
"uname", `String uname;
|
||||
"backend", `String env#backend_id;
|
||||
"recommended_domain_count", `Int (Domain.recommended_domain_count ());
|
||||
];
|
||||
"results", `List (List.map run benchmarks);
|
||||
]
|
7
bench/metric.ml
Normal file
7
bench/metric.ml
Normal file
@ -0,0 +1,7 @@
|
||||
let create name value units description : Yojson.Safe.t =
|
||||
`Assoc [
|
||||
"name", `String name;
|
||||
"value", (value :> Yojson.Safe.t);
|
||||
"units", `String units;
|
||||
"description", `String description;
|
||||
]
|
3
doc/dune
3
doc/dune
@ -1,4 +1,5 @@
|
||||
(mdx
|
||||
(package eio_main)
|
||||
(deps (package eio_main))
|
||||
(deps (package eio_main) (env_var "EIO_BACKEND"))
|
||||
(enabled_if (<> %{os_type} "Win32"))
|
||||
(files multicore.md))
|
||||
|
@ -4,21 +4,22 @@
|
||||
|
||||
* [Introduction](#introduction)
|
||||
* [Problems with Multicore Programming](#problems-with-multicore-programming)
|
||||
* [Optimisation 1: Caching](#optimisation-1-caching)
|
||||
* [Optimisation 2: Out-of-Order Execution](#optimisation-2-out-of-order-execution)
|
||||
* [Optimisation 3: Compiler Optimisations](#optimisation-3-compiler-optimisations)
|
||||
* [Optimisation 4: Multiple Cores](#optimisation-4-multiple-cores)
|
||||
* [Optimisation 1: Caching](#optimisation-1-caching)
|
||||
* [Optimisation 2: Out-of-Order Execution](#optimisation-2-out-of-order-execution)
|
||||
* [Optimisation 3: Compiler Optimisations](#optimisation-3-compiler-optimisations)
|
||||
* [Optimisation 4: Multiple Cores](#optimisation-4-multiple-cores)
|
||||
* [The OCaml Memory Model](#the-ocaml-memory-model)
|
||||
* [Atomic Locations](#atomic-locations)
|
||||
* [Initialisation](#initialisation)
|
||||
* [Guidelines](#guidelines)
|
||||
* [Atomic Locations](#atomic-locations)
|
||||
* [Initialisation](#initialisation)
|
||||
* [Safety Guidelines](#safety-guidelines)
|
||||
* [Performance Guidelines](#performance-guidelines)
|
||||
* [Further Reading](#further-reading)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
## Introduction
|
||||
|
||||
OCaml 5.00 adds support for using multiple CPU cores in a single OCaml process.
|
||||
OCaml 5.0 adds support for using multiple CPU cores in a single OCaml process.
|
||||
An OCaml process is made up of one or more *domains*, and
|
||||
the operating system can run each domain on a different core, so that they run in parallel.
|
||||
This can make programs run much faster, but also introduces new ways for programs to go wrong.
|
||||
@ -446,7 +447,7 @@ So it will always see a correct list:
|
||||
- : unit = ()
|
||||
```
|
||||
|
||||
## Guidelines
|
||||
## Safety Guidelines
|
||||
|
||||
It's important to understand the above to avoid writing incorrect code,
|
||||
but there are several general principles that avoid most problems:
|
||||
@ -502,6 +503,28 @@ Finally, note that OCaml remains type-safe even with multiple domains.
|
||||
For example, accessing a `Queue` in parallel from multiple domains may result in a corrupted queue,
|
||||
but it won't cause a segfault.
|
||||
|
||||
## Performance Guidelines
|
||||
|
||||
The following recommendations will help you extract as much performance as possible from your hardware:
|
||||
|
||||
- There's a certain overhead associated with placing execution onto another domain,
|
||||
but that overhead will be paid off quickly if your job takes at least a few milliseconds to complete.
|
||||
Jobs that complete under 2-5ms may not be worth running on a separate domain.
|
||||
- Similarly, jobs that are 100% I/O-bound may not be worth running on a separate domain.
|
||||
The small initial overhead is simply never recouped.
|
||||
- If your program never hits 100% CPU usage, it's unlikely that parallelizing it will improve performance.
|
||||
- Try to avoid reading or writing to memory that's modified by other domains after the start of your job.
|
||||
Ideally, your jobs shouldn't need to interact with other domains' "working data".
|
||||
Aim to make your jobs as independent as possible.
|
||||
If unavoidable, the [Saturn](https://github.com/ocaml-multicore/saturn) library offers a collection of efficient threadsafe data structures.
|
||||
- It's often easier to design code to be multithreading friendly from the start
|
||||
(by making longer, independent jobs) than by refactoring existing code.
|
||||
- There's a cost associated with creating a domain, so try to use the same domains for longer periods of time.
|
||||
`Eio.Executor_pool` takes care of this automatically.
|
||||
- Obviously, reuse the same executor pool whenever possible! Don't recreate it over and over.
|
||||
- Having a large number of domains active at the same time imposes additional overhead on
|
||||
both the OS scheduler and the OCaml runtime, even if those domains are idle.
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [OCaml Memory Model][] describes the full details of the memory model.
|
||||
|
@ -1,44 +1,34 @@
|
||||
#require "eio_main";;
|
||||
#require "eio.mock";;
|
||||
|
||||
module Eio_main = struct
|
||||
open Eio.Std
|
||||
|
||||
let now = ref 1623940778.27033591
|
||||
|
||||
let fake_clock real_clock = object (_ : #Eio.Time.clock)
|
||||
method now = !now
|
||||
method sleep_until time =
|
||||
(* The fake times are all in the past, so we just ask to wait until the
|
||||
fake time is due and it will happen immediately. If we wait for
|
||||
multiple times, they'll get woken in the right order. At the moment,
|
||||
the scheduler only checks for expired timers when the run-queue is
|
||||
empty, so this is a convenient way to wait for the system to be idle.
|
||||
TODO: This is no longer true (since #213). *)
|
||||
Eio.Time.sleep_until real_clock time;
|
||||
now := max !now time
|
||||
module Fake_clock = struct
|
||||
type time = float
|
||||
type t = unit
|
||||
let sleep_until () _time = failwith "No sleeping in tests!"
|
||||
let now _ = 1623940778.27033591
|
||||
end
|
||||
|
||||
(* To avoid non-deterministic output, we run the examples a single domain. *)
|
||||
let fake_domain_mgr = object (_ : #Eio.Domain_manager.t)
|
||||
method run fn =
|
||||
(* Since we're in the same domain, cancelling the calling fiber will
|
||||
cancel the fake spawned one automatically. *)
|
||||
let cancelled, _ = Promise.create () in
|
||||
fn ~cancelled
|
||||
|
||||
method run_raw fn = fn ()
|
||||
end
|
||||
let fake_clock =
|
||||
let handler = Eio.Time.Pi.clock (module Fake_clock) in
|
||||
Eio.Resource.T ((), handler)
|
||||
|
||||
let run fn =
|
||||
(* To avoid non-deterministic output, we run the examples a single domain. *)
|
||||
let fake_domain_mgr = Eio_mock.Domain_manager.create () in
|
||||
Eio_main.run @@ fun env ->
|
||||
fn @@ object
|
||||
method net = env#net
|
||||
method stdin = env#stdin
|
||||
method stdout = env#stdout
|
||||
method cwd = env#cwd
|
||||
method domain_mgr = fake_domain_mgr
|
||||
method clock = fake_clock env#clock
|
||||
method net = env#net
|
||||
method stdin = env#stdin
|
||||
method stdout = env#stdout
|
||||
method stderr = env#stderr
|
||||
method cwd = env#cwd
|
||||
method process_mgr = env#process_mgr
|
||||
method domain_mgr = fake_domain_mgr
|
||||
method clock = fake_clock
|
||||
end
|
||||
end
|
||||
|
||||
let parse_config (flow : #Eio.Flow.source) = ignore
|
||||
let parse_config (flow : _ Eio.Flow.source) = ignore
|
||||
|
@ -69,7 +69,7 @@ For example, there are many ways to provide a stream of bytes (from a file, TCP
|
||||
Often this choice is determined by the user at runtime, for example by providing a URL giving the scheme to use.
|
||||
We may even need to choose a completely different Eio backend at runtime.
|
||||
For example `Eio_main.run` will use the io_uring backend if the Linux kernel is new enough,
|
||||
but fall back to `Eio_luv` if not.
|
||||
but fall back to `Eio_posix` if not.
|
||||
For these reasons, Eio needs to use dynamic dispatch.
|
||||
|
||||
A resource whose implementation isn't known until runtime can be represented in many ways, including:
|
||||
@ -125,7 +125,7 @@ For dynamic dispatch with subtyping, objects seem to be the best choice:
|
||||
An object uses a single block to store the object's fields and a pointer to the shared method table.
|
||||
|
||||
- First-class modules and GADTs are an advanced feature of the language.
|
||||
The new users we hope to attract to OCaml 5.00 are likely to be familiar with objects already.
|
||||
The new users we hope to attract to OCaml 5.0 are likely to be familiar with objects already.
|
||||
|
||||
- It is possible to provide base classes with default implementations of some methods.
|
||||
This can allow adding new operations to the API in future without breaking existing providers.
|
||||
@ -133,24 +133,19 @@ For dynamic dispatch with subtyping, objects seem to be the best choice:
|
||||
In general, simulating objects using other features of the language leads to worse performance
|
||||
and worse ergonomics than using the language's built-in support.
|
||||
|
||||
In Eio, we split the provider and consumer APIs:
|
||||
However, in order for Eio to be widely accepted in the OCaml community,
|
||||
we no longer use of objects and instead use a pair of a value and a function for looking up interfaces.
|
||||
There is a problem here, because each interface has a different type,
|
||||
so the function's return type depends on its input (the interface ID).
|
||||
This requires using a GADT. However, GADT's don't support sub-typing.
|
||||
To get around this, we use an extensible GADT to get the correct typing
|
||||
(but which will raise an exception if the interface isn't supported),
|
||||
and then wrap this with a polymorphic variant phantom type to help ensure
|
||||
it is used correctly.
|
||||
|
||||
- To *provide* a flow, you implement an object type.
|
||||
- To *use* a flow, you call a function (e.g. `Flow.close`).
|
||||
|
||||
The functions mostly just call the corresponding method on the object.
|
||||
If you call object methods directly in OCaml then you tend to get poor compiler error messages.
|
||||
This is because OCaml can only refer to the object types by listing the methods you seem to want to use.
|
||||
Using functions avoids this, because the function signature specifies the type of its argument,
|
||||
allowing type inference to work as for non-object code.
|
||||
In this way, users of Eio can be largely unaware that objects are being used at all.
|
||||
|
||||
The function wrappers can also provide extra checks that the API is being followed correctly,
|
||||
such as asserting that a read does not return 0 bytes,
|
||||
or add extra convenience functions without forcing every implementor to add them too.
|
||||
|
||||
Note that the use of objects in Eio is not motivated by the use of the "Object Capabilities" security model.
|
||||
Despite the name, that is not specific to objects at all.
|
||||
This system gives the same performance as using objects and without requiring allocation.
|
||||
However, care is needed when defining new interfaces,
|
||||
since the compiler can't check that the resource really implements all the interfaces its phantom type suggests.
|
||||
|
||||
## Results vs Exceptions
|
||||
|
||||
|
223
doc/trace.svg
223
doc/trace.svg
@ -1,223 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="580pt" height="132pt" viewBox="0 0 580 132" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d="M 0.59375 2.125 L 0.59375 -8.46875 L 6.59375 -8.46875 L 6.59375 2.125 Z M 1.265625 1.453125 L 5.9375 1.453125 L 5.9375 -7.78125 L 1.265625 -7.78125 Z M 1.265625 1.453125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 1.171875 -8.75 L 6.703125 -8.75 L 6.703125 -7.75 L 2.359375 -7.75 L 2.359375 -5.15625 L 6.53125 -5.15625 L 6.53125 -4.171875 L 2.359375 -4.171875 L 2.359375 -1 L 6.8125 -1 L 6.8125 0 L 1.171875 0 Z M 1.171875 -8.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 4.109375 -3.296875 C 3.242188 -3.296875 2.640625 -3.195312 2.296875 -3 C 1.960938 -2.800781 1.796875 -2.460938 1.796875 -1.984375 C 1.796875 -1.597656 1.921875 -1.289062 2.171875 -1.0625 C 2.429688 -0.84375 2.773438 -0.734375 3.203125 -0.734375 C 3.804688 -0.734375 4.285156 -0.941406 4.640625 -1.359375 C 5.003906 -1.785156 5.1875 -2.351562 5.1875 -3.0625 L 5.1875 -3.296875 Z M 6.265625 -3.75 L 6.265625 0 L 5.1875 0 L 5.1875 -1 C 4.9375 -0.601562 4.628906 -0.304688 4.265625 -0.109375 C 3.898438 0.078125 3.453125 0.171875 2.921875 0.171875 C 2.242188 0.171875 1.707031 -0.015625 1.3125 -0.390625 C 0.914062 -0.773438 0.71875 -1.28125 0.71875 -1.90625 C 0.71875 -2.644531 0.960938 -3.203125 1.453125 -3.578125 C 1.953125 -3.953125 2.691406 -4.140625 3.671875 -4.140625 L 5.1875 -4.140625 L 5.1875 -4.25 C 5.1875 -4.75 5.019531 -5.132812 4.6875 -5.40625 C 4.363281 -5.675781 3.910156 -5.8125 3.328125 -5.8125 C 2.953125 -5.8125 2.582031 -5.765625 2.21875 -5.671875 C 1.863281 -5.578125 1.523438 -5.441406 1.203125 -5.265625 L 1.203125 -6.265625 C 1.597656 -6.421875 1.976562 -6.535156 2.34375 -6.609375 C 2.71875 -6.679688 3.082031 -6.71875 3.4375 -6.71875 C 4.382812 -6.71875 5.09375 -6.472656 5.5625 -5.984375 C 6.03125 -5.492188 6.265625 -4.75 6.265625 -3.75 Z M 6.265625 -3.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 5.859375 -6.3125 L 5.859375 -5.296875 C 5.546875 -5.472656 5.238281 -5.601562 4.9375 -5.6875 C 4.632812 -5.769531 4.328125 -5.8125 4.015625 -5.8125 C 3.304688 -5.8125 2.757812 -5.585938 2.375 -5.140625 C 1.988281 -4.703125 1.796875 -4.082031 1.796875 -3.28125 C 1.796875 -2.476562 1.988281 -1.851562 2.375 -1.40625 C 2.757812 -0.96875 3.304688 -0.75 4.015625 -0.75 C 4.328125 -0.75 4.632812 -0.789062 4.9375 -0.875 C 5.238281 -0.957031 5.546875 -1.082031 5.859375 -1.25 L 5.859375 -0.25 C 5.554688 -0.113281 5.242188 -0.0078125 4.921875 0.0625 C 4.597656 0.132812 4.253906 0.171875 3.890625 0.171875 C 2.898438 0.171875 2.113281 -0.132812 1.53125 -0.75 C 0.945312 -1.375 0.65625 -2.21875 0.65625 -3.28125 C 0.65625 -4.34375 0.945312 -5.179688 1.53125 -5.796875 C 2.125 -6.410156 2.9375 -6.71875 3.96875 -6.71875 C 4.289062 -6.71875 4.609375 -6.679688 4.921875 -6.609375 C 5.242188 -6.546875 5.554688 -6.445312 5.859375 -6.3125 Z M 5.859375 -6.3125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -9.125 L 2.171875 -9.125 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 5.453125 -3.359375 C 5.453125 -4.140625 5.289062 -4.742188 4.96875 -5.171875 C 4.644531 -5.597656 4.191406 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.597656 2.265625 -5.171875 C 1.941406 -4.742188 1.78125 -4.140625 1.78125 -3.359375 C 1.78125 -2.578125 1.941406 -1.972656 2.265625 -1.546875 C 2.585938 -1.117188 3.035156 -0.90625 3.609375 -0.90625 C 4.191406 -0.90625 4.644531 -1.117188 4.96875 -1.546875 C 5.289062 -1.972656 5.453125 -2.578125 5.453125 -3.359375 Z M 6.53125 -0.8125 C 6.53125 0.300781 6.28125 1.128906 5.78125 1.671875 C 5.289062 2.222656 4.53125 2.5 3.5 2.5 C 3.125 2.5 2.765625 2.46875 2.421875 2.40625 C 2.085938 2.351562 1.765625 2.269531 1.453125 2.15625 L 1.453125 1.109375 C 1.765625 1.273438 2.078125 1.398438 2.390625 1.484375 C 2.703125 1.566406 3.015625 1.609375 3.328125 1.609375 C 4.035156 1.609375 4.566406 1.421875 4.921875 1.046875 C 5.273438 0.679688 5.453125 0.125 5.453125 -0.625 L 5.453125 -1.15625 C 5.222656 -0.769531 4.9375 -0.476562 4.59375 -0.28125 C 4.25 -0.09375 3.832031 0 3.34375 0 C 2.539062 0 1.890625 -0.304688 1.390625 -0.921875 C 0.898438 -1.535156 0.65625 -2.347656 0.65625 -3.359375 C 0.65625 -4.367188 0.898438 -5.179688 1.390625 -5.796875 C 1.890625 -6.410156 2.539062 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.617188 4.59375 -6.421875 C 4.9375 -6.234375 5.222656 -5.945312 5.453125 -5.5625 L 5.453125 -6.5625 L 6.53125 -6.5625 Z M 6.53125 -0.8125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-7">
|
||||
<path style="stroke:none;" d="M 4.9375 -5.5625 C 4.8125 -5.625 4.675781 -5.671875 4.53125 -5.703125 C 4.394531 -5.742188 4.238281 -5.765625 4.0625 -5.765625 C 3.457031 -5.765625 2.988281 -5.566406 2.65625 -5.171875 C 2.332031 -4.773438 2.171875 -4.203125 2.171875 -3.453125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.398438 -5.941406 2.695312 -6.234375 3.0625 -6.421875 C 3.425781 -6.617188 3.867188 -6.71875 4.390625 -6.71875 C 4.460938 -6.71875 4.539062 -6.710938 4.625 -6.703125 C 4.71875 -6.691406 4.816406 -6.675781 4.921875 -6.65625 Z M 4.9375 -5.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-8">
|
||||
<path style="stroke:none;" d="M 1.125 -6.5625 L 2.203125 -6.5625 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 -7.75 L 1.125 -7.75 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-9">
|
||||
<path style="stroke:none;" d="M 5.453125 -5.5625 L 5.453125 -9.125 L 6.53125 -9.125 L 6.53125 0 L 5.453125 0 L 5.453125 -0.984375 C 5.222656 -0.597656 4.9375 -0.304688 4.59375 -0.109375 C 4.25 0.078125 3.832031 0.171875 3.34375 0.171875 C 2.550781 0.171875 1.90625 -0.144531 1.40625 -0.78125 C 0.90625 -1.414062 0.65625 -2.25 0.65625 -3.28125 C 0.65625 -4.3125 0.90625 -5.140625 1.40625 -5.765625 C 1.90625 -6.398438 2.550781 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.625 4.59375 -6.4375 C 4.9375 -6.25 5.222656 -5.957031 5.453125 -5.5625 Z M 1.78125 -3.28125 C 1.78125 -2.488281 1.941406 -1.863281 2.265625 -1.40625 C 2.585938 -0.957031 3.035156 -0.734375 3.609375 -0.734375 C 4.179688 -0.734375 4.628906 -0.957031 4.953125 -1.40625 C 5.285156 -1.863281 5.453125 -2.488281 5.453125 -3.28125 C 5.453125 -4.070312 5.285156 -4.691406 4.953125 -5.140625 C 4.628906 -5.585938 4.179688 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.585938 2.265625 -5.140625 C 1.941406 -4.691406 1.78125 -4.070312 1.78125 -3.28125 Z M 1.78125 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-10">
|
||||
<path style="stroke:none;" d="M 0.359375 -6.5625 L 1.5 -6.5625 L 3.546875 -1.0625 L 5.609375 -6.5625 L 6.75 -6.5625 L 4.28125 0 L 2.8125 0 Z M 0.359375 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-11">
|
||||
<path style="stroke:none;" d="M 5.3125 -6.375 L 5.3125 -5.34375 C 5.007812 -5.5 4.691406 -5.613281 4.359375 -5.6875 C 4.035156 -5.769531 3.695312 -5.8125 3.34375 -5.8125 C 2.8125 -5.8125 2.410156 -5.726562 2.140625 -5.5625 C 1.867188 -5.40625 1.734375 -5.160156 1.734375 -4.828125 C 1.734375 -4.578125 1.828125 -4.378906 2.015625 -4.234375 C 2.210938 -4.097656 2.601562 -3.96875 3.1875 -3.84375 L 3.546875 -3.75 C 4.316406 -3.59375 4.863281 -3.363281 5.1875 -3.0625 C 5.507812 -2.757812 5.671875 -2.34375 5.671875 -1.8125 C 5.671875 -1.195312 5.425781 -0.710938 4.9375 -0.359375 C 4.457031 -0.00390625 3.796875 0.171875 2.953125 0.171875 C 2.597656 0.171875 2.226562 0.132812 1.84375 0.0625 C 1.46875 0 1.070312 -0.0976562 0.65625 -0.234375 L 0.65625 -1.359375 C 1.050781 -1.148438 1.441406 -0.992188 1.828125 -0.890625 C 2.210938 -0.785156 2.597656 -0.734375 2.984375 -0.734375 C 3.484375 -0.734375 3.867188 -0.816406 4.140625 -0.984375 C 4.421875 -1.160156 4.5625 -1.410156 4.5625 -1.734375 C 4.5625 -2.023438 4.460938 -2.25 4.265625 -2.40625 C 4.066406 -2.5625 3.632812 -2.710938 2.96875 -2.859375 L 2.59375 -2.9375 C 1.925781 -3.082031 1.441406 -3.300781 1.140625 -3.59375 C 0.847656 -3.882812 0.703125 -4.28125 0.703125 -4.78125 C 0.703125 -5.40625 0.921875 -5.882812 1.359375 -6.21875 C 1.796875 -6.550781 2.414062 -6.71875 3.21875 -6.71875 C 3.613281 -6.71875 3.988281 -6.6875 4.34375 -6.625 C 4.695312 -6.570312 5.019531 -6.488281 5.3125 -6.375 Z M 5.3125 -6.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-12">
|
||||
<path style="stroke:none;" d="M 3.671875 -5.8125 C 3.097656 -5.8125 2.640625 -5.582031 2.296875 -5.125 C 1.960938 -4.675781 1.796875 -4.0625 1.796875 -3.28125 C 1.796875 -2.488281 1.960938 -1.867188 2.296875 -1.421875 C 2.628906 -0.972656 3.085938 -0.75 3.671875 -0.75 C 4.242188 -0.75 4.695312 -0.972656 5.03125 -1.421875 C 5.375 -1.878906 5.546875 -2.5 5.546875 -3.28125 C 5.546875 -4.050781 5.375 -4.664062 5.03125 -5.125 C 4.695312 -5.582031 4.242188 -5.8125 3.671875 -5.8125 Z M 3.671875 -6.71875 C 4.609375 -6.71875 5.34375 -6.410156 5.875 -5.796875 C 6.414062 -5.191406 6.6875 -4.351562 6.6875 -3.28125 C 6.6875 -2.207031 6.414062 -1.363281 5.875 -0.75 C 5.34375 -0.132812 4.609375 0.171875 3.671875 0.171875 C 2.734375 0.171875 1.992188 -0.132812 1.453125 -0.75 C 0.921875 -1.363281 0.65625 -2.207031 0.65625 -3.28125 C 0.65625 -4.351562 0.921875 -5.191406 1.453125 -5.796875 C 1.992188 -6.410156 2.734375 -6.71875 3.671875 -6.71875 Z M 3.671875 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-13">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-14">
|
||||
<path style="stroke:none;" d="M 1.40625 -1.484375 L 2.640625 -1.484375 L 2.640625 0 L 1.40625 0 Z M 1.40625 -6.203125 L 2.640625 -6.203125 L 2.640625 -4.71875 L 1.40625 -4.71875 Z M 1.40625 -6.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-15">
|
||||
<path style="stroke:none;" d="M 1.484375 -1 L 3.421875 -1 L 3.421875 -7.671875 L 1.3125 -7.25 L 1.3125 -8.328125 L 3.40625 -8.75 L 4.59375 -8.75 L 4.59375 -1 L 6.53125 -1 L 6.53125 0 L 1.484375 0 Z M 1.484375 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-16">
|
||||
<path style="stroke:none;" d="M 3.8125 -7.96875 C 3.207031 -7.96875 2.75 -7.664062 2.4375 -7.0625 C 2.132812 -6.46875 1.984375 -5.566406 1.984375 -4.359375 C 1.984375 -3.160156 2.132812 -2.257812 2.4375 -1.65625 C 2.75 -1.0625 3.207031 -0.765625 3.8125 -0.765625 C 4.425781 -0.765625 4.882812 -1.0625 5.1875 -1.65625 C 5.5 -2.257812 5.65625 -3.160156 5.65625 -4.359375 C 5.65625 -5.566406 5.5 -6.46875 5.1875 -7.0625 C 4.882812 -7.664062 4.425781 -7.96875 3.8125 -7.96875 Z M 3.8125 -8.90625 C 4.789062 -8.90625 5.539062 -8.515625 6.0625 -7.734375 C 6.582031 -6.960938 6.84375 -5.835938 6.84375 -4.359375 C 6.84375 -2.890625 6.582031 -1.765625 6.0625 -0.984375 C 5.539062 -0.210938 4.789062 0.171875 3.8125 0.171875 C 2.832031 0.171875 2.082031 -0.210938 1.5625 -0.984375 C 1.050781 -1.765625 0.796875 -2.890625 0.796875 -4.359375 C 0.796875 -5.835938 1.050781 -6.960938 1.5625 -7.734375 C 2.082031 -8.515625 2.832031 -8.90625 3.8125 -8.90625 Z M 3.8125 -8.90625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-17">
|
||||
<path style="stroke:none;" d="M 1.015625 -2.59375 L 1.015625 -6.5625 L 2.09375 -6.5625 L 2.09375 -2.625 C 2.09375 -2.007812 2.210938 -1.546875 2.453125 -1.234375 C 2.703125 -0.921875 3.066406 -0.765625 3.546875 -0.765625 C 4.128906 -0.765625 4.585938 -0.945312 4.921875 -1.3125 C 5.265625 -1.6875 5.4375 -2.195312 5.4375 -2.84375 L 5.4375 -6.5625 L 6.515625 -6.5625 L 6.515625 0 L 5.4375 0 L 5.4375 -1.015625 C 5.175781 -0.609375 4.875 -0.304688 4.53125 -0.109375 C 4.1875 0.078125 3.785156 0.171875 3.328125 0.171875 C 2.566406 0.171875 1.988281 -0.0625 1.59375 -0.53125 C 1.207031 -1 1.015625 -1.6875 1.015625 -2.59375 Z M 3.734375 -6.71875 Z M 3.734375 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-18">
|
||||
<path style="stroke:none;" d="M 3.859375 0.609375 C 3.554688 1.390625 3.257812 1.898438 2.96875 2.140625 C 2.675781 2.378906 2.289062 2.5 1.8125 2.5 L 0.953125 2.5 L 0.953125 1.59375 L 1.578125 1.59375 C 1.878906 1.59375 2.109375 1.519531 2.265625 1.375 C 2.429688 1.238281 2.613281 0.910156 2.8125 0.390625 L 3.015625 -0.109375 L 0.359375 -6.5625 L 1.5 -6.5625 L 3.546875 -1.4375 L 5.609375 -6.5625 L 6.75 -6.5625 Z M 3.859375 0.609375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-19">
|
||||
<path style="stroke:none;" d="M 1.265625 -5.453125 L 8.78125 -5.453125 L 8.78125 -4.46875 L 1.265625 -4.46875 Z M 1.265625 -3.0625 L 8.78125 -3.0625 L 8.78125 -2.0625 L 1.265625 -2.0625 Z M 1.265625 -3.0625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-20">
|
||||
<path style="stroke:none;" d="M 2.296875 -1 L 6.4375 -1 L 6.4375 0 L 0.875 0 L 0.875 -1 C 1.320312 -1.457031 1.929688 -2.078125 2.703125 -2.859375 C 3.484375 -3.648438 3.972656 -4.160156 4.171875 -4.390625 C 4.554688 -4.804688 4.820312 -5.160156 4.96875 -5.453125 C 5.125 -5.753906 5.203125 -6.046875 5.203125 -6.328125 C 5.203125 -6.796875 5.035156 -7.175781 4.703125 -7.46875 C 4.378906 -7.757812 3.957031 -7.90625 3.4375 -7.90625 C 3.0625 -7.90625 2.664062 -7.84375 2.25 -7.71875 C 1.84375 -7.59375 1.40625 -7.394531 0.9375 -7.125 L 0.9375 -8.328125 C 1.414062 -8.515625 1.859375 -8.65625 2.265625 -8.75 C 2.679688 -8.851562 3.0625 -8.90625 3.40625 -8.90625 C 4.3125 -8.90625 5.035156 -8.675781 5.578125 -8.21875 C 6.117188 -7.769531 6.390625 -7.164062 6.390625 -6.40625 C 6.390625 -6.050781 6.320312 -5.710938 6.1875 -5.390625 C 6.050781 -5.066406 5.804688 -4.6875 5.453125 -4.25 C 5.347656 -4.132812 5.035156 -3.804688 4.515625 -3.265625 C 3.992188 -2.722656 3.253906 -1.96875 2.296875 -1 Z M 2.296875 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-21">
|
||||
<path style="stroke:none;" d="M 4.875 -4.71875 C 5.4375 -4.59375 5.875 -4.335938 6.1875 -3.953125 C 6.507812 -3.578125 6.671875 -3.109375 6.671875 -2.546875 C 6.671875 -1.679688 6.375 -1.007812 5.78125 -0.53125 C 5.1875 -0.0625 4.34375 0.171875 3.25 0.171875 C 2.882812 0.171875 2.503906 0.132812 2.109375 0.0625 C 1.722656 -0.0078125 1.328125 -0.117188 0.921875 -0.265625 L 0.921875 -1.40625 C 1.242188 -1.21875 1.597656 -1.070312 1.984375 -0.96875 C 2.378906 -0.875 2.789062 -0.828125 3.21875 -0.828125 C 3.957031 -0.828125 4.519531 -0.972656 4.90625 -1.265625 C 5.300781 -1.554688 5.5 -1.984375 5.5 -2.546875 C 5.5 -3.054688 5.316406 -3.457031 4.953125 -3.75 C 4.585938 -4.039062 4.085938 -4.1875 3.453125 -4.1875 L 2.421875 -4.1875 L 2.421875 -5.15625 L 3.5 -5.15625 C 4.070312 -5.15625 4.515625 -5.269531 4.828125 -5.5 C 5.140625 -5.738281 5.296875 -6.078125 5.296875 -6.515625 C 5.296875 -6.960938 5.132812 -7.304688 4.8125 -7.546875 C 4.5 -7.785156 4.046875 -7.90625 3.453125 -7.90625 C 3.117188 -7.90625 2.765625 -7.867188 2.390625 -7.796875 C 2.023438 -7.734375 1.617188 -7.628906 1.171875 -7.484375 L 1.171875 -8.53125 C 1.628906 -8.65625 2.050781 -8.75 2.4375 -8.8125 C 2.832031 -8.875 3.203125 -8.90625 3.546875 -8.90625 C 4.453125 -8.90625 5.164062 -8.703125 5.6875 -8.296875 C 6.207031 -7.890625 6.46875 -7.335938 6.46875 -6.640625 C 6.46875 -6.148438 6.328125 -5.738281 6.046875 -5.40625 C 5.773438 -5.070312 5.382812 -4.84375 4.875 -4.71875 Z M 4.875 -4.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-22">
|
||||
<path style="stroke:none;" d="M 6.59375 -6.5625 L 4.21875 -3.375 L 6.703125 0 L 5.4375 0 L 3.53125 -2.578125 L 1.625 0 L 0.34375 0 L 2.890625 -3.4375 L 0.5625 -6.5625 L 1.828125 -6.5625 L 3.578125 -4.21875 L 5.3125 -6.5625 Z M 6.59375 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-23">
|
||||
<path style="stroke:none;" d="M 2.171875 -0.984375 L 2.171875 2.5 L 1.09375 2.5 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.5625 C 2.398438 -5.957031 2.6875 -6.25 3.03125 -6.4375 C 3.375 -6.625 3.785156 -6.71875 4.265625 -6.71875 C 5.066406 -6.71875 5.71875 -6.398438 6.21875 -5.765625 C 6.71875 -5.140625 6.96875 -4.3125 6.96875 -3.28125 C 6.96875 -2.25 6.71875 -1.414062 6.21875 -0.78125 C 5.71875 -0.144531 5.066406 0.171875 4.265625 0.171875 C 3.785156 0.171875 3.375 0.078125 3.03125 -0.109375 C 2.6875 -0.304688 2.398438 -0.597656 2.171875 -0.984375 Z M 5.84375 -3.28125 C 5.84375 -4.070312 5.675781 -4.691406 5.34375 -5.140625 C 5.019531 -5.585938 4.578125 -5.8125 4.015625 -5.8125 C 3.441406 -5.8125 2.988281 -5.585938 2.65625 -5.140625 C 2.332031 -4.691406 2.171875 -4.070312 2.171875 -3.28125 C 2.171875 -2.488281 2.332031 -1.863281 2.65625 -1.40625 C 2.988281 -0.957031 3.441406 -0.734375 4.015625 -0.734375 C 4.578125 -0.734375 5.019531 -0.957031 5.34375 -1.40625 C 5.675781 -1.863281 5.84375 -2.488281 5.84375 -3.28125 Z M 5.84375 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-24">
|
||||
<path style="stroke:none;" d="M 6.75 -3.546875 L 6.75 -3.03125 L 1.78125 -3.03125 C 1.832031 -2.28125 2.054688 -1.710938 2.453125 -1.328125 C 2.859375 -0.941406 3.414062 -0.75 4.125 -0.75 C 4.539062 -0.75 4.941406 -0.796875 5.328125 -0.890625 C 5.722656 -0.992188 6.113281 -1.148438 6.5 -1.359375 L 6.5 -0.328125 C 6.101562 -0.171875 5.703125 -0.0507812 5.296875 0.03125 C 4.890625 0.125 4.476562 0.171875 4.0625 0.171875 C 3.019531 0.171875 2.191406 -0.128906 1.578125 -0.734375 C 0.960938 -1.347656 0.65625 -2.175781 0.65625 -3.21875 C 0.65625 -4.289062 0.945312 -5.140625 1.53125 -5.765625 C 2.113281 -6.398438 2.894531 -6.71875 3.875 -6.71875 C 4.757812 -6.71875 5.457031 -6.429688 5.96875 -5.859375 C 6.488281 -5.296875 6.75 -4.523438 6.75 -3.546875 Z M 5.671875 -3.875 C 5.660156 -4.457031 5.492188 -4.925781 5.171875 -5.28125 C 4.847656 -5.632812 4.421875 -5.8125 3.890625 -5.8125 C 3.285156 -5.8125 2.800781 -5.640625 2.4375 -5.296875 C 2.082031 -4.953125 1.878906 -4.472656 1.828125 -3.859375 Z M 5.671875 -3.875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-25">
|
||||
<path style="stroke:none;" d="M 2.203125 -8.421875 L 2.203125 -6.5625 L 4.421875 -6.5625 L 4.421875 -5.71875 L 2.203125 -5.71875 L 2.203125 -2.15625 C 2.203125 -1.625 2.273438 -1.28125 2.421875 -1.125 C 2.566406 -0.976562 2.863281 -0.90625 3.3125 -0.90625 L 4.421875 -0.90625 L 4.421875 0 L 3.3125 0 C 2.476562 0 1.898438 -0.15625 1.578125 -0.46875 C 1.265625 -0.78125 1.109375 -1.34375 1.109375 -2.15625 L 1.109375 -5.71875 L 0.328125 -5.71875 L 0.328125 -6.5625 L 1.109375 -6.5625 L 1.109375 -8.421875 Z M 2.203125 -8.421875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-26">
|
||||
<path style="stroke:none;" d="M 1.09375 -9.125 L 2.171875 -9.125 L 2.171875 -3.734375 L 5.390625 -6.5625 L 6.765625 -6.5625 L 3.28125 -3.5 L 6.921875 0 L 5.515625 0 L 2.171875 -3.203125 L 2.171875 0 L 1.09375 0 Z M 1.09375 -9.125 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 1 0 L 579 0 L 579 132 L 1 132 Z M 1 0 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface845">
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<rect x="0" y="0" width="580" height="132" style="fill:rgb(90%,90%,90%);fill-opacity:1;stroke:none;"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 2.59375 0 L 2.59375 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 34.976562 0 L 34.976562 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 67.363281 0 L 67.363281 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 99.75 0 L 99.75 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 132.132812 0 L 132.132812 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 164.519531 0 L 164.519531 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.90625 0 L 196.90625 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 229.289062 0 L 229.289062 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 261.675781 0 L 261.675781 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 294.0625 0 L 294.0625 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 326.445312 0 L 326.445312 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 358.832031 0 L 358.832031 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 391.21875 0 L 391.21875 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 423.601562 0 L 423.601562 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 455.988281 0 L 455.988281 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 488.371094 0 L 488.371094 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 520.757812 0 L 520.757812 132 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 553.144531 0 L 553.144531 132 "/>
|
||||
<g style="fill:rgb(40%,40%,40%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="4" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-2" x="11.582031" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-3" x="18.935547" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-4" x="25.533203" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="33.138672" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-6" x="36.953125" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-7" x="44.570312" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="49.503906" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="52.837891" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="60.455078" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="64.269531" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="71.886719" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-10" x="75.220703" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="82.322266" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="85.65625" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="91.908203" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-12" x="95.242188" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-13" x="102.583984" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-14" x="110.189453" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="114.232422" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-15" x="118.046875" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-16" x="125.681641" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="133.316406" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-17" x="137.130859" y="127.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="144.736328" y="127.503906"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(20%,20%,20%);stroke-opacity:1;stroke-miterlimit:10;" d="M 2.59375 31.183594 L 573.648438 31.183594 "/>
|
||||
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(20%,20%,20%);stroke-opacity:1;stroke-miterlimit:10;" d="M 38.8125 31.183594 L 38.8125 102 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(20%,20%,20%);fill-opacity:1;" d="M 573.648438 31.183594 L 567.648438 27.183594 L 567.648438 35.183594 "/>
|
||||
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(20%,20%,20%);stroke-opacity:1;stroke-miterlimit:10;" d="M 38.8125 102 L 557.929688 102 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 565.921875 31.183594 L 570.410156 31.183594 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 480.792969 31.183594 L 552.542969 31.183594 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 322.886719 31.183594 L 402.945312 31.183594 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.828125 31.183594 L 247.347656 31.183594 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 2.59375 31.183594 L 46.933594 31.183594 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 552.542969 102 L 557.929688 102 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 402.945312 102 L 480.792969 102 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 247.347656 102 L 322.886719 102 "/>
|
||||
<path style="fill:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 46.933594 102 L 176.828125 102 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,100%);stroke-opacity:0.99792;stroke-miterlimit:10;" d="M 557.929688 102 L 570.410156 41.183594 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,100%);fill-opacity:0.99792;" d="M 570.410156 31.183594 L 574.410156 41.183594 L 566.410156 41.183594 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="209.296875" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-5" x="216.398438" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-19" x="220.212891" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-5" x="230.267578" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-15" x="234.082031" y="28.183594"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 225.507812 28.183594 L 225.507812 34.183594 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="351.765625" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-5" x="358.867188" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-19" x="362.681641" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-5" x="372.736328" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-20" x="376.550781" y="28.183594"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 367.976562 28.183594 L 367.976562 34.183594 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="509.097656" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-5" x="516.199219" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-19" x="520.013672" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-5" x="530.068359" y="28.183594"/>
|
||||
<use xlink:href="#glyph0-21" x="533.882812" y="28.183594"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 525.308594 28.183594 L 525.308594 34.183594 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="101.585938" y="99"/>
|
||||
<use xlink:href="#glyph0-5" x="108.6875" y="99"/>
|
||||
<use xlink:href="#glyph0-19" x="112.501953" y="99"/>
|
||||
<use xlink:href="#glyph0-5" x="122.556641" y="99"/>
|
||||
<use xlink:href="#glyph0-15" x="126.371094" y="99"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 117.792969 99 L 117.792969 105 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="274.625" y="99"/>
|
||||
<use xlink:href="#glyph0-5" x="281.726562" y="99"/>
|
||||
<use xlink:href="#glyph0-19" x="285.541016" y="99"/>
|
||||
<use xlink:href="#glyph0-5" x="295.595703" y="99"/>
|
||||
<use xlink:href="#glyph0-20" x="299.410156" y="99"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 290.835938 99 L 290.835938 105 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="433.574219" y="99"/>
|
||||
<use xlink:href="#glyph0-5" x="440.675781" y="99"/>
|
||||
<use xlink:href="#glyph0-19" x="444.490234" y="99"/>
|
||||
<use xlink:href="#glyph0-5" x="454.544922" y="99"/>
|
||||
<use xlink:href="#glyph0-21" x="458.359375" y="99"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:bevel;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 449.78125 99 L 449.78125 105 "/>
|
||||
<g style="fill:rgb(50%,50%,50%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-23" x="4.59375" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-7" x="12.210938" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-24" x="17.144531" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-24" x="24.527344" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-22" x="31.910156" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-8" x="39.011719" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-11" x="42.345703" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-25" x="48.597656" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-8" x="53.302734" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-13" x="56.636719" y="41.183594"/>
|
||||
<use xlink:href="#glyph0-6" x="64.242188" y="41.183594"/>
|
||||
</g>
|
||||
<g style="fill:rgb(50%,50%,50%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-25" x="40.8125" y="112"/>
|
||||
<use xlink:href="#glyph0-2" x="45.517578" y="112"/>
|
||||
<use xlink:href="#glyph0-11" x="52.871094" y="112"/>
|
||||
<use xlink:href="#glyph0-26" x="59.123047" y="112"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 31 KiB |
4
doc/traces/Makefile
Normal file
4
doc/traces/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
all: both-posix.svg cancel-posix.svg switch-mock.svg net-posix.svg multicore-posix.svg
|
||||
|
||||
%.svg: %.fxt
|
||||
eio-trace render "$<"
|
BIN
doc/traces/both-posix.fxt
Normal file
BIN
doc/traces/both-posix.fxt
Normal file
Binary file not shown.
351
doc/traces/both-posix.svg
Normal file
351
doc/traces/both-posix.svg
Normal file
@ -0,0 +1,351 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1280pt" height="120pt" viewBox="0 0 1280 120" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d="M 0.59375 2.125 L 0.59375 -8.46875 L 6.59375 -8.46875 L 6.59375 2.125 Z M 1.265625 1.453125 L 5.9375 1.453125 L 5.9375 -7.78125 L 1.265625 -7.78125 Z M 1.265625 1.453125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 1.171875 -8.75 L 6.703125 -8.75 L 6.703125 -7.75 L 2.359375 -7.75 L 2.359375 -5.15625 L 6.53125 -5.15625 L 6.53125 -4.171875 L 2.359375 -4.171875 L 2.359375 -1 L 6.8125 -1 L 6.8125 0 L 1.171875 0 Z M 1.171875 -8.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 4.109375 -3.296875 C 3.242188 -3.296875 2.640625 -3.195312 2.296875 -3 C 1.960938 -2.800781 1.796875 -2.460938 1.796875 -1.984375 C 1.796875 -1.597656 1.921875 -1.289062 2.171875 -1.0625 C 2.429688 -0.84375 2.773438 -0.734375 3.203125 -0.734375 C 3.804688 -0.734375 4.285156 -0.941406 4.640625 -1.359375 C 5.003906 -1.785156 5.1875 -2.351562 5.1875 -3.0625 L 5.1875 -3.296875 Z M 6.265625 -3.75 L 6.265625 0 L 5.1875 0 L 5.1875 -1 C 4.9375 -0.601562 4.628906 -0.304688 4.265625 -0.109375 C 3.898438 0.078125 3.453125 0.171875 2.921875 0.171875 C 2.242188 0.171875 1.707031 -0.015625 1.3125 -0.390625 C 0.914062 -0.773438 0.71875 -1.28125 0.71875 -1.90625 C 0.71875 -2.644531 0.960938 -3.203125 1.453125 -3.578125 C 1.953125 -3.953125 2.691406 -4.140625 3.671875 -4.140625 L 5.1875 -4.140625 L 5.1875 -4.25 C 5.1875 -4.75 5.019531 -5.132812 4.6875 -5.40625 C 4.363281 -5.675781 3.910156 -5.8125 3.328125 -5.8125 C 2.953125 -5.8125 2.582031 -5.765625 2.21875 -5.671875 C 1.863281 -5.578125 1.523438 -5.441406 1.203125 -5.265625 L 1.203125 -6.265625 C 1.597656 -6.421875 1.976562 -6.535156 2.34375 -6.609375 C 2.71875 -6.679688 3.082031 -6.71875 3.4375 -6.71875 C 4.382812 -6.71875 5.09375 -6.472656 5.5625 -5.984375 C 6.03125 -5.492188 6.265625 -4.75 6.265625 -3.75 Z M 6.265625 -3.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 5.859375 -6.3125 L 5.859375 -5.296875 C 5.546875 -5.472656 5.238281 -5.601562 4.9375 -5.6875 C 4.632812 -5.769531 4.328125 -5.8125 4.015625 -5.8125 C 3.304688 -5.8125 2.757812 -5.585938 2.375 -5.140625 C 1.988281 -4.703125 1.796875 -4.082031 1.796875 -3.28125 C 1.796875 -2.476562 1.988281 -1.851562 2.375 -1.40625 C 2.757812 -0.96875 3.304688 -0.75 4.015625 -0.75 C 4.328125 -0.75 4.632812 -0.789062 4.9375 -0.875 C 5.238281 -0.957031 5.546875 -1.082031 5.859375 -1.25 L 5.859375 -0.25 C 5.554688 -0.113281 5.242188 -0.0078125 4.921875 0.0625 C 4.597656 0.132812 4.253906 0.171875 3.890625 0.171875 C 2.898438 0.171875 2.113281 -0.132812 1.53125 -0.75 C 0.945312 -1.375 0.65625 -2.21875 0.65625 -3.28125 C 0.65625 -4.34375 0.945312 -5.179688 1.53125 -5.796875 C 2.125 -6.410156 2.9375 -6.71875 3.96875 -6.71875 C 4.289062 -6.71875 4.609375 -6.679688 4.921875 -6.609375 C 5.242188 -6.546875 5.554688 -6.445312 5.859375 -6.3125 Z M 5.859375 -6.3125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -9.125 L 2.171875 -9.125 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 5.453125 -3.359375 C 5.453125 -4.140625 5.289062 -4.742188 4.96875 -5.171875 C 4.644531 -5.597656 4.191406 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.597656 2.265625 -5.171875 C 1.941406 -4.742188 1.78125 -4.140625 1.78125 -3.359375 C 1.78125 -2.578125 1.941406 -1.972656 2.265625 -1.546875 C 2.585938 -1.117188 3.035156 -0.90625 3.609375 -0.90625 C 4.191406 -0.90625 4.644531 -1.117188 4.96875 -1.546875 C 5.289062 -1.972656 5.453125 -2.578125 5.453125 -3.359375 Z M 6.53125 -0.8125 C 6.53125 0.300781 6.28125 1.128906 5.78125 1.671875 C 5.289062 2.222656 4.53125 2.5 3.5 2.5 C 3.125 2.5 2.765625 2.46875 2.421875 2.40625 C 2.085938 2.351562 1.765625 2.269531 1.453125 2.15625 L 1.453125 1.109375 C 1.765625 1.273438 2.078125 1.398438 2.390625 1.484375 C 2.703125 1.566406 3.015625 1.609375 3.328125 1.609375 C 4.035156 1.609375 4.566406 1.421875 4.921875 1.046875 C 5.273438 0.679688 5.453125 0.125 5.453125 -0.625 L 5.453125 -1.15625 C 5.222656 -0.769531 4.9375 -0.476562 4.59375 -0.28125 C 4.25 -0.09375 3.832031 0 3.34375 0 C 2.539062 0 1.890625 -0.304688 1.390625 -0.921875 C 0.898438 -1.535156 0.65625 -2.347656 0.65625 -3.359375 C 0.65625 -4.367188 0.898438 -5.179688 1.390625 -5.796875 C 1.890625 -6.410156 2.539062 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.617188 4.59375 -6.421875 C 4.9375 -6.234375 5.222656 -5.945312 5.453125 -5.5625 L 5.453125 -6.5625 L 6.53125 -6.5625 Z M 6.53125 -0.8125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-7">
|
||||
<path style="stroke:none;" d="M 4.9375 -5.5625 C 4.8125 -5.625 4.675781 -5.671875 4.53125 -5.703125 C 4.394531 -5.742188 4.238281 -5.765625 4.0625 -5.765625 C 3.457031 -5.765625 2.988281 -5.566406 2.65625 -5.171875 C 2.332031 -4.773438 2.171875 -4.203125 2.171875 -3.453125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.398438 -5.941406 2.695312 -6.234375 3.0625 -6.421875 C 3.425781 -6.617188 3.867188 -6.71875 4.390625 -6.71875 C 4.460938 -6.71875 4.539062 -6.710938 4.625 -6.703125 C 4.71875 -6.691406 4.816406 -6.675781 4.921875 -6.65625 Z M 4.9375 -5.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-8">
|
||||
<path style="stroke:none;" d="M 1.125 -6.5625 L 2.203125 -6.5625 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 -7.75 L 1.125 -7.75 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-9">
|
||||
<path style="stroke:none;" d="M 5.453125 -5.5625 L 5.453125 -9.125 L 6.53125 -9.125 L 6.53125 0 L 5.453125 0 L 5.453125 -0.984375 C 5.222656 -0.597656 4.9375 -0.304688 4.59375 -0.109375 C 4.25 0.078125 3.832031 0.171875 3.34375 0.171875 C 2.550781 0.171875 1.90625 -0.144531 1.40625 -0.78125 C 0.90625 -1.414062 0.65625 -2.25 0.65625 -3.28125 C 0.65625 -4.3125 0.90625 -5.140625 1.40625 -5.765625 C 1.90625 -6.398438 2.550781 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.625 4.59375 -6.4375 C 4.9375 -6.25 5.222656 -5.957031 5.453125 -5.5625 Z M 1.78125 -3.28125 C 1.78125 -2.488281 1.941406 -1.863281 2.265625 -1.40625 C 2.585938 -0.957031 3.035156 -0.734375 3.609375 -0.734375 C 4.179688 -0.734375 4.628906 -0.957031 4.953125 -1.40625 C 5.285156 -1.863281 5.453125 -2.488281 5.453125 -3.28125 C 5.453125 -4.070312 5.285156 -4.691406 4.953125 -5.140625 C 4.628906 -5.585938 4.179688 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.585938 2.265625 -5.140625 C 1.941406 -4.691406 1.78125 -4.070312 1.78125 -3.28125 Z M 1.78125 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-10">
|
||||
<path style="stroke:none;" d="M 0.359375 -6.5625 L 1.5 -6.5625 L 3.546875 -1.0625 L 5.609375 -6.5625 L 6.75 -6.5625 L 4.28125 0 L 2.8125 0 Z M 0.359375 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-11">
|
||||
<path style="stroke:none;" d="M 5.3125 -6.375 L 5.3125 -5.34375 C 5.007812 -5.5 4.691406 -5.613281 4.359375 -5.6875 C 4.035156 -5.769531 3.695312 -5.8125 3.34375 -5.8125 C 2.8125 -5.8125 2.410156 -5.726562 2.140625 -5.5625 C 1.867188 -5.40625 1.734375 -5.160156 1.734375 -4.828125 C 1.734375 -4.578125 1.828125 -4.378906 2.015625 -4.234375 C 2.210938 -4.097656 2.601562 -3.96875 3.1875 -3.84375 L 3.546875 -3.75 C 4.316406 -3.59375 4.863281 -3.363281 5.1875 -3.0625 C 5.507812 -2.757812 5.671875 -2.34375 5.671875 -1.8125 C 5.671875 -1.195312 5.425781 -0.710938 4.9375 -0.359375 C 4.457031 -0.00390625 3.796875 0.171875 2.953125 0.171875 C 2.597656 0.171875 2.226562 0.132812 1.84375 0.0625 C 1.46875 0 1.070312 -0.0976562 0.65625 -0.234375 L 0.65625 -1.359375 C 1.050781 -1.148438 1.441406 -0.992188 1.828125 -0.890625 C 2.210938 -0.785156 2.597656 -0.734375 2.984375 -0.734375 C 3.484375 -0.734375 3.867188 -0.816406 4.140625 -0.984375 C 4.421875 -1.160156 4.5625 -1.410156 4.5625 -1.734375 C 4.5625 -2.023438 4.460938 -2.25 4.265625 -2.40625 C 4.066406 -2.5625 3.632812 -2.710938 2.96875 -2.859375 L 2.59375 -2.9375 C 1.925781 -3.082031 1.441406 -3.300781 1.140625 -3.59375 C 0.847656 -3.882812 0.703125 -4.28125 0.703125 -4.78125 C 0.703125 -5.40625 0.921875 -5.882812 1.359375 -6.21875 C 1.796875 -6.550781 2.414062 -6.71875 3.21875 -6.71875 C 3.613281 -6.71875 3.988281 -6.6875 4.34375 -6.625 C 4.695312 -6.570312 5.019531 -6.488281 5.3125 -6.375 Z M 5.3125 -6.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-12">
|
||||
<path style="stroke:none;" d="M 3.671875 -5.8125 C 3.097656 -5.8125 2.640625 -5.582031 2.296875 -5.125 C 1.960938 -4.675781 1.796875 -4.0625 1.796875 -3.28125 C 1.796875 -2.488281 1.960938 -1.867188 2.296875 -1.421875 C 2.628906 -0.972656 3.085938 -0.75 3.671875 -0.75 C 4.242188 -0.75 4.695312 -0.972656 5.03125 -1.421875 C 5.375 -1.878906 5.546875 -2.5 5.546875 -3.28125 C 5.546875 -4.050781 5.375 -4.664062 5.03125 -5.125 C 4.695312 -5.582031 4.242188 -5.8125 3.671875 -5.8125 Z M 3.671875 -6.71875 C 4.609375 -6.71875 5.34375 -6.410156 5.875 -5.796875 C 6.414062 -5.191406 6.6875 -4.351562 6.6875 -3.28125 C 6.6875 -2.207031 6.414062 -1.363281 5.875 -0.75 C 5.34375 -0.132812 4.609375 0.171875 3.671875 0.171875 C 2.734375 0.171875 1.992188 -0.132812 1.453125 -0.75 C 0.921875 -1.363281 0.65625 -2.207031 0.65625 -3.28125 C 0.65625 -4.351562 0.921875 -5.191406 1.453125 -5.796875 C 1.992188 -6.410156 2.734375 -6.71875 3.671875 -6.71875 Z M 3.671875 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-13">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-14">
|
||||
<path style="stroke:none;" d="M 1.40625 -1.484375 L 2.640625 -1.484375 L 2.640625 0 L 1.40625 0 Z M 1.40625 -6.203125 L 2.640625 -6.203125 L 2.640625 -4.71875 L 1.40625 -4.71875 Z M 1.40625 -6.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-15">
|
||||
<path style="stroke:none;" d="M 1.484375 -1 L 3.421875 -1 L 3.421875 -7.671875 L 1.3125 -7.25 L 1.3125 -8.328125 L 3.40625 -8.75 L 4.59375 -8.75 L 4.59375 -1 L 6.53125 -1 L 6.53125 0 L 1.484375 0 Z M 1.484375 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-16">
|
||||
<path style="stroke:none;" d="M 3.8125 -7.96875 C 3.207031 -7.96875 2.75 -7.664062 2.4375 -7.0625 C 2.132812 -6.46875 1.984375 -5.566406 1.984375 -4.359375 C 1.984375 -3.160156 2.132812 -2.257812 2.4375 -1.65625 C 2.75 -1.0625 3.207031 -0.765625 3.8125 -0.765625 C 4.425781 -0.765625 4.882812 -1.0625 5.1875 -1.65625 C 5.5 -2.257812 5.65625 -3.160156 5.65625 -4.359375 C 5.65625 -5.566406 5.5 -6.46875 5.1875 -7.0625 C 4.882812 -7.664062 4.425781 -7.96875 3.8125 -7.96875 Z M 3.8125 -8.90625 C 4.789062 -8.90625 5.539062 -8.515625 6.0625 -7.734375 C 6.582031 -6.960938 6.84375 -5.835938 6.84375 -4.359375 C 6.84375 -2.890625 6.582031 -1.765625 6.0625 -0.984375 C 5.539062 -0.210938 4.789062 0.171875 3.8125 0.171875 C 2.832031 0.171875 2.082031 -0.210938 1.5625 -0.984375 C 1.050781 -1.765625 0.796875 -2.890625 0.796875 -4.359375 C 0.796875 -5.835938 1.050781 -6.960938 1.5625 -7.734375 C 2.082031 -8.515625 2.832031 -8.90625 3.8125 -8.90625 Z M 3.8125 -8.90625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-17">
|
||||
<path style="stroke:none;" d="M 1.015625 -2.59375 L 1.015625 -6.5625 L 2.09375 -6.5625 L 2.09375 -2.625 C 2.09375 -2.007812 2.210938 -1.546875 2.453125 -1.234375 C 2.703125 -0.921875 3.066406 -0.765625 3.546875 -0.765625 C 4.128906 -0.765625 4.585938 -0.945312 4.921875 -1.3125 C 5.265625 -1.6875 5.4375 -2.195312 5.4375 -2.84375 L 5.4375 -6.5625 L 6.515625 -6.5625 L 6.515625 0 L 5.4375 0 L 5.4375 -1.015625 C 5.175781 -0.609375 4.875 -0.304688 4.53125 -0.109375 C 4.1875 0.078125 3.785156 0.171875 3.328125 0.171875 C 2.566406 0.171875 1.988281 -0.0625 1.59375 -0.53125 C 1.207031 -1 1.015625 -1.6875 1.015625 -2.59375 Z M 3.734375 -6.71875 Z M 3.734375 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-18">
|
||||
<path style="stroke:none;" d="M 2.203125 -8.421875 L 2.203125 -6.5625 L 4.421875 -6.5625 L 4.421875 -5.71875 L 2.203125 -5.71875 L 2.203125 -2.15625 C 2.203125 -1.625 2.273438 -1.28125 2.421875 -1.125 C 2.566406 -0.976562 2.863281 -0.90625 3.3125 -0.90625 L 4.421875 -0.90625 L 4.421875 0 L 3.3125 0 C 2.476562 0 1.898438 -0.15625 1.578125 -0.46875 C 1.265625 -0.78125 1.109375 -1.34375 1.109375 -2.15625 L 1.109375 -5.71875 L 0.328125 -5.71875 L 0.328125 -6.5625 L 1.109375 -6.5625 L 1.109375 -8.421875 Z M 2.203125 -8.421875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-19">
|
||||
<path style="stroke:none;" d="M 6.75 -3.546875 L 6.75 -3.03125 L 1.78125 -3.03125 C 1.832031 -2.28125 2.054688 -1.710938 2.453125 -1.328125 C 2.859375 -0.941406 3.414062 -0.75 4.125 -0.75 C 4.539062 -0.75 4.941406 -0.796875 5.328125 -0.890625 C 5.722656 -0.992188 6.113281 -1.148438 6.5 -1.359375 L 6.5 -0.328125 C 6.101562 -0.171875 5.703125 -0.0507812 5.296875 0.03125 C 4.890625 0.125 4.476562 0.171875 4.0625 0.171875 C 3.019531 0.171875 2.191406 -0.128906 1.578125 -0.734375 C 0.960938 -1.347656 0.65625 -2.175781 0.65625 -3.21875 C 0.65625 -4.289062 0.945312 -5.140625 1.53125 -5.765625 C 2.113281 -6.398438 2.894531 -6.71875 3.875 -6.71875 C 4.757812 -6.71875 5.457031 -6.429688 5.96875 -5.859375 C 6.488281 -5.296875 6.75 -4.523438 6.75 -3.546875 Z M 5.671875 -3.875 C 5.660156 -4.457031 5.492188 -4.925781 5.171875 -5.28125 C 4.847656 -5.632812 4.421875 -5.8125 3.890625 -5.8125 C 3.285156 -5.8125 2.800781 -5.640625 2.4375 -5.296875 C 2.082031 -4.953125 1.878906 -4.472656 1.828125 -3.859375 Z M 5.671875 -3.875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-20">
|
||||
<path style="stroke:none;" d="M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-0">
|
||||
<path style="stroke:none;" d="M 0.40625 1.421875 L 0.40625 -5.640625 L 4.40625 -5.640625 L 4.40625 1.421875 Z M 0.84375 0.96875 L 3.953125 0.96875 L 3.953125 -5.1875 L 0.84375 -5.1875 Z M 0.84375 0.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-1">
|
||||
<path style="stroke:none;" d="M 4.390625 -4.375 L 2.8125 -2.25 L 4.46875 0 L 3.625 0 L 2.359375 -1.71875 L 1.078125 0 L 0.234375 0 L 1.9375 -2.296875 L 0.375 -4.375 L 1.21875 -4.375 L 2.390625 -2.8125 L 3.546875 -4.375 Z M 4.390625 -4.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-2">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-3">
|
||||
<path style="stroke:none;" d="M 0.84375 -3.640625 L 5.859375 -3.640625 L 5.859375 -2.984375 L 0.84375 -2.984375 Z M 0.84375 -2.046875 L 5.859375 -2.046875 L 5.859375 -1.375 L 0.84375 -1.375 Z M 0.84375 -2.046875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-4">
|
||||
<path style="stroke:none;" d="M 1 -0.671875 L 2.28125 -0.671875 L 2.28125 -5.109375 L 0.875 -4.828125 L 0.875 -5.546875 L 2.28125 -5.828125 L 3.0625 -5.828125 L 3.0625 -0.671875 L 4.359375 -0.671875 L 4.359375 0 L 1 0 Z M 1 -0.671875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-5">
|
||||
<path style="stroke:none;" d="M 1.53125 -0.671875 L 4.296875 -0.671875 L 4.296875 0 L 0.59375 0 L 0.59375 -0.671875 C 0.882812 -0.972656 1.289062 -1.382812 1.8125 -1.90625 C 2.332031 -2.4375 2.65625 -2.773438 2.78125 -2.921875 C 3.039062 -3.203125 3.21875 -3.441406 3.3125 -3.640625 C 3.414062 -3.835938 3.46875 -4.03125 3.46875 -4.21875 C 3.46875 -4.53125 3.359375 -4.785156 3.140625 -4.984375 C 2.921875 -5.179688 2.640625 -5.28125 2.296875 -5.28125 C 2.046875 -5.28125 1.78125 -5.234375 1.5 -5.140625 C 1.226562 -5.054688 0.9375 -4.925781 0.625 -4.75 L 0.625 -5.546875 C 0.945312 -5.679688 1.242188 -5.78125 1.515625 -5.84375 C 1.796875 -5.90625 2.050781 -5.9375 2.28125 -5.9375 C 2.882812 -5.9375 3.363281 -5.785156 3.71875 -5.484375 C 4.082031 -5.179688 4.265625 -4.78125 4.265625 -4.28125 C 4.265625 -4.039062 4.21875 -3.8125 4.125 -3.59375 C 4.03125 -3.375 3.867188 -3.117188 3.640625 -2.828125 C 3.566406 -2.753906 3.351562 -2.535156 3 -2.171875 C 2.65625 -1.816406 2.164062 -1.316406 1.53125 -0.671875 Z M 1.53125 -0.671875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-6">
|
||||
<path style="stroke:none;" d="M 3.25 -3.140625 C 3.625 -3.066406 3.914062 -2.898438 4.125 -2.640625 C 4.34375 -2.390625 4.453125 -2.078125 4.453125 -1.703125 C 4.453125 -1.117188 4.253906 -0.671875 3.859375 -0.359375 C 3.460938 -0.046875 2.898438 0.109375 2.171875 0.109375 C 1.921875 0.109375 1.664062 0.0820312 1.40625 0.03125 C 1.15625 -0.0078125 0.890625 -0.078125 0.609375 -0.171875 L 0.609375 -0.9375 C 0.828125 -0.8125 1.066406 -0.710938 1.328125 -0.640625 C 1.585938 -0.578125 1.859375 -0.546875 2.140625 -0.546875 C 2.640625 -0.546875 3.019531 -0.644531 3.28125 -0.84375 C 3.539062 -1.039062 3.671875 -1.328125 3.671875 -1.703125 C 3.671875 -2.046875 3.546875 -2.3125 3.296875 -2.5 C 3.054688 -2.695312 2.722656 -2.796875 2.296875 -2.796875 L 1.625 -2.796875 L 1.625 -3.4375 L 2.328125 -3.4375 C 2.710938 -3.4375 3.007812 -3.515625 3.21875 -3.671875 C 3.425781 -3.828125 3.53125 -4.050781 3.53125 -4.34375 C 3.53125 -4.644531 3.421875 -4.875 3.203125 -5.03125 C 2.992188 -5.195312 2.691406 -5.28125 2.296875 -5.28125 C 2.078125 -5.28125 1.84375 -5.253906 1.59375 -5.203125 C 1.351562 -5.160156 1.082031 -5.085938 0.78125 -4.984375 L 0.78125 -5.6875 C 1.082031 -5.769531 1.363281 -5.832031 1.625 -5.875 C 1.882812 -5.914062 2.132812 -5.9375 2.375 -5.9375 C 2.96875 -5.9375 3.4375 -5.800781 3.78125 -5.53125 C 4.132812 -5.257812 4.3125 -4.890625 4.3125 -4.421875 C 4.3125 -4.097656 4.21875 -3.828125 4.03125 -3.609375 C 3.851562 -3.390625 3.59375 -3.234375 3.25 -3.140625 Z M 3.25 -3.140625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-7">
|
||||
<path style="stroke:none;" d="M 2.578125 0.40625 C 2.367188 0.925781 2.164062 1.265625 1.96875 1.421875 C 1.78125 1.585938 1.523438 1.671875 1.203125 1.671875 L 0.640625 1.671875 L 0.640625 1.0625 L 1.0625 1.0625 C 1.257812 1.0625 1.410156 1.015625 1.515625 0.921875 C 1.628906 0.828125 1.75 0.609375 1.875 0.265625 L 2.015625 -0.078125 L 0.234375 -4.375 L 1 -4.375 L 2.375 -0.953125 L 3.734375 -4.375 L 4.5 -4.375 Z M 2.578125 0.40625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-8">
|
||||
<path style="stroke:none;" d="M 3.890625 -2.1875 C 3.890625 -2.71875 3.78125 -3.128906 3.5625 -3.421875 C 3.351562 -3.722656 3.054688 -3.875 2.671875 -3.875 C 2.296875 -3.875 2 -3.722656 1.78125 -3.421875 C 1.5625 -3.128906 1.453125 -2.71875 1.453125 -2.1875 C 1.453125 -1.65625 1.5625 -1.238281 1.78125 -0.9375 C 2 -0.632812 2.296875 -0.484375 2.671875 -0.484375 C 3.054688 -0.484375 3.351562 -0.632812 3.5625 -0.9375 C 3.78125 -1.238281 3.890625 -1.65625 3.890625 -2.1875 Z M 1.453125 -3.71875 C 1.597656 -3.976562 1.785156 -4.171875 2.015625 -4.296875 C 2.253906 -4.421875 2.53125 -4.484375 2.84375 -4.484375 C 3.375 -4.484375 3.804688 -4.269531 4.140625 -3.84375 C 4.472656 -3.425781 4.640625 -2.875 4.640625 -2.1875 C 4.640625 -1.5 4.472656 -0.941406 4.140625 -0.515625 C 3.804688 -0.0976562 3.375 0.109375 2.84375 0.109375 C 2.53125 0.109375 2.253906 0.046875 2.015625 -0.078125 C 1.785156 -0.203125 1.597656 -0.394531 1.453125 -0.65625 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 Z M 1.453125 -3.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-9">
|
||||
<path style="stroke:none;" d="M 2.453125 -3.875 C 2.066406 -3.875 1.757812 -3.722656 1.53125 -3.421875 C 1.3125 -3.117188 1.203125 -2.707031 1.203125 -2.1875 C 1.203125 -1.664062 1.3125 -1.253906 1.53125 -0.953125 C 1.757812 -0.648438 2.066406 -0.5 2.453125 -0.5 C 2.835938 -0.5 3.140625 -0.648438 3.359375 -0.953125 C 3.585938 -1.253906 3.703125 -1.664062 3.703125 -2.1875 C 3.703125 -2.707031 3.585938 -3.117188 3.359375 -3.421875 C 3.140625 -3.722656 2.835938 -3.875 2.453125 -3.875 Z M 2.453125 -4.484375 C 3.078125 -4.484375 3.566406 -4.28125 3.921875 -3.875 C 4.273438 -3.46875 4.453125 -2.90625 4.453125 -2.1875 C 4.453125 -1.46875 4.273438 -0.90625 3.921875 -0.5 C 3.566406 -0.09375 3.078125 0.109375 2.453125 0.109375 C 1.828125 0.109375 1.332031 -0.09375 0.96875 -0.5 C 0.613281 -0.90625 0.4375 -1.46875 0.4375 -2.1875 C 0.4375 -2.90625 0.613281 -3.46875 0.96875 -3.875 C 1.332031 -4.28125 1.828125 -4.484375 2.453125 -4.484375 Z M 2.453125 -4.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-10">
|
||||
<path style="stroke:none;" d="M 1.46875 -5.625 L 1.46875 -4.375 L 2.953125 -4.375 L 2.953125 -3.8125 L 1.46875 -3.8125 L 1.46875 -1.4375 C 1.46875 -1.082031 1.515625 -0.851562 1.609375 -0.75 C 1.710938 -0.65625 1.910156 -0.609375 2.203125 -0.609375 L 2.953125 -0.609375 L 2.953125 0 L 2.203125 0 C 1.648438 0 1.269531 -0.101562 1.0625 -0.3125 C 0.851562 -0.519531 0.75 -0.894531 0.75 -1.4375 L 0.75 -3.8125 L 0.21875 -3.8125 L 0.21875 -4.375 L 0.75 -4.375 L 0.75 -5.625 Z M 1.46875 -5.625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-11">
|
||||
<path style="stroke:none;" d="M 4.390625 -2.640625 L 4.390625 0 L 3.671875 0 L 3.671875 -2.625 C 3.671875 -3.03125 3.585938 -3.335938 3.421875 -3.546875 C 3.265625 -3.753906 3.023438 -3.859375 2.703125 -3.859375 C 2.316406 -3.859375 2.007812 -3.734375 1.78125 -3.484375 C 1.5625 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.285156 -4.414062 2.554688 -4.484375 2.859375 -4.484375 C 3.367188 -4.484375 3.75 -4.328125 4 -4.015625 C 4.257812 -3.703125 4.390625 -3.242188 4.390625 -2.640625 Z M 4.390625 -2.640625 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 692.644531 48 L 734 48 L 734 59 L 692.644531 59 Z M 692.644531 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip2">
|
||||
<path d="M 885.316406 48 L 927 48 L 927 59 L 885.316406 59 Z M 885.316406 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip3">
|
||||
<path d="M 1038.214844 48 L 1060.753906 48 L 1060.753906 59 L 1038.214844 59 Z M 1038.214844 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip4">
|
||||
<path d="M 819.328125 80 L 861 80 L 861 91 L 819.328125 91 Z M 819.328125 80 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip5">
|
||||
<path d="M 967 80 L 1006.179688 80 L 1006.179688 91 L 967 91 Z M 967 80 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip6">
|
||||
<path d="M 433.214844 70 L 455 70 L 455 76 L 433.214844 76 Z M 433.214844 70 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip7">
|
||||
<path d="M 854.011719 70 L 875 70 L 875 76 L 854.011719 76 Z M 854.011719 70 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip8">
|
||||
<path d="M 993.652344 70 L 1015 70 L 1015 77 L 993.652344 77 Z M 993.652344 70 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip9">
|
||||
<path d="M 738.246094 38 L 760 38 L 760 46 L 738.246094 46 Z M 738.246094 38 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip10">
|
||||
<path d="M 937.078125 38 L 958 38 L 958 46 L 937.078125 46 Z M 937.078125 38 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip11">
|
||||
<path d="M 1047.515625 38 L 1069 38 L 1069 46 L 1047.515625 46 Z M 1047.515625 38 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface2">
|
||||
<rect x="0" y="0" width="1280" height="120" style="fill:rgb(90%,90%,90%);fill-opacity:1;stroke:none;"/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 4 0 L 4 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 169.472656 0 L 169.472656 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 334.945312 0 L 334.945312 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 500.417969 0 L 500.417969 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 665.886719 0 L 665.886719 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 831.359375 0 L 831.359375 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 996.832031 0 L 996.832031 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1162.304688 0 L 1162.304688 120 "/>
|
||||
<g style="fill:rgb(40%,40%,40%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="4" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-2" x="11.582031" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-3" x="18.935547" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-4" x="25.533203" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="33.138672" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-6" x="36.953125" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-7" x="44.570312" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="49.503906" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="52.837891" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="60.455078" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="64.269531" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="71.886719" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-10" x="75.220703" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="82.322266" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="85.65625" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="91.908203" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-12" x="95.242188" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-13" x="102.583984" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-14" x="110.189453" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="114.232422" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-15" x="118.046875" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-16" x="125.681641" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="133.316406" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-17" x="137.130859" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="144.736328" y="115.503906"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 10.984375 46 L 19.375 46 L 19.375 60 L 10.984375 60 Z M 10.984375 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 19.371094 46 L 117.976562 46 L 117.976562 60 L 19.371094 60 Z M 19.371094 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 117.976562 46 L 657.960938 46 L 657.960938 60 L 117.976562 60 Z M 117.976562 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 657.960938 46 L 690.640625 46 L 690.640625 60 L 657.960938 60 Z M 657.960938 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 690.644531 46 L 762.277344 46 L 762.277344 60 L 690.644531 60 Z M 690.644531 46 "/>
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="692.644531" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="697.349609" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="702.283203" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="709.636719" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="716.234375" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="723.617188" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="726.951172" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 762.277344 46 L 765.703125 46 L 765.703125 60 L 762.277344 60 Z M 762.277344 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 765.699219 46 L 874.28125 46 L 874.28125 60 L 765.699219 60 Z M 765.699219 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 874.285156 46 L 883.320312 46 L 883.320312 60 L 874.285156 60 Z M 874.285156 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 883.316406 46 L 950.152344 46 L 950.152344 60 L 883.316406 60 Z M 883.316406 46 "/>
|
||||
<g clip-path="url(#clip2)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="885.316406" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="890.021484" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="894.955078" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="902.308594" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="908.90625" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="916.289062" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="919.623047" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 950.152344 46 L 952.253906 46 L 952.253906 60 L 950.152344 60 Z M 950.152344 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 952.253906 46 L 1010.515625 46 L 1010.515625 60 L 952.253906 60 Z M 952.253906 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1010.515625 46 L 1036.214844 46 L 1036.214844 60 L 1010.515625 60 Z M 1010.515625 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1036.214844 46 L 1060.753906 46 L 1060.753906 60 L 1036.214844 60 Z M 1036.214844 46 "/>
|
||||
<g clip-path="url(#clip3)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="1038.214844" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="1042.919922" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1047.853516" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="1055.207031" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1061.804688" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="1069.1875" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="1072.521484" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1060.753906 46 L 1062.9375 46 L 1062.9375 60 L 1060.753906 60 Z M 1060.753906 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1062.9375 46 L 1096.113281 46 L 1096.113281 60 L 1062.9375 60 Z M 1062.9375 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1096.117188 46 L 1185.753906 46 L 1185.753906 60 L 1096.117188 60 Z M 1096.117188 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1185.75 46 L 1231.652344 46 L 1231.652344 60 L 1185.75 60 Z M 1185.75 46 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="1187.75" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="1194.347656" y="58"/>
|
||||
<use xlink:href="#glyph0-12" x="1197.681641" y="58"/>
|
||||
<use xlink:href="#glyph0-11" x="1205.023438" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1211.275391" y="58"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1231.652344 46 L 1108.410156 46 L 1108.410156 60 L 1231.652344 60 Z M 1231.652344 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 117.976562 78 L 125.953125 78 L 125.953125 92 L 117.976562 92 Z M 117.976562 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 125.953125 78 L 273.785156 78 L 273.785156 92 L 125.953125 92 Z M 125.953125 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 273.785156 78 L 630.226562 78 L 630.226562 92 L 273.785156 92 Z M 273.785156 78 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="275.785156" y="90"/>
|
||||
<use xlink:href="#glyph0-7" x="280.490234" y="90"/>
|
||||
<use xlink:href="#glyph0-2" x="285.423828" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="292.777344" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="299.375" y="90"/>
|
||||
<use xlink:href="#glyph0-20" x="306.757812" y="90"/>
|
||||
<use xlink:href="#glyph0-13" x="310.091797" y="90"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 630.230469 78 L 643.714844 78 L 643.714844 92 L 630.230469 92 Z M 630.230469 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 643.714844 78 L 803.261719 78 L 803.261719 92 L 643.714844 92 Z M 643.714844 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 803.261719 78 L 817.328125 78 L 817.328125 92 L 803.261719 92 Z M 803.261719 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 817.328125 78 L 869.75 78 L 869.75 92 L 817.328125 92 Z M 817.328125 78 "/>
|
||||
<g clip-path="url(#clip4)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="819.328125" y="90"/>
|
||||
<use xlink:href="#glyph0-7" x="824.033203" y="90"/>
|
||||
<use xlink:href="#glyph0-2" x="828.966797" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="836.320312" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="842.917969" y="90"/>
|
||||
<use xlink:href="#glyph0-20" x="850.300781" y="90"/>
|
||||
<use xlink:href="#glyph0-13" x="853.634766" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 869.75 78 L 871.902344 78 L 871.902344 92 L 869.75 92 Z M 869.75 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 871.902344 78 L 956.558594 78 L 956.558594 92 L 871.902344 92 Z M 871.902344 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 956.554688 78 L 964.960938 78 L 964.960938 92 L 956.554688 92 Z M 956.554688 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 964.960938 78 L 1006.179688 78 L 1006.179688 92 L 964.960938 92 Z M 964.960938 78 "/>
|
||||
<g clip-path="url(#clip5)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="966.960938" y="90"/>
|
||||
<use xlink:href="#glyph0-7" x="971.666016" y="90"/>
|
||||
<use xlink:href="#glyph0-2" x="976.599609" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="983.953125" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="990.550781" y="90"/>
|
||||
<use xlink:href="#glyph0-20" x="997.933594" y="90"/>
|
||||
<use xlink:href="#glyph0-13" x="1001.267578" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1006.179688 78 L 1008.5625 78 L 1008.5625 92 L 1006.179688 92 Z M 1006.179688 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1008.5625 78 L 1083.6875 78 L 1083.6875 92 L 1008.5625 92 Z M 1008.5625 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1083.6875 78 L 1096.113281 78 L 1096.113281 92 L 1083.6875 92 Z M 1083.6875 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1096.117188 78 L 1093.667969 78 L 1093.667969 92 L 1096.117188 92 Z M 1096.117188 78 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 431.214844 81 L 431.214844 75 "/>
|
||||
<g clip-path="url(#clip6)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="433.214844" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="437.949219" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="440.492188" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="447.195312" y="76"/>
|
||||
<use xlink:href="#glyph1-4" x="449.738281" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 852.011719 81 L 852.011719 75 "/>
|
||||
<g clip-path="url(#clip7)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="854.011719" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="858.746094" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="861.289062" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="867.992188" y="76"/>
|
||||
<use xlink:href="#glyph1-5" x="870.535156" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 991.652344 81 L 991.652344 75 "/>
|
||||
<g clip-path="url(#clip8)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="993.652344" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="998.386719" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="1000.929688" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="1007.632812" y="76"/>
|
||||
<use xlink:href="#glyph1-6" x="1010.175781" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 117.976562 46 L 117.976562 92 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 736.246094 49 L 736.246094 43 "/>
|
||||
<g clip-path="url(#clip9)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-7" x="738.246094" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="742.980469" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="745.523438" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="752.226562" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="754.769531" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 935.078125 49 L 935.078125 43 "/>
|
||||
<g clip-path="url(#clip10)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-7" x="937.078125" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="941.8125" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="944.355469" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="951.058594" y="44"/>
|
||||
<use xlink:href="#glyph1-5" x="953.601562" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1045.515625 49 L 1045.515625 43 "/>
|
||||
<g clip-path="url(#clip11)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-7" x="1047.515625" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1052.25" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="1054.792969" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1061.496094" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1064.039062" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 78.671875 36 L 74.671875 36 L 74.671875 96 L 78.671875 96 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1101.464844 36 L 1105.464844 36 L 1105.464844 96 L 1101.464844 96 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-8" x="76.671875" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="81.75" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="86.644531" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="89.78125" y="44"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 10.984375 46 L 10.984375 60 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 40 KiB |
BIN
doc/traces/cancel-posix.fxt
Normal file
BIN
doc/traces/cancel-posix.fxt
Normal file
Binary file not shown.
344
doc/traces/cancel-posix.svg
Normal file
344
doc/traces/cancel-posix.svg
Normal file
@ -0,0 +1,344 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1280pt" height="120pt" viewBox="0 0 1280 120" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d="M 0.59375 2.125 L 0.59375 -8.46875 L 6.59375 -8.46875 L 6.59375 2.125 Z M 1.265625 1.453125 L 5.9375 1.453125 L 5.9375 -7.78125 L 1.265625 -7.78125 Z M 1.265625 1.453125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 1.171875 -8.75 L 6.703125 -8.75 L 6.703125 -7.75 L 2.359375 -7.75 L 2.359375 -5.15625 L 6.53125 -5.15625 L 6.53125 -4.171875 L 2.359375 -4.171875 L 2.359375 -1 L 6.8125 -1 L 6.8125 0 L 1.171875 0 Z M 1.171875 -8.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 4.109375 -3.296875 C 3.242188 -3.296875 2.640625 -3.195312 2.296875 -3 C 1.960938 -2.800781 1.796875 -2.460938 1.796875 -1.984375 C 1.796875 -1.597656 1.921875 -1.289062 2.171875 -1.0625 C 2.429688 -0.84375 2.773438 -0.734375 3.203125 -0.734375 C 3.804688 -0.734375 4.285156 -0.941406 4.640625 -1.359375 C 5.003906 -1.785156 5.1875 -2.351562 5.1875 -3.0625 L 5.1875 -3.296875 Z M 6.265625 -3.75 L 6.265625 0 L 5.1875 0 L 5.1875 -1 C 4.9375 -0.601562 4.628906 -0.304688 4.265625 -0.109375 C 3.898438 0.078125 3.453125 0.171875 2.921875 0.171875 C 2.242188 0.171875 1.707031 -0.015625 1.3125 -0.390625 C 0.914062 -0.773438 0.71875 -1.28125 0.71875 -1.90625 C 0.71875 -2.644531 0.960938 -3.203125 1.453125 -3.578125 C 1.953125 -3.953125 2.691406 -4.140625 3.671875 -4.140625 L 5.1875 -4.140625 L 5.1875 -4.25 C 5.1875 -4.75 5.019531 -5.132812 4.6875 -5.40625 C 4.363281 -5.675781 3.910156 -5.8125 3.328125 -5.8125 C 2.953125 -5.8125 2.582031 -5.765625 2.21875 -5.671875 C 1.863281 -5.578125 1.523438 -5.441406 1.203125 -5.265625 L 1.203125 -6.265625 C 1.597656 -6.421875 1.976562 -6.535156 2.34375 -6.609375 C 2.71875 -6.679688 3.082031 -6.71875 3.4375 -6.71875 C 4.382812 -6.71875 5.09375 -6.472656 5.5625 -5.984375 C 6.03125 -5.492188 6.265625 -4.75 6.265625 -3.75 Z M 6.265625 -3.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 5.859375 -6.3125 L 5.859375 -5.296875 C 5.546875 -5.472656 5.238281 -5.601562 4.9375 -5.6875 C 4.632812 -5.769531 4.328125 -5.8125 4.015625 -5.8125 C 3.304688 -5.8125 2.757812 -5.585938 2.375 -5.140625 C 1.988281 -4.703125 1.796875 -4.082031 1.796875 -3.28125 C 1.796875 -2.476562 1.988281 -1.851562 2.375 -1.40625 C 2.757812 -0.96875 3.304688 -0.75 4.015625 -0.75 C 4.328125 -0.75 4.632812 -0.789062 4.9375 -0.875 C 5.238281 -0.957031 5.546875 -1.082031 5.859375 -1.25 L 5.859375 -0.25 C 5.554688 -0.113281 5.242188 -0.0078125 4.921875 0.0625 C 4.597656 0.132812 4.253906 0.171875 3.890625 0.171875 C 2.898438 0.171875 2.113281 -0.132812 1.53125 -0.75 C 0.945312 -1.375 0.65625 -2.21875 0.65625 -3.28125 C 0.65625 -4.34375 0.945312 -5.179688 1.53125 -5.796875 C 2.125 -6.410156 2.9375 -6.71875 3.96875 -6.71875 C 4.289062 -6.71875 4.609375 -6.679688 4.921875 -6.609375 C 5.242188 -6.546875 5.554688 -6.445312 5.859375 -6.3125 Z M 5.859375 -6.3125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -9.125 L 2.171875 -9.125 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 5.453125 -3.359375 C 5.453125 -4.140625 5.289062 -4.742188 4.96875 -5.171875 C 4.644531 -5.597656 4.191406 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.597656 2.265625 -5.171875 C 1.941406 -4.742188 1.78125 -4.140625 1.78125 -3.359375 C 1.78125 -2.578125 1.941406 -1.972656 2.265625 -1.546875 C 2.585938 -1.117188 3.035156 -0.90625 3.609375 -0.90625 C 4.191406 -0.90625 4.644531 -1.117188 4.96875 -1.546875 C 5.289062 -1.972656 5.453125 -2.578125 5.453125 -3.359375 Z M 6.53125 -0.8125 C 6.53125 0.300781 6.28125 1.128906 5.78125 1.671875 C 5.289062 2.222656 4.53125 2.5 3.5 2.5 C 3.125 2.5 2.765625 2.46875 2.421875 2.40625 C 2.085938 2.351562 1.765625 2.269531 1.453125 2.15625 L 1.453125 1.109375 C 1.765625 1.273438 2.078125 1.398438 2.390625 1.484375 C 2.703125 1.566406 3.015625 1.609375 3.328125 1.609375 C 4.035156 1.609375 4.566406 1.421875 4.921875 1.046875 C 5.273438 0.679688 5.453125 0.125 5.453125 -0.625 L 5.453125 -1.15625 C 5.222656 -0.769531 4.9375 -0.476562 4.59375 -0.28125 C 4.25 -0.09375 3.832031 0 3.34375 0 C 2.539062 0 1.890625 -0.304688 1.390625 -0.921875 C 0.898438 -1.535156 0.65625 -2.347656 0.65625 -3.359375 C 0.65625 -4.367188 0.898438 -5.179688 1.390625 -5.796875 C 1.890625 -6.410156 2.539062 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.617188 4.59375 -6.421875 C 4.9375 -6.234375 5.222656 -5.945312 5.453125 -5.5625 L 5.453125 -6.5625 L 6.53125 -6.5625 Z M 6.53125 -0.8125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-7">
|
||||
<path style="stroke:none;" d="M 4.9375 -5.5625 C 4.8125 -5.625 4.675781 -5.671875 4.53125 -5.703125 C 4.394531 -5.742188 4.238281 -5.765625 4.0625 -5.765625 C 3.457031 -5.765625 2.988281 -5.566406 2.65625 -5.171875 C 2.332031 -4.773438 2.171875 -4.203125 2.171875 -3.453125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.398438 -5.941406 2.695312 -6.234375 3.0625 -6.421875 C 3.425781 -6.617188 3.867188 -6.71875 4.390625 -6.71875 C 4.460938 -6.71875 4.539062 -6.710938 4.625 -6.703125 C 4.71875 -6.691406 4.816406 -6.675781 4.921875 -6.65625 Z M 4.9375 -5.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-8">
|
||||
<path style="stroke:none;" d="M 1.125 -6.5625 L 2.203125 -6.5625 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 -7.75 L 1.125 -7.75 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-9">
|
||||
<path style="stroke:none;" d="M 5.453125 -5.5625 L 5.453125 -9.125 L 6.53125 -9.125 L 6.53125 0 L 5.453125 0 L 5.453125 -0.984375 C 5.222656 -0.597656 4.9375 -0.304688 4.59375 -0.109375 C 4.25 0.078125 3.832031 0.171875 3.34375 0.171875 C 2.550781 0.171875 1.90625 -0.144531 1.40625 -0.78125 C 0.90625 -1.414062 0.65625 -2.25 0.65625 -3.28125 C 0.65625 -4.3125 0.90625 -5.140625 1.40625 -5.765625 C 1.90625 -6.398438 2.550781 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.625 4.59375 -6.4375 C 4.9375 -6.25 5.222656 -5.957031 5.453125 -5.5625 Z M 1.78125 -3.28125 C 1.78125 -2.488281 1.941406 -1.863281 2.265625 -1.40625 C 2.585938 -0.957031 3.035156 -0.734375 3.609375 -0.734375 C 4.179688 -0.734375 4.628906 -0.957031 4.953125 -1.40625 C 5.285156 -1.863281 5.453125 -2.488281 5.453125 -3.28125 C 5.453125 -4.070312 5.285156 -4.691406 4.953125 -5.140625 C 4.628906 -5.585938 4.179688 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.585938 2.265625 -5.140625 C 1.941406 -4.691406 1.78125 -4.070312 1.78125 -3.28125 Z M 1.78125 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-10">
|
||||
<path style="stroke:none;" d="M 0.359375 -6.5625 L 1.5 -6.5625 L 3.546875 -1.0625 L 5.609375 -6.5625 L 6.75 -6.5625 L 4.28125 0 L 2.8125 0 Z M 0.359375 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-11">
|
||||
<path style="stroke:none;" d="M 5.3125 -6.375 L 5.3125 -5.34375 C 5.007812 -5.5 4.691406 -5.613281 4.359375 -5.6875 C 4.035156 -5.769531 3.695312 -5.8125 3.34375 -5.8125 C 2.8125 -5.8125 2.410156 -5.726562 2.140625 -5.5625 C 1.867188 -5.40625 1.734375 -5.160156 1.734375 -4.828125 C 1.734375 -4.578125 1.828125 -4.378906 2.015625 -4.234375 C 2.210938 -4.097656 2.601562 -3.96875 3.1875 -3.84375 L 3.546875 -3.75 C 4.316406 -3.59375 4.863281 -3.363281 5.1875 -3.0625 C 5.507812 -2.757812 5.671875 -2.34375 5.671875 -1.8125 C 5.671875 -1.195312 5.425781 -0.710938 4.9375 -0.359375 C 4.457031 -0.00390625 3.796875 0.171875 2.953125 0.171875 C 2.597656 0.171875 2.226562 0.132812 1.84375 0.0625 C 1.46875 0 1.070312 -0.0976562 0.65625 -0.234375 L 0.65625 -1.359375 C 1.050781 -1.148438 1.441406 -0.992188 1.828125 -0.890625 C 2.210938 -0.785156 2.597656 -0.734375 2.984375 -0.734375 C 3.484375 -0.734375 3.867188 -0.816406 4.140625 -0.984375 C 4.421875 -1.160156 4.5625 -1.410156 4.5625 -1.734375 C 4.5625 -2.023438 4.460938 -2.25 4.265625 -2.40625 C 4.066406 -2.5625 3.632812 -2.710938 2.96875 -2.859375 L 2.59375 -2.9375 C 1.925781 -3.082031 1.441406 -3.300781 1.140625 -3.59375 C 0.847656 -3.882812 0.703125 -4.28125 0.703125 -4.78125 C 0.703125 -5.40625 0.921875 -5.882812 1.359375 -6.21875 C 1.796875 -6.550781 2.414062 -6.71875 3.21875 -6.71875 C 3.613281 -6.71875 3.988281 -6.6875 4.34375 -6.625 C 4.695312 -6.570312 5.019531 -6.488281 5.3125 -6.375 Z M 5.3125 -6.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-12">
|
||||
<path style="stroke:none;" d="M 3.671875 -5.8125 C 3.097656 -5.8125 2.640625 -5.582031 2.296875 -5.125 C 1.960938 -4.675781 1.796875 -4.0625 1.796875 -3.28125 C 1.796875 -2.488281 1.960938 -1.867188 2.296875 -1.421875 C 2.628906 -0.972656 3.085938 -0.75 3.671875 -0.75 C 4.242188 -0.75 4.695312 -0.972656 5.03125 -1.421875 C 5.375 -1.878906 5.546875 -2.5 5.546875 -3.28125 C 5.546875 -4.050781 5.375 -4.664062 5.03125 -5.125 C 4.695312 -5.582031 4.242188 -5.8125 3.671875 -5.8125 Z M 3.671875 -6.71875 C 4.609375 -6.71875 5.34375 -6.410156 5.875 -5.796875 C 6.414062 -5.191406 6.6875 -4.351562 6.6875 -3.28125 C 6.6875 -2.207031 6.414062 -1.363281 5.875 -0.75 C 5.34375 -0.132812 4.609375 0.171875 3.671875 0.171875 C 2.734375 0.171875 1.992188 -0.132812 1.453125 -0.75 C 0.921875 -1.363281 0.65625 -2.207031 0.65625 -3.28125 C 0.65625 -4.351562 0.921875 -5.191406 1.453125 -5.796875 C 1.992188 -6.410156 2.734375 -6.71875 3.671875 -6.71875 Z M 3.671875 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-13">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-14">
|
||||
<path style="stroke:none;" d="M 1.40625 -1.484375 L 2.640625 -1.484375 L 2.640625 0 L 1.40625 0 Z M 1.40625 -6.203125 L 2.640625 -6.203125 L 2.640625 -4.71875 L 1.40625 -4.71875 Z M 1.40625 -6.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-15">
|
||||
<path style="stroke:none;" d="M 1.484375 -1 L 3.421875 -1 L 3.421875 -7.671875 L 1.3125 -7.25 L 1.3125 -8.328125 L 3.40625 -8.75 L 4.59375 -8.75 L 4.59375 -1 L 6.53125 -1 L 6.53125 0 L 1.484375 0 Z M 1.484375 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-16">
|
||||
<path style="stroke:none;" d="M 3.8125 -7.96875 C 3.207031 -7.96875 2.75 -7.664062 2.4375 -7.0625 C 2.132812 -6.46875 1.984375 -5.566406 1.984375 -4.359375 C 1.984375 -3.160156 2.132812 -2.257812 2.4375 -1.65625 C 2.75 -1.0625 3.207031 -0.765625 3.8125 -0.765625 C 4.425781 -0.765625 4.882812 -1.0625 5.1875 -1.65625 C 5.5 -2.257812 5.65625 -3.160156 5.65625 -4.359375 C 5.65625 -5.566406 5.5 -6.46875 5.1875 -7.0625 C 4.882812 -7.664062 4.425781 -7.96875 3.8125 -7.96875 Z M 3.8125 -8.90625 C 4.789062 -8.90625 5.539062 -8.515625 6.0625 -7.734375 C 6.582031 -6.960938 6.84375 -5.835938 6.84375 -4.359375 C 6.84375 -2.890625 6.582031 -1.765625 6.0625 -0.984375 C 5.539062 -0.210938 4.789062 0.171875 3.8125 0.171875 C 2.832031 0.171875 2.082031 -0.210938 1.5625 -0.984375 C 1.050781 -1.765625 0.796875 -2.890625 0.796875 -4.359375 C 0.796875 -5.835938 1.050781 -6.960938 1.5625 -7.734375 C 2.082031 -8.515625 2.832031 -8.90625 3.8125 -8.90625 Z M 3.8125 -8.90625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-17">
|
||||
<path style="stroke:none;" d="M 1.015625 -2.59375 L 1.015625 -6.5625 L 2.09375 -6.5625 L 2.09375 -2.625 C 2.09375 -2.007812 2.210938 -1.546875 2.453125 -1.234375 C 2.703125 -0.921875 3.066406 -0.765625 3.546875 -0.765625 C 4.128906 -0.765625 4.585938 -0.945312 4.921875 -1.3125 C 5.265625 -1.6875 5.4375 -2.195312 5.4375 -2.84375 L 5.4375 -6.5625 L 6.515625 -6.5625 L 6.515625 0 L 5.4375 0 L 5.4375 -1.015625 C 5.175781 -0.609375 4.875 -0.304688 4.53125 -0.109375 C 4.1875 0.078125 3.785156 0.171875 3.328125 0.171875 C 2.566406 0.171875 1.988281 -0.0625 1.59375 -0.53125 C 1.207031 -1 1.015625 -1.6875 1.015625 -2.59375 Z M 3.734375 -6.71875 Z M 3.734375 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-18">
|
||||
<path style="stroke:none;" d="M 2.171875 -0.984375 L 2.171875 2.5 L 1.09375 2.5 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.5625 C 2.398438 -5.957031 2.6875 -6.25 3.03125 -6.4375 C 3.375 -6.625 3.785156 -6.71875 4.265625 -6.71875 C 5.066406 -6.71875 5.71875 -6.398438 6.21875 -5.765625 C 6.71875 -5.140625 6.96875 -4.3125 6.96875 -3.28125 C 6.96875 -2.25 6.71875 -1.414062 6.21875 -0.78125 C 5.71875 -0.144531 5.066406 0.171875 4.265625 0.171875 C 3.785156 0.171875 3.375 0.078125 3.03125 -0.109375 C 2.6875 -0.304688 2.398438 -0.597656 2.171875 -0.984375 Z M 5.84375 -3.28125 C 5.84375 -4.070312 5.675781 -4.691406 5.34375 -5.140625 C 5.019531 -5.585938 4.578125 -5.8125 4.015625 -5.8125 C 3.441406 -5.8125 2.988281 -5.585938 2.65625 -5.140625 C 2.332031 -4.691406 2.171875 -4.070312 2.171875 -3.28125 C 2.171875 -2.488281 2.332031 -1.863281 2.65625 -1.40625 C 2.988281 -0.957031 3.441406 -0.734375 4.015625 -0.734375 C 4.578125 -0.734375 5.019531 -0.957031 5.34375 -1.40625 C 5.675781 -1.863281 5.84375 -2.488281 5.84375 -3.28125 Z M 5.84375 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-19">
|
||||
<path style="stroke:none;" d="M 6.75 -3.546875 L 6.75 -3.03125 L 1.78125 -3.03125 C 1.832031 -2.28125 2.054688 -1.710938 2.453125 -1.328125 C 2.859375 -0.941406 3.414062 -0.75 4.125 -0.75 C 4.539062 -0.75 4.941406 -0.796875 5.328125 -0.890625 C 5.722656 -0.992188 6.113281 -1.148438 6.5 -1.359375 L 6.5 -0.328125 C 6.101562 -0.171875 5.703125 -0.0507812 5.296875 0.03125 C 4.890625 0.125 4.476562 0.171875 4.0625 0.171875 C 3.019531 0.171875 2.191406 -0.128906 1.578125 -0.734375 C 0.960938 -1.347656 0.65625 -2.175781 0.65625 -3.21875 C 0.65625 -4.289062 0.945312 -5.140625 1.53125 -5.765625 C 2.113281 -6.398438 2.894531 -6.71875 3.875 -6.71875 C 4.757812 -6.71875 5.457031 -6.429688 5.96875 -5.859375 C 6.488281 -5.296875 6.75 -4.523438 6.75 -3.546875 Z M 5.671875 -3.875 C 5.660156 -4.457031 5.492188 -4.925781 5.171875 -5.28125 C 4.847656 -5.632812 4.421875 -5.8125 3.890625 -5.8125 C 3.285156 -5.8125 2.800781 -5.640625 2.4375 -5.296875 C 2.082031 -4.953125 1.878906 -4.472656 1.828125 -3.859375 Z M 5.671875 -3.875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-20">
|
||||
<path style="stroke:none;" d="M 0.59375 -3.765625 L 3.75 -3.765625 L 3.75 -2.8125 L 0.59375 -2.8125 Z M 0.59375 -3.765625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-21">
|
||||
<path style="stroke:none;" d="M 6.234375 -5.296875 C 6.503906 -5.785156 6.828125 -6.144531 7.203125 -6.375 C 7.578125 -6.601562 8.019531 -6.71875 8.53125 -6.71875 C 9.21875 -6.71875 9.742188 -6.476562 10.109375 -6 C 10.484375 -5.519531 10.671875 -4.84375 10.671875 -3.96875 L 10.671875 0 L 9.59375 0 L 9.59375 -3.921875 C 9.59375 -4.554688 9.476562 -5.023438 9.25 -5.328125 C 9.03125 -5.628906 8.691406 -5.78125 8.234375 -5.78125 C 7.671875 -5.78125 7.226562 -5.59375 6.90625 -5.21875 C 6.582031 -4.851562 6.421875 -4.347656 6.421875 -3.703125 L 6.421875 0 L 5.34375 0 L 5.34375 -3.921875 C 5.34375 -4.554688 5.226562 -5.023438 5 -5.328125 C 4.78125 -5.628906 4.4375 -5.78125 3.96875 -5.78125 C 3.414062 -5.78125 2.976562 -5.59375 2.65625 -5.21875 C 2.332031 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.421875 -5.941406 2.71875 -6.234375 3.0625 -6.421875 C 3.40625 -6.617188 3.8125 -6.71875 4.28125 -6.71875 C 4.757812 -6.71875 5.164062 -6.597656 5.5 -6.359375 C 5.832031 -6.117188 6.078125 -5.765625 6.234375 -5.296875 Z M 6.234375 -5.296875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-22">
|
||||
<path style="stroke:none;" d="M 6.421875 -8.46875 L 6.421875 -7.3125 C 5.972656 -7.519531 5.546875 -7.675781 5.140625 -7.78125 C 4.742188 -7.894531 4.363281 -7.953125 4 -7.953125 C 3.351562 -7.953125 2.851562 -7.828125 2.5 -7.578125 C 2.15625 -7.328125 1.984375 -6.96875 1.984375 -6.5 C 1.984375 -6.113281 2.097656 -5.820312 2.328125 -5.625 C 2.554688 -5.425781 3 -5.269531 3.65625 -5.15625 L 4.359375 -5 C 5.242188 -4.832031 5.894531 -4.535156 6.3125 -4.109375 C 6.738281 -3.691406 6.953125 -3.128906 6.953125 -2.421875 C 6.953125 -1.566406 6.664062 -0.921875 6.09375 -0.484375 C 5.53125 -0.046875 4.695312 0.171875 3.59375 0.171875 C 3.1875 0.171875 2.75 0.125 2.28125 0.03125 C 1.8125 -0.0625 1.328125 -0.203125 0.828125 -0.390625 L 0.828125 -1.609375 C 1.304688 -1.335938 1.773438 -1.132812 2.234375 -1 C 2.703125 -0.863281 3.15625 -0.796875 3.59375 -0.796875 C 4.269531 -0.796875 4.789062 -0.925781 5.15625 -1.1875 C 5.53125 -1.457031 5.71875 -1.835938 5.71875 -2.328125 C 5.71875 -2.753906 5.582031 -3.085938 5.3125 -3.328125 C 5.050781 -3.578125 4.617188 -3.757812 4.015625 -3.875 L 3.296875 -4.015625 C 2.410156 -4.191406 1.769531 -4.46875 1.375 -4.84375 C 0.988281 -5.21875 0.796875 -5.738281 0.796875 -6.40625 C 0.796875 -7.1875 1.066406 -7.796875 1.609375 -8.234375 C 2.148438 -8.679688 2.898438 -8.90625 3.859375 -8.90625 C 4.273438 -8.90625 4.691406 -8.867188 5.109375 -8.796875 C 5.535156 -8.722656 5.972656 -8.613281 6.421875 -8.46875 Z M 6.421875 -8.46875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-23">
|
||||
<path style="stroke:none;" d="M 0.5 -6.5625 L 1.578125 -6.5625 L 2.9375 -1.4375 L 4.265625 -6.5625 L 5.546875 -6.5625 L 6.890625 -1.4375 L 8.234375 -6.5625 L 9.3125 -6.5625 L 7.59375 0 L 6.328125 0 L 4.90625 -5.375 L 3.5 0 L 2.21875 0 Z M 0.5 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-24">
|
||||
<path style="stroke:none;" d="M 2.203125 -8.421875 L 2.203125 -6.5625 L 4.421875 -6.5625 L 4.421875 -5.71875 L 2.203125 -5.71875 L 2.203125 -2.15625 C 2.203125 -1.625 2.273438 -1.28125 2.421875 -1.125 C 2.566406 -0.976562 2.863281 -0.90625 3.3125 -0.90625 L 4.421875 -0.90625 L 4.421875 0 L 3.3125 0 C 2.476562 0 1.898438 -0.15625 1.578125 -0.46875 C 1.265625 -0.78125 1.109375 -1.34375 1.109375 -2.15625 L 1.109375 -5.71875 L 0.328125 -5.71875 L 0.328125 -6.5625 L 1.109375 -6.5625 L 1.109375 -8.421875 Z M 2.203125 -8.421875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-25">
|
||||
<path style="stroke:none;" d="M 1.28125 -1.484375 L 2.515625 -1.484375 L 2.515625 0 L 1.28125 0 Z M 1.28125 -1.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-26">
|
||||
<path style="stroke:none;" d="M 6.125 2 L 6.125 2.828125 L -0.125 2.828125 L -0.125 2 Z M 6.125 2 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-27">
|
||||
<path style="stroke:none;" d="M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-0">
|
||||
<path style="stroke:none;" d="M 0.40625 1.421875 L 0.40625 -5.640625 L 4.40625 -5.640625 L 4.40625 1.421875 Z M 0.84375 0.96875 L 3.953125 0.96875 L 3.953125 -5.1875 L 0.84375 -5.1875 Z M 0.84375 0.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-1">
|
||||
<path style="stroke:none;" d="M 4.390625 -4.375 L 2.8125 -2.25 L 4.46875 0 L 3.625 0 L 2.359375 -1.71875 L 1.078125 0 L 0.234375 0 L 1.9375 -2.296875 L 0.375 -4.375 L 1.21875 -4.375 L 2.390625 -2.8125 L 3.546875 -4.375 Z M 4.390625 -4.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-2">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-3">
|
||||
<path style="stroke:none;" d="M 0.84375 -3.640625 L 5.859375 -3.640625 L 5.859375 -2.984375 L 0.84375 -2.984375 Z M 0.84375 -2.046875 L 5.859375 -2.046875 L 5.859375 -1.375 L 0.84375 -1.375 Z M 0.84375 -2.046875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-4">
|
||||
<path style="stroke:none;" d="M 1 -0.671875 L 2.28125 -0.671875 L 2.28125 -5.109375 L 0.875 -4.828125 L 0.875 -5.546875 L 2.28125 -5.828125 L 3.0625 -5.828125 L 3.0625 -0.671875 L 4.359375 -0.671875 L 4.359375 0 L 1 0 Z M 1 -0.671875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-5">
|
||||
<path style="stroke:none;" d="M 0.78125 -5.828125 L 4.140625 -5.828125 L 4.140625 -5.171875 L 1.578125 -5.171875 L 1.578125 -3.453125 L 3.890625 -3.453125 L 3.890625 -2.78125 L 1.578125 -2.78125 L 1.578125 0 L 0.78125 0 Z M 0.78125 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-6">
|
||||
<path style="stroke:none;" d="M 2.75 -2.203125 C 2.164062 -2.203125 1.757812 -2.132812 1.53125 -2 C 1.3125 -1.863281 1.203125 -1.640625 1.203125 -1.328125 C 1.203125 -1.066406 1.285156 -0.859375 1.453125 -0.703125 C 1.617188 -0.554688 1.847656 -0.484375 2.140625 -0.484375 C 2.535156 -0.484375 2.851562 -0.625 3.09375 -0.90625 C 3.332031 -1.195312 3.453125 -1.578125 3.453125 -2.046875 L 3.453125 -2.203125 Z M 4.171875 -2.5 L 4.171875 0 L 3.453125 0 L 3.453125 -0.671875 C 3.296875 -0.398438 3.09375 -0.203125 2.84375 -0.078125 C 2.601562 0.046875 2.304688 0.109375 1.953125 0.109375 C 1.503906 0.109375 1.144531 -0.015625 0.875 -0.265625 C 0.613281 -0.515625 0.484375 -0.851562 0.484375 -1.28125 C 0.484375 -1.769531 0.644531 -2.140625 0.96875 -2.390625 C 1.300781 -2.640625 1.796875 -2.765625 2.453125 -2.765625 L 3.453125 -2.765625 L 3.453125 -2.828125 C 3.453125 -3.160156 3.34375 -3.414062 3.125 -3.59375 C 2.914062 -3.78125 2.613281 -3.875 2.21875 -3.875 C 1.96875 -3.875 1.722656 -3.84375 1.484375 -3.78125 C 1.242188 -3.71875 1.015625 -3.628906 0.796875 -3.515625 L 0.796875 -4.171875 C 1.066406 -4.273438 1.320312 -4.351562 1.5625 -4.40625 C 1.8125 -4.457031 2.054688 -4.484375 2.296875 -4.484375 C 2.921875 -4.484375 3.390625 -4.316406 3.703125 -3.984375 C 4.015625 -3.660156 4.171875 -3.164062 4.171875 -2.5 Z M 4.171875 -2.5 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-7">
|
||||
<path style="stroke:none;" d="M 0.75 -4.375 L 1.46875 -4.375 L 1.46875 0 L 0.75 0 Z M 0.75 -6.078125 L 1.46875 -6.078125 L 1.46875 -5.171875 L 0.75 -5.171875 Z M 0.75 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-8">
|
||||
<path style="stroke:none;" d="M 0.75 -6.078125 L 1.46875 -6.078125 L 1.46875 0 L 0.75 0 Z M 0.75 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-9">
|
||||
<path style="stroke:none;" d="M 0.6875 -1.734375 L 0.6875 -4.375 L 1.40625 -4.375 L 1.40625 -1.75 C 1.40625 -1.34375 1.484375 -1.035156 1.640625 -0.828125 C 1.804688 -0.617188 2.050781 -0.515625 2.375 -0.515625 C 2.757812 -0.515625 3.0625 -0.632812 3.28125 -0.875 C 3.507812 -1.125 3.625 -1.460938 3.625 -1.890625 L 3.625 -4.375 L 4.34375 -4.375 L 4.34375 0 L 3.625 0 L 3.625 -0.671875 C 3.445312 -0.410156 3.242188 -0.210938 3.015625 -0.078125 C 2.785156 0.046875 2.519531 0.109375 2.21875 0.109375 C 1.71875 0.109375 1.335938 -0.046875 1.078125 -0.359375 C 0.816406 -0.671875 0.6875 -1.128906 0.6875 -1.734375 Z M 2.484375 -4.484375 Z M 2.484375 -4.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-10">
|
||||
<path style="stroke:none;" d="M 3.296875 -3.703125 C 3.210938 -3.753906 3.125 -3.789062 3.03125 -3.8125 C 2.9375 -3.832031 2.832031 -3.84375 2.71875 -3.84375 C 2.3125 -3.84375 2 -3.707031 1.78125 -3.4375 C 1.5625 -3.175781 1.453125 -2.800781 1.453125 -2.3125 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.597656 -3.960938 1.789062 -4.15625 2.03125 -4.28125 C 2.28125 -4.414062 2.578125 -4.484375 2.921875 -4.484375 C 2.972656 -4.484375 3.023438 -4.476562 3.078125 -4.46875 C 3.140625 -4.46875 3.207031 -4.457031 3.28125 -4.4375 Z M 3.296875 -3.703125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-11">
|
||||
<path style="stroke:none;" d="M 4.5 -2.375 L 4.5 -2.015625 L 1.1875 -2.015625 C 1.21875 -1.523438 1.367188 -1.148438 1.640625 -0.890625 C 1.910156 -0.628906 2.28125 -0.5 2.75 -0.5 C 3.03125 -0.5 3.300781 -0.53125 3.5625 -0.59375 C 3.820312 -0.664062 4.078125 -0.769531 4.328125 -0.90625 L 4.328125 -0.21875 C 4.066406 -0.113281 3.800781 -0.0351562 3.53125 0.015625 C 3.257812 0.078125 2.988281 0.109375 2.71875 0.109375 C 2.019531 0.109375 1.460938 -0.09375 1.046875 -0.5 C 0.640625 -0.90625 0.4375 -1.453125 0.4375 -2.140625 C 0.4375 -2.859375 0.628906 -3.425781 1.015625 -3.84375 C 1.410156 -4.269531 1.9375 -4.484375 2.59375 -4.484375 C 3.175781 -4.484375 3.640625 -4.289062 3.984375 -3.90625 C 4.328125 -3.53125 4.5 -3.019531 4.5 -2.375 Z M 3.78125 -2.578125 C 3.769531 -2.972656 3.65625 -3.285156 3.4375 -3.515625 C 3.226562 -3.753906 2.945312 -3.875 2.59375 -3.875 C 2.195312 -3.875 1.875 -3.757812 1.625 -3.53125 C 1.382812 -3.300781 1.25 -2.984375 1.21875 -2.578125 Z M 3.78125 -2.578125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-12">
|
||||
<path style="stroke:none;" d="M 2.484375 -6.078125 C 2.128906 -5.472656 1.867188 -4.878906 1.703125 -4.296875 C 1.535156 -3.710938 1.453125 -3.117188 1.453125 -2.515625 C 1.453125 -1.910156 1.535156 -1.3125 1.703125 -0.71875 C 1.878906 -0.132812 2.140625 0.457031 2.484375 1.0625 L 1.859375 1.0625 C 1.460938 0.445312 1.164062 -0.15625 0.96875 -0.75 C 0.78125 -1.34375 0.6875 -1.929688 0.6875 -2.515625 C 0.6875 -3.097656 0.78125 -3.679688 0.96875 -4.265625 C 1.164062 -4.859375 1.460938 -5.460938 1.859375 -6.078125 Z M 2.484375 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-13">
|
||||
<path style="stroke:none;" d="M 1.4375 -5.828125 L 1.4375 -3.671875 L 0.765625 -3.671875 L 0.765625 -5.828125 Z M 2.90625 -5.828125 L 2.90625 -3.671875 L 2.25 -3.671875 L 2.25 -5.828125 Z M 2.90625 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-14">
|
||||
<path style="stroke:none;" d="M 4.28125 -5.640625 L 4.28125 -4.875 C 3.976562 -5.019531 3.691406 -5.125 3.421875 -5.1875 C 3.160156 -5.257812 2.910156 -5.296875 2.671875 -5.296875 C 2.234375 -5.296875 1.898438 -5.210938 1.671875 -5.046875 C 1.441406 -4.878906 1.328125 -4.644531 1.328125 -4.34375 C 1.328125 -4.082031 1.398438 -3.882812 1.546875 -3.75 C 1.703125 -3.625 2 -3.519531 2.4375 -3.4375 L 2.90625 -3.34375 C 3.5 -3.226562 3.9375 -3.03125 4.21875 -2.75 C 4.5 -2.46875 4.640625 -2.085938 4.640625 -1.609375 C 4.640625 -1.046875 4.445312 -0.617188 4.0625 -0.328125 C 3.6875 -0.0351562 3.132812 0.109375 2.40625 0.109375 C 2.125 0.109375 1.828125 0.078125 1.515625 0.015625 C 1.203125 -0.046875 0.878906 -0.140625 0.546875 -0.265625 L 0.546875 -1.078125 C 0.867188 -0.890625 1.179688 -0.75 1.484375 -0.65625 C 1.796875 -0.570312 2.101562 -0.53125 2.40625 -0.53125 C 2.851562 -0.53125 3.195312 -0.617188 3.4375 -0.796875 C 3.6875 -0.972656 3.8125 -1.222656 3.8125 -1.546875 C 3.8125 -1.835938 3.722656 -2.0625 3.546875 -2.21875 C 3.367188 -2.382812 3.082031 -2.507812 2.6875 -2.59375 L 2.203125 -2.6875 C 1.609375 -2.800781 1.179688 -2.984375 0.921875 -3.234375 C 0.660156 -3.484375 0.53125 -3.832031 0.53125 -4.28125 C 0.53125 -4.789062 0.710938 -5.191406 1.078125 -5.484375 C 1.441406 -5.785156 1.941406 -5.9375 2.578125 -5.9375 C 2.847656 -5.9375 3.125 -5.910156 3.40625 -5.859375 C 3.695312 -5.816406 3.988281 -5.742188 4.28125 -5.640625 Z M 4.28125 -5.640625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-15">
|
||||
<path style="stroke:none;" d="M 4.15625 -3.53125 C 4.34375 -3.851562 4.5625 -4.09375 4.8125 -4.25 C 5.0625 -4.40625 5.351562 -4.484375 5.6875 -4.484375 C 6.144531 -4.484375 6.492188 -4.320312 6.734375 -4 C 6.984375 -3.6875 7.109375 -3.234375 7.109375 -2.640625 L 7.109375 0 L 6.390625 0 L 6.390625 -2.625 C 6.390625 -3.039062 6.316406 -3.347656 6.171875 -3.546875 C 6.023438 -3.753906 5.796875 -3.859375 5.484375 -3.859375 C 5.117188 -3.859375 4.828125 -3.734375 4.609375 -3.484375 C 4.390625 -3.234375 4.28125 -2.894531 4.28125 -2.46875 L 4.28125 0 L 3.5625 0 L 3.5625 -2.625 C 3.5625 -3.039062 3.484375 -3.347656 3.328125 -3.546875 C 3.179688 -3.753906 2.957031 -3.859375 2.65625 -3.859375 C 2.28125 -3.859375 1.984375 -3.734375 1.765625 -3.484375 C 1.554688 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.273438 -4.414062 2.546875 -4.484375 2.859375 -4.484375 C 3.171875 -4.484375 3.4375 -4.398438 3.65625 -4.234375 C 3.882812 -4.078125 4.050781 -3.84375 4.15625 -3.53125 Z M 4.15625 -3.53125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-16">
|
||||
<path style="stroke:none;" d="M 1.46875 -5.625 L 1.46875 -4.375 L 2.953125 -4.375 L 2.953125 -3.8125 L 1.46875 -3.8125 L 1.46875 -1.4375 C 1.46875 -1.082031 1.515625 -0.851562 1.609375 -0.75 C 1.710938 -0.65625 1.910156 -0.609375 2.203125 -0.609375 L 2.953125 -0.609375 L 2.953125 0 L 2.203125 0 C 1.648438 0 1.269531 -0.101562 1.0625 -0.3125 C 0.851562 -0.519531 0.75 -0.894531 0.75 -1.4375 L 0.75 -3.8125 L 0.21875 -3.8125 L 0.21875 -4.375 L 0.75 -4.375 L 0.75 -5.625 Z M 1.46875 -5.625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-17">
|
||||
<path style="stroke:none;" d="M 3.640625 -3.71875 L 3.640625 -6.078125 L 4.359375 -6.078125 L 4.359375 0 L 3.640625 0 L 3.640625 -0.65625 C 3.484375 -0.394531 3.289062 -0.203125 3.0625 -0.078125 C 2.832031 0.046875 2.554688 0.109375 2.234375 0.109375 C 1.703125 0.109375 1.269531 -0.0976562 0.9375 -0.515625 C 0.601562 -0.941406 0.4375 -1.5 0.4375 -2.1875 C 0.4375 -2.875 0.601562 -3.425781 0.9375 -3.84375 C 1.269531 -4.269531 1.703125 -4.484375 2.234375 -4.484375 C 2.554688 -4.484375 2.832031 -4.421875 3.0625 -4.296875 C 3.289062 -4.171875 3.484375 -3.976562 3.640625 -3.71875 Z M 1.1875 -2.1875 C 1.1875 -1.65625 1.296875 -1.238281 1.515625 -0.9375 C 1.734375 -0.632812 2.03125 -0.484375 2.40625 -0.484375 C 2.789062 -0.484375 3.09375 -0.632812 3.3125 -0.9375 C 3.53125 -1.238281 3.640625 -1.65625 3.640625 -2.1875 C 3.640625 -2.71875 3.53125 -3.128906 3.3125 -3.421875 C 3.09375 -3.722656 2.789062 -3.875 2.40625 -3.875 C 2.03125 -3.875 1.734375 -3.722656 1.515625 -3.421875 C 1.296875 -3.128906 1.1875 -2.71875 1.1875 -2.1875 Z M 1.1875 -2.1875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-18">
|
||||
<path style="stroke:none;" d="M 2.453125 -3.875 C 2.066406 -3.875 1.757812 -3.722656 1.53125 -3.421875 C 1.3125 -3.117188 1.203125 -2.707031 1.203125 -2.1875 C 1.203125 -1.664062 1.3125 -1.253906 1.53125 -0.953125 C 1.757812 -0.648438 2.066406 -0.5 2.453125 -0.5 C 2.835938 -0.5 3.140625 -0.648438 3.359375 -0.953125 C 3.585938 -1.253906 3.703125 -1.664062 3.703125 -2.1875 C 3.703125 -2.707031 3.585938 -3.117188 3.359375 -3.421875 C 3.140625 -3.722656 2.835938 -3.875 2.453125 -3.875 Z M 2.453125 -4.484375 C 3.078125 -4.484375 3.566406 -4.28125 3.921875 -3.875 C 4.273438 -3.46875 4.453125 -2.90625 4.453125 -2.1875 C 4.453125 -1.46875 4.273438 -0.90625 3.921875 -0.5 C 3.566406 -0.09375 3.078125 0.109375 2.453125 0.109375 C 1.828125 0.109375 1.332031 -0.09375 0.96875 -0.5 C 0.613281 -0.90625 0.4375 -1.46875 0.4375 -2.1875 C 0.4375 -2.90625 0.613281 -3.46875 0.96875 -3.875 C 1.332031 -4.28125 1.828125 -4.484375 2.453125 -4.484375 Z M 2.453125 -4.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-19">
|
||||
<path style="stroke:none;" d="M 0.640625 -6.078125 L 1.265625 -6.078125 C 1.660156 -5.460938 1.953125 -4.859375 2.140625 -4.265625 C 2.335938 -3.679688 2.4375 -3.097656 2.4375 -2.515625 C 2.4375 -1.929688 2.335938 -1.34375 2.140625 -0.75 C 1.953125 -0.15625 1.660156 0.445312 1.265625 1.0625 L 0.640625 1.0625 C 0.984375 0.457031 1.238281 -0.132812 1.40625 -0.71875 C 1.582031 -1.3125 1.671875 -1.910156 1.671875 -2.515625 C 1.671875 -3.117188 1.582031 -3.710938 1.40625 -4.296875 C 1.238281 -4.878906 0.984375 -5.472656 0.640625 -6.078125 Z M 0.640625 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-20">
|
||||
<path style="stroke:none;" d="M 3.890625 -2.1875 C 3.890625 -2.71875 3.78125 -3.128906 3.5625 -3.421875 C 3.351562 -3.722656 3.054688 -3.875 2.671875 -3.875 C 2.296875 -3.875 2 -3.722656 1.78125 -3.421875 C 1.5625 -3.128906 1.453125 -2.71875 1.453125 -2.1875 C 1.453125 -1.65625 1.5625 -1.238281 1.78125 -0.9375 C 2 -0.632812 2.296875 -0.484375 2.671875 -0.484375 C 3.054688 -0.484375 3.351562 -0.632812 3.5625 -0.9375 C 3.78125 -1.238281 3.890625 -1.65625 3.890625 -2.1875 Z M 1.453125 -3.71875 C 1.597656 -3.976562 1.785156 -4.171875 2.015625 -4.296875 C 2.253906 -4.421875 2.53125 -4.484375 2.84375 -4.484375 C 3.375 -4.484375 3.804688 -4.269531 4.140625 -3.84375 C 4.472656 -3.425781 4.640625 -2.875 4.640625 -2.1875 C 4.640625 -1.5 4.472656 -0.941406 4.140625 -0.515625 C 3.804688 -0.0976562 3.375 0.109375 2.84375 0.109375 C 2.53125 0.109375 2.253906 0.046875 2.015625 -0.078125 C 1.785156 -0.203125 1.597656 -0.394531 1.453125 -0.65625 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 Z M 1.453125 -3.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-21">
|
||||
<path style="stroke:none;" d="M 4.390625 -2.640625 L 4.390625 0 L 3.671875 0 L 3.671875 -2.625 C 3.671875 -3.03125 3.585938 -3.335938 3.421875 -3.546875 C 3.265625 -3.753906 3.023438 -3.859375 2.703125 -3.859375 C 2.316406 -3.859375 2.007812 -3.734375 1.78125 -3.484375 C 1.5625 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.285156 -4.414062 2.554688 -4.484375 2.859375 -4.484375 C 3.367188 -4.484375 3.75 -4.328125 4 -4.015625 C 4.257812 -3.703125 4.390625 -3.242188 4.390625 -2.640625 Z M 4.390625 -2.640625 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 1053.125 6 L 1121.109375 6 L 1121.109375 19 L 1053.125 19 Z M 1053.125 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip2">
|
||||
<path d="M 1149 6 L 1155.90625 6 L 1155.90625 19 L 1149 19 Z M 1149 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip3">
|
||||
<path d="M 506.714844 70 L 528 70 L 528 76 L 506.714844 76 Z M 506.714844 70 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip4">
|
||||
<path d="M 84.230469 37 L 102 37 L 102 45 L 84.230469 45 Z M 84.230469 37 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface2">
|
||||
<rect x="0" y="0" width="1280" height="120" style="fill:rgb(90%,90%,90%);fill-opacity:1;stroke:none;"/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 1051.125 4 L 1119.308594 4 L 1119.308594 100 L 1051.125 100 Z M 1051.125 4 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 1146.546875 4 L 1154.105469 4 L 1154.105469 100 L 1146.546875 100 Z M 1146.546875 4 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 4 0 L 4 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 234.425781 0 L 234.425781 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 464.851562 0 L 464.851562 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 695.28125 0 L 695.28125 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 925.707031 0 L 925.707031 120 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1156.132812 0 L 1156.132812 120 "/>
|
||||
<g style="fill:rgb(40%,40%,40%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="4" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-2" x="11.582031" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-3" x="18.935547" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-4" x="25.533203" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="33.138672" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-6" x="36.953125" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-7" x="44.570312" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="49.503906" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="52.837891" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="60.455078" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="64.269531" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="71.886719" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-10" x="75.220703" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="82.322266" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="85.65625" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="91.908203" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-12" x="95.242188" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-13" x="102.583984" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-14" x="110.189453" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="114.232422" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-15" x="118.046875" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-16" x="125.681641" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="133.316406" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-17" x="137.130859" y="115.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="144.736328" y="115.503906"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="1053.125" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="1059.376953" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="1066.982422" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="1073.234375" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="1080.851562" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1088.234375" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1095.839844" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="1103.457031" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1107.787109" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="1115.404297" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="1122.746094" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="1134.435547" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="1141.789062" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1145.123047" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#clip2)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="1148.546875" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="1154.798828" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="1162.404297" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="1168.65625" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="1176.273438" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1183.65625" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1191.261719" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="1198.878906" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1203.208984" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="1210.826172" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="1218.167969" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="1229.857422" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="1237.210938" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1240.544922" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 12.019531 46 L 22.988281 46 L 22.988281 60 L 12.019531 60 Z M 12.019531 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 22.988281 46 L 147.027344 46 L 147.027344 60 L 22.988281 60 Z M 22.988281 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 147.027344 46 L 791.160156 46 L 791.160156 60 L 147.027344 60 Z M 147.027344 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 791.160156 46 L 1007.484375 46 L 1007.484375 60 L 791.160156 60 Z M 791.160156 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1007.484375 46 L 1155.441406 46 L 1155.441406 60 L 1007.484375 60 Z M 1007.484375 46 "/>
|
||||
<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="1009.484375" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1017.101562" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1026.916016" y="58"/>
|
||||
<use xlink:href="#glyph0-24" x="1030.25" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="1034.955078" y="58"/>
|
||||
<use xlink:href="#glyph0-4" x="1041.552734" y="58"/>
|
||||
<use xlink:href="#glyph0-25" x="1049.158203" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1052.972656" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1060.326172" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1070.140625" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1077.494141" y="58"/>
|
||||
<use xlink:href="#glyph0-24" x="1080.828125" y="58"/>
|
||||
<use xlink:href="#glyph0-26" x="1085.533203" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1091.533203" y="58"/>
|
||||
<use xlink:href="#glyph0-9" x="1094.867188" y="58"/>
|
||||
<use xlink:href="#glyph0-27" x="1102.484375" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1105.818359" y="58"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1155.441406 46 L 1224.984375 46 L 1224.984375 60 L 1155.441406 60 Z M 1155.441406 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1224.984375 46 L 1276 46 L 1276 60 L 1224.984375 60 Z M 1224.984375 46 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="1226.984375" y="58"/>
|
||||
<use xlink:href="#glyph0-27" x="1233.582031" y="58"/>
|
||||
<use xlink:href="#glyph0-12" x="1236.916016" y="58"/>
|
||||
<use xlink:href="#glyph0-11" x="1244.257812" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1250.509766" y="58"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1276 46 L 1177.722656 46 L 1177.722656 60 L 1276 60 Z M 1276 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 147.027344 78 L 152.121094 78 L 152.121094 92 L 147.027344 92 Z M 147.027344 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 152.117188 78 L 335.929688 78 L 335.929688 92 L 152.117188 92 Z M 152.117188 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 335.929688 78 L 763.671875 78 L 763.671875 92 L 335.929688 92 Z M 335.929688 78 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-24" x="337.929688" y="90"/>
|
||||
<use xlink:href="#glyph0-7" x="342.634766" y="90"/>
|
||||
<use xlink:href="#glyph0-2" x="347.568359" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="354.921875" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="361.519531" y="90"/>
|
||||
<use xlink:href="#glyph0-27" x="368.902344" y="90"/>
|
||||
<use xlink:href="#glyph0-13" x="372.236328" y="90"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 763.667969 78 L 771.59375 78 L 771.59375 92 L 763.667969 92 Z M 763.667969 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 771.597656 78 L 1122.46875 78 L 1122.46875 92 L 771.597656 92 Z M 771.597656 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1122.46875 78 L 1155.441406 78 L 1155.441406 92 L 1122.46875 92 Z M 1122.46875 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1155.441406 78 L 1142.445312 78 L 1142.445312 92 L 1155.441406 92 Z M 1155.441406 78 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 504.714844 81 L 504.714844 75 "/>
|
||||
<g clip-path="url(#clip3)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="506.714844" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="511.449219" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="513.992188" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="520.695312" y="76"/>
|
||||
<use xlink:href="#glyph1-4" x="523.238281" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 147.027344 46 L 147.027344 92 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(80%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 992.34375 36 L 992.34375 100 "/>
|
||||
<g style="fill:rgb(80%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-5" x="994.34375" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="998.945312" y="44"/>
|
||||
<use xlink:href="#glyph1-7" x="1003.847656" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="1006.070312" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1008.292969" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1013.363281" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="1016.652344" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="1021.574219" y="44"/>
|
||||
<use xlink:href="#glyph1-13" x="1024.695312" y="44"/>
|
||||
<use xlink:href="#glyph1-14" x="1028.375" y="44"/>
|
||||
<use xlink:href="#glyph1-7" x="1033.453125" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="1035.675781" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1043.46875" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="1048.539062" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1050.761719" y="44"/>
|
||||
<use xlink:href="#glyph1-16" x="1055.664062" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="1058.800781" y="44"/>
|
||||
<use xlink:href="#glyph1-17" x="1063.722656" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1068.800781" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="1071.34375" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1076.265625" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1079.554688" y="44"/>
|
||||
<use xlink:href="#glyph1-18" x="1082.84375" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1087.738281" y="44"/>
|
||||
<use xlink:href="#glyph1-13" x="1091.027344" y="44"/>
|
||||
<use xlink:href="#glyph1-19" x="1094.707031" y="44"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 86.230469 36 L 82.230469 36 L 82.230469 96 L 86.230469 96 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1170.613281 36 L 1174.613281 36 L 1174.613281 96 L 1170.613281 96 "/>
|
||||
<g clip-path="url(#clip4)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-20" x="84.230469" y="44"/>
|
||||
<use xlink:href="#glyph1-18" x="89.308594" y="44"/>
|
||||
<use xlink:href="#glyph1-16" x="94.203125" y="44"/>
|
||||
<use xlink:href="#glyph1-21" x="97.339844" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 12.019531 46 L 12.019531 60 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 46 KiB |
BIN
doc/traces/multicore-posix.fxt
Normal file
BIN
doc/traces/multicore-posix.fxt
Normal file
Binary file not shown.
1490
doc/traces/multicore-posix.svg
Normal file
1490
doc/traces/multicore-posix.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 138 KiB |
BIN
doc/traces/net-posix.fxt
Normal file
BIN
doc/traces/net-posix.fxt
Normal file
Binary file not shown.
832
doc/traces/net-posix.svg
Normal file
832
doc/traces/net-posix.svg
Normal file
@ -0,0 +1,832 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1280pt" height="152pt" viewBox="0 0 1280 152" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d="M 0.59375 2.125 L 0.59375 -8.46875 L 6.59375 -8.46875 L 6.59375 2.125 Z M 1.265625 1.453125 L 5.9375 1.453125 L 5.9375 -7.78125 L 1.265625 -7.78125 Z M 1.265625 1.453125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 1.171875 -8.75 L 6.703125 -8.75 L 6.703125 -7.75 L 2.359375 -7.75 L 2.359375 -5.15625 L 6.53125 -5.15625 L 6.53125 -4.171875 L 2.359375 -4.171875 L 2.359375 -1 L 6.8125 -1 L 6.8125 0 L 1.171875 0 Z M 1.171875 -8.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 4.109375 -3.296875 C 3.242188 -3.296875 2.640625 -3.195312 2.296875 -3 C 1.960938 -2.800781 1.796875 -2.460938 1.796875 -1.984375 C 1.796875 -1.597656 1.921875 -1.289062 2.171875 -1.0625 C 2.429688 -0.84375 2.773438 -0.734375 3.203125 -0.734375 C 3.804688 -0.734375 4.285156 -0.941406 4.640625 -1.359375 C 5.003906 -1.785156 5.1875 -2.351562 5.1875 -3.0625 L 5.1875 -3.296875 Z M 6.265625 -3.75 L 6.265625 0 L 5.1875 0 L 5.1875 -1 C 4.9375 -0.601562 4.628906 -0.304688 4.265625 -0.109375 C 3.898438 0.078125 3.453125 0.171875 2.921875 0.171875 C 2.242188 0.171875 1.707031 -0.015625 1.3125 -0.390625 C 0.914062 -0.773438 0.71875 -1.28125 0.71875 -1.90625 C 0.71875 -2.644531 0.960938 -3.203125 1.453125 -3.578125 C 1.953125 -3.953125 2.691406 -4.140625 3.671875 -4.140625 L 5.1875 -4.140625 L 5.1875 -4.25 C 5.1875 -4.75 5.019531 -5.132812 4.6875 -5.40625 C 4.363281 -5.675781 3.910156 -5.8125 3.328125 -5.8125 C 2.953125 -5.8125 2.582031 -5.765625 2.21875 -5.671875 C 1.863281 -5.578125 1.523438 -5.441406 1.203125 -5.265625 L 1.203125 -6.265625 C 1.597656 -6.421875 1.976562 -6.535156 2.34375 -6.609375 C 2.71875 -6.679688 3.082031 -6.71875 3.4375 -6.71875 C 4.382812 -6.71875 5.09375 -6.472656 5.5625 -5.984375 C 6.03125 -5.492188 6.265625 -4.75 6.265625 -3.75 Z M 6.265625 -3.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 5.859375 -6.3125 L 5.859375 -5.296875 C 5.546875 -5.472656 5.238281 -5.601562 4.9375 -5.6875 C 4.632812 -5.769531 4.328125 -5.8125 4.015625 -5.8125 C 3.304688 -5.8125 2.757812 -5.585938 2.375 -5.140625 C 1.988281 -4.703125 1.796875 -4.082031 1.796875 -3.28125 C 1.796875 -2.476562 1.988281 -1.851562 2.375 -1.40625 C 2.757812 -0.96875 3.304688 -0.75 4.015625 -0.75 C 4.328125 -0.75 4.632812 -0.789062 4.9375 -0.875 C 5.238281 -0.957031 5.546875 -1.082031 5.859375 -1.25 L 5.859375 -0.25 C 5.554688 -0.113281 5.242188 -0.0078125 4.921875 0.0625 C 4.597656 0.132812 4.253906 0.171875 3.890625 0.171875 C 2.898438 0.171875 2.113281 -0.132812 1.53125 -0.75 C 0.945312 -1.375 0.65625 -2.21875 0.65625 -3.28125 C 0.65625 -4.34375 0.945312 -5.179688 1.53125 -5.796875 C 2.125 -6.410156 2.9375 -6.71875 3.96875 -6.71875 C 4.289062 -6.71875 4.609375 -6.679688 4.921875 -6.609375 C 5.242188 -6.546875 5.554688 -6.445312 5.859375 -6.3125 Z M 5.859375 -6.3125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -9.125 L 2.171875 -9.125 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 5.453125 -3.359375 C 5.453125 -4.140625 5.289062 -4.742188 4.96875 -5.171875 C 4.644531 -5.597656 4.191406 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.597656 2.265625 -5.171875 C 1.941406 -4.742188 1.78125 -4.140625 1.78125 -3.359375 C 1.78125 -2.578125 1.941406 -1.972656 2.265625 -1.546875 C 2.585938 -1.117188 3.035156 -0.90625 3.609375 -0.90625 C 4.191406 -0.90625 4.644531 -1.117188 4.96875 -1.546875 C 5.289062 -1.972656 5.453125 -2.578125 5.453125 -3.359375 Z M 6.53125 -0.8125 C 6.53125 0.300781 6.28125 1.128906 5.78125 1.671875 C 5.289062 2.222656 4.53125 2.5 3.5 2.5 C 3.125 2.5 2.765625 2.46875 2.421875 2.40625 C 2.085938 2.351562 1.765625 2.269531 1.453125 2.15625 L 1.453125 1.109375 C 1.765625 1.273438 2.078125 1.398438 2.390625 1.484375 C 2.703125 1.566406 3.015625 1.609375 3.328125 1.609375 C 4.035156 1.609375 4.566406 1.421875 4.921875 1.046875 C 5.273438 0.679688 5.453125 0.125 5.453125 -0.625 L 5.453125 -1.15625 C 5.222656 -0.769531 4.9375 -0.476562 4.59375 -0.28125 C 4.25 -0.09375 3.832031 0 3.34375 0 C 2.539062 0 1.890625 -0.304688 1.390625 -0.921875 C 0.898438 -1.535156 0.65625 -2.347656 0.65625 -3.359375 C 0.65625 -4.367188 0.898438 -5.179688 1.390625 -5.796875 C 1.890625 -6.410156 2.539062 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.617188 4.59375 -6.421875 C 4.9375 -6.234375 5.222656 -5.945312 5.453125 -5.5625 L 5.453125 -6.5625 L 6.53125 -6.5625 Z M 6.53125 -0.8125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-7">
|
||||
<path style="stroke:none;" d="M 4.9375 -5.5625 C 4.8125 -5.625 4.675781 -5.671875 4.53125 -5.703125 C 4.394531 -5.742188 4.238281 -5.765625 4.0625 -5.765625 C 3.457031 -5.765625 2.988281 -5.566406 2.65625 -5.171875 C 2.332031 -4.773438 2.171875 -4.203125 2.171875 -3.453125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.398438 -5.941406 2.695312 -6.234375 3.0625 -6.421875 C 3.425781 -6.617188 3.867188 -6.71875 4.390625 -6.71875 C 4.460938 -6.71875 4.539062 -6.710938 4.625 -6.703125 C 4.71875 -6.691406 4.816406 -6.675781 4.921875 -6.65625 Z M 4.9375 -5.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-8">
|
||||
<path style="stroke:none;" d="M 1.125 -6.5625 L 2.203125 -6.5625 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 -7.75 L 1.125 -7.75 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-9">
|
||||
<path style="stroke:none;" d="M 5.453125 -5.5625 L 5.453125 -9.125 L 6.53125 -9.125 L 6.53125 0 L 5.453125 0 L 5.453125 -0.984375 C 5.222656 -0.597656 4.9375 -0.304688 4.59375 -0.109375 C 4.25 0.078125 3.832031 0.171875 3.34375 0.171875 C 2.550781 0.171875 1.90625 -0.144531 1.40625 -0.78125 C 0.90625 -1.414062 0.65625 -2.25 0.65625 -3.28125 C 0.65625 -4.3125 0.90625 -5.140625 1.40625 -5.765625 C 1.90625 -6.398438 2.550781 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.625 4.59375 -6.4375 C 4.9375 -6.25 5.222656 -5.957031 5.453125 -5.5625 Z M 1.78125 -3.28125 C 1.78125 -2.488281 1.941406 -1.863281 2.265625 -1.40625 C 2.585938 -0.957031 3.035156 -0.734375 3.609375 -0.734375 C 4.179688 -0.734375 4.628906 -0.957031 4.953125 -1.40625 C 5.285156 -1.863281 5.453125 -2.488281 5.453125 -3.28125 C 5.453125 -4.070312 5.285156 -4.691406 4.953125 -5.140625 C 4.628906 -5.585938 4.179688 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.585938 2.265625 -5.140625 C 1.941406 -4.691406 1.78125 -4.070312 1.78125 -3.28125 Z M 1.78125 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-10">
|
||||
<path style="stroke:none;" d="M 0.359375 -6.5625 L 1.5 -6.5625 L 3.546875 -1.0625 L 5.609375 -6.5625 L 6.75 -6.5625 L 4.28125 0 L 2.8125 0 Z M 0.359375 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-11">
|
||||
<path style="stroke:none;" d="M 5.3125 -6.375 L 5.3125 -5.34375 C 5.007812 -5.5 4.691406 -5.613281 4.359375 -5.6875 C 4.035156 -5.769531 3.695312 -5.8125 3.34375 -5.8125 C 2.8125 -5.8125 2.410156 -5.726562 2.140625 -5.5625 C 1.867188 -5.40625 1.734375 -5.160156 1.734375 -4.828125 C 1.734375 -4.578125 1.828125 -4.378906 2.015625 -4.234375 C 2.210938 -4.097656 2.601562 -3.96875 3.1875 -3.84375 L 3.546875 -3.75 C 4.316406 -3.59375 4.863281 -3.363281 5.1875 -3.0625 C 5.507812 -2.757812 5.671875 -2.34375 5.671875 -1.8125 C 5.671875 -1.195312 5.425781 -0.710938 4.9375 -0.359375 C 4.457031 -0.00390625 3.796875 0.171875 2.953125 0.171875 C 2.597656 0.171875 2.226562 0.132812 1.84375 0.0625 C 1.46875 0 1.070312 -0.0976562 0.65625 -0.234375 L 0.65625 -1.359375 C 1.050781 -1.148438 1.441406 -0.992188 1.828125 -0.890625 C 2.210938 -0.785156 2.597656 -0.734375 2.984375 -0.734375 C 3.484375 -0.734375 3.867188 -0.816406 4.140625 -0.984375 C 4.421875 -1.160156 4.5625 -1.410156 4.5625 -1.734375 C 4.5625 -2.023438 4.460938 -2.25 4.265625 -2.40625 C 4.066406 -2.5625 3.632812 -2.710938 2.96875 -2.859375 L 2.59375 -2.9375 C 1.925781 -3.082031 1.441406 -3.300781 1.140625 -3.59375 C 0.847656 -3.882812 0.703125 -4.28125 0.703125 -4.78125 C 0.703125 -5.40625 0.921875 -5.882812 1.359375 -6.21875 C 1.796875 -6.550781 2.414062 -6.71875 3.21875 -6.71875 C 3.613281 -6.71875 3.988281 -6.6875 4.34375 -6.625 C 4.695312 -6.570312 5.019531 -6.488281 5.3125 -6.375 Z M 5.3125 -6.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-12">
|
||||
<path style="stroke:none;" d="M 3.671875 -5.8125 C 3.097656 -5.8125 2.640625 -5.582031 2.296875 -5.125 C 1.960938 -4.675781 1.796875 -4.0625 1.796875 -3.28125 C 1.796875 -2.488281 1.960938 -1.867188 2.296875 -1.421875 C 2.628906 -0.972656 3.085938 -0.75 3.671875 -0.75 C 4.242188 -0.75 4.695312 -0.972656 5.03125 -1.421875 C 5.375 -1.878906 5.546875 -2.5 5.546875 -3.28125 C 5.546875 -4.050781 5.375 -4.664062 5.03125 -5.125 C 4.695312 -5.582031 4.242188 -5.8125 3.671875 -5.8125 Z M 3.671875 -6.71875 C 4.609375 -6.71875 5.34375 -6.410156 5.875 -5.796875 C 6.414062 -5.191406 6.6875 -4.351562 6.6875 -3.28125 C 6.6875 -2.207031 6.414062 -1.363281 5.875 -0.75 C 5.34375 -0.132812 4.609375 0.171875 3.671875 0.171875 C 2.734375 0.171875 1.992188 -0.132812 1.453125 -0.75 C 0.921875 -1.363281 0.65625 -2.207031 0.65625 -3.28125 C 0.65625 -4.351562 0.921875 -5.191406 1.453125 -5.796875 C 1.992188 -6.410156 2.734375 -6.71875 3.671875 -6.71875 Z M 3.671875 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-13">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-14">
|
||||
<path style="stroke:none;" d="M 1.40625 -1.484375 L 2.640625 -1.484375 L 2.640625 0 L 1.40625 0 Z M 1.40625 -6.203125 L 2.640625 -6.203125 L 2.640625 -4.71875 L 1.40625 -4.71875 Z M 1.40625 -6.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-15">
|
||||
<path style="stroke:none;" d="M 1.484375 -1 L 3.421875 -1 L 3.421875 -7.671875 L 1.3125 -7.25 L 1.3125 -8.328125 L 3.40625 -8.75 L 4.59375 -8.75 L 4.59375 -1 L 6.53125 -1 L 6.53125 0 L 1.484375 0 Z M 1.484375 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-16">
|
||||
<path style="stroke:none;" d="M 3.8125 -7.96875 C 3.207031 -7.96875 2.75 -7.664062 2.4375 -7.0625 C 2.132812 -6.46875 1.984375 -5.566406 1.984375 -4.359375 C 1.984375 -3.160156 2.132812 -2.257812 2.4375 -1.65625 C 2.75 -1.0625 3.207031 -0.765625 3.8125 -0.765625 C 4.425781 -0.765625 4.882812 -1.0625 5.1875 -1.65625 C 5.5 -2.257812 5.65625 -3.160156 5.65625 -4.359375 C 5.65625 -5.566406 5.5 -6.46875 5.1875 -7.0625 C 4.882812 -7.664062 4.425781 -7.96875 3.8125 -7.96875 Z M 3.8125 -8.90625 C 4.789062 -8.90625 5.539062 -8.515625 6.0625 -7.734375 C 6.582031 -6.960938 6.84375 -5.835938 6.84375 -4.359375 C 6.84375 -2.890625 6.582031 -1.765625 6.0625 -0.984375 C 5.539062 -0.210938 4.789062 0.171875 3.8125 0.171875 C 2.832031 0.171875 2.082031 -0.210938 1.5625 -0.984375 C 1.050781 -1.765625 0.796875 -2.890625 0.796875 -4.359375 C 0.796875 -5.835938 1.050781 -6.960938 1.5625 -7.734375 C 2.082031 -8.515625 2.832031 -8.90625 3.8125 -8.90625 Z M 3.8125 -8.90625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-17">
|
||||
<path style="stroke:none;" d="M 1.015625 -2.59375 L 1.015625 -6.5625 L 2.09375 -6.5625 L 2.09375 -2.625 C 2.09375 -2.007812 2.210938 -1.546875 2.453125 -1.234375 C 2.703125 -0.921875 3.066406 -0.765625 3.546875 -0.765625 C 4.128906 -0.765625 4.585938 -0.945312 4.921875 -1.3125 C 5.265625 -1.6875 5.4375 -2.195312 5.4375 -2.84375 L 5.4375 -6.5625 L 6.515625 -6.5625 L 6.515625 0 L 5.4375 0 L 5.4375 -1.015625 C 5.175781 -0.609375 4.875 -0.304688 4.53125 -0.109375 C 4.1875 0.078125 3.785156 0.171875 3.328125 0.171875 C 2.566406 0.171875 1.988281 -0.0625 1.59375 -0.53125 C 1.207031 -1 1.015625 -1.6875 1.015625 -2.59375 Z M 3.734375 -6.71875 Z M 3.734375 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-18">
|
||||
<path style="stroke:none;" d="M 2.171875 -0.984375 L 2.171875 2.5 L 1.09375 2.5 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.5625 C 2.398438 -5.957031 2.6875 -6.25 3.03125 -6.4375 C 3.375 -6.625 3.785156 -6.71875 4.265625 -6.71875 C 5.066406 -6.71875 5.71875 -6.398438 6.21875 -5.765625 C 6.71875 -5.140625 6.96875 -4.3125 6.96875 -3.28125 C 6.96875 -2.25 6.71875 -1.414062 6.21875 -0.78125 C 5.71875 -0.144531 5.066406 0.171875 4.265625 0.171875 C 3.785156 0.171875 3.375 0.078125 3.03125 -0.109375 C 2.6875 -0.304688 2.398438 -0.597656 2.171875 -0.984375 Z M 5.84375 -3.28125 C 5.84375 -4.070312 5.675781 -4.691406 5.34375 -5.140625 C 5.019531 -5.585938 4.578125 -5.8125 4.015625 -5.8125 C 3.441406 -5.8125 2.988281 -5.585938 2.65625 -5.140625 C 2.332031 -4.691406 2.171875 -4.070312 2.171875 -3.28125 C 2.171875 -2.488281 2.332031 -1.863281 2.65625 -1.40625 C 2.988281 -0.957031 3.441406 -0.734375 4.015625 -0.734375 C 4.578125 -0.734375 5.019531 -0.957031 5.34375 -1.40625 C 5.675781 -1.863281 5.84375 -2.488281 5.84375 -3.28125 Z M 5.84375 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-19">
|
||||
<path style="stroke:none;" d="M 6.75 -3.546875 L 6.75 -3.03125 L 1.78125 -3.03125 C 1.832031 -2.28125 2.054688 -1.710938 2.453125 -1.328125 C 2.859375 -0.941406 3.414062 -0.75 4.125 -0.75 C 4.539062 -0.75 4.941406 -0.796875 5.328125 -0.890625 C 5.722656 -0.992188 6.113281 -1.148438 6.5 -1.359375 L 6.5 -0.328125 C 6.101562 -0.171875 5.703125 -0.0507812 5.296875 0.03125 C 4.890625 0.125 4.476562 0.171875 4.0625 0.171875 C 3.019531 0.171875 2.191406 -0.128906 1.578125 -0.734375 C 0.960938 -1.347656 0.65625 -2.175781 0.65625 -3.21875 C 0.65625 -4.289062 0.945312 -5.140625 1.53125 -5.765625 C 2.113281 -6.398438 2.894531 -6.71875 3.875 -6.71875 C 4.757812 -6.71875 5.457031 -6.429688 5.96875 -5.859375 C 6.488281 -5.296875 6.75 -4.523438 6.75 -3.546875 Z M 5.671875 -3.875 C 5.660156 -4.457031 5.492188 -4.925781 5.171875 -5.28125 C 4.847656 -5.632812 4.421875 -5.8125 3.890625 -5.8125 C 3.285156 -5.8125 2.800781 -5.640625 2.4375 -5.296875 C 2.082031 -4.953125 1.878906 -4.472656 1.828125 -3.859375 Z M 5.671875 -3.875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-20">
|
||||
<path style="stroke:none;" d="M 0.59375 -3.765625 L 3.75 -3.765625 L 3.75 -2.8125 L 0.59375 -2.8125 Z M 0.59375 -3.765625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-21">
|
||||
<path style="stroke:none;" d="M 6.234375 -5.296875 C 6.503906 -5.785156 6.828125 -6.144531 7.203125 -6.375 C 7.578125 -6.601562 8.019531 -6.71875 8.53125 -6.71875 C 9.21875 -6.71875 9.742188 -6.476562 10.109375 -6 C 10.484375 -5.519531 10.671875 -4.84375 10.671875 -3.96875 L 10.671875 0 L 9.59375 0 L 9.59375 -3.921875 C 9.59375 -4.554688 9.476562 -5.023438 9.25 -5.328125 C 9.03125 -5.628906 8.691406 -5.78125 8.234375 -5.78125 C 7.671875 -5.78125 7.226562 -5.59375 6.90625 -5.21875 C 6.582031 -4.851562 6.421875 -4.347656 6.421875 -3.703125 L 6.421875 0 L 5.34375 0 L 5.34375 -3.921875 C 5.34375 -4.554688 5.226562 -5.023438 5 -5.328125 C 4.78125 -5.628906 4.4375 -5.78125 3.96875 -5.78125 C 3.414062 -5.78125 2.976562 -5.59375 2.65625 -5.21875 C 2.332031 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.421875 -5.941406 2.71875 -6.234375 3.0625 -6.421875 C 3.40625 -6.617188 3.8125 -6.71875 4.28125 -6.71875 C 4.757812 -6.71875 5.164062 -6.597656 5.5 -6.359375 C 5.832031 -6.117188 6.078125 -5.765625 6.234375 -5.296875 Z M 6.234375 -5.296875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-22">
|
||||
<path style="stroke:none;" d="M 2.203125 -8.421875 L 2.203125 -6.5625 L 4.421875 -6.5625 L 4.421875 -5.71875 L 2.203125 -5.71875 L 2.203125 -2.15625 C 2.203125 -1.625 2.273438 -1.28125 2.421875 -1.125 C 2.566406 -0.976562 2.863281 -0.90625 3.3125 -0.90625 L 4.421875 -0.90625 L 4.421875 0 L 3.3125 0 C 2.476562 0 1.898438 -0.15625 1.578125 -0.46875 C 1.265625 -0.78125 1.109375 -1.34375 1.109375 -2.15625 L 1.109375 -5.71875 L 0.328125 -5.71875 L 0.328125 -6.5625 L 1.109375 -6.5625 L 1.109375 -8.421875 Z M 2.203125 -8.421875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-23">
|
||||
<path style="stroke:none;" d="M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-24">
|
||||
<path style="stroke:none;" d="M 6.421875 -8.46875 L 6.421875 -7.3125 C 5.972656 -7.519531 5.546875 -7.675781 5.140625 -7.78125 C 4.742188 -7.894531 4.363281 -7.953125 4 -7.953125 C 3.351562 -7.953125 2.851562 -7.828125 2.5 -7.578125 C 2.15625 -7.328125 1.984375 -6.96875 1.984375 -6.5 C 1.984375 -6.113281 2.097656 -5.820312 2.328125 -5.625 C 2.554688 -5.425781 3 -5.269531 3.65625 -5.15625 L 4.359375 -5 C 5.242188 -4.832031 5.894531 -4.535156 6.3125 -4.109375 C 6.738281 -3.691406 6.953125 -3.128906 6.953125 -2.421875 C 6.953125 -1.566406 6.664062 -0.921875 6.09375 -0.484375 C 5.53125 -0.046875 4.695312 0.171875 3.59375 0.171875 C 3.1875 0.171875 2.75 0.125 2.28125 0.03125 C 1.8125 -0.0625 1.328125 -0.203125 0.828125 -0.390625 L 0.828125 -1.609375 C 1.304688 -1.335938 1.773438 -1.132812 2.234375 -1 C 2.703125 -0.863281 3.15625 -0.796875 3.59375 -0.796875 C 4.269531 -0.796875 4.789062 -0.925781 5.15625 -1.1875 C 5.53125 -1.457031 5.71875 -1.835938 5.71875 -2.328125 C 5.71875 -2.753906 5.582031 -3.085938 5.3125 -3.328125 C 5.050781 -3.578125 4.617188 -3.757812 4.015625 -3.875 L 3.296875 -4.015625 C 2.410156 -4.191406 1.769531 -4.46875 1.375 -4.84375 C 0.988281 -5.21875 0.796875 -5.738281 0.796875 -6.40625 C 0.796875 -7.1875 1.066406 -7.796875 1.609375 -8.234375 C 2.148438 -8.679688 2.898438 -8.90625 3.859375 -8.90625 C 4.273438 -8.90625 4.691406 -8.867188 5.109375 -8.796875 C 5.535156 -8.722656 5.972656 -8.613281 6.421875 -8.46875 Z M 6.421875 -8.46875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-25">
|
||||
<path style="stroke:none;" d="M 0.5 -6.5625 L 1.578125 -6.5625 L 2.9375 -1.4375 L 4.265625 -6.5625 L 5.546875 -6.5625 L 6.890625 -1.4375 L 8.234375 -6.5625 L 9.3125 -6.5625 L 7.59375 0 L 6.328125 0 L 4.90625 -5.375 L 3.5 0 L 2.21875 0 Z M 0.5 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-26">
|
||||
<path style="stroke:none;" d="M 1.28125 -1.484375 L 2.515625 -1.484375 L 2.515625 0 L 1.28125 0 Z M 1.28125 -1.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-27">
|
||||
<path style="stroke:none;" d="M 6.125 2 L 6.125 2.828125 L -0.125 2.828125 L -0.125 2 Z M 6.125 2 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-0">
|
||||
<path style="stroke:none;" d="M 0.40625 1.421875 L 0.40625 -5.640625 L 4.40625 -5.640625 L 4.40625 1.421875 Z M 0.84375 0.96875 L 3.953125 0.96875 L 3.953125 -5.1875 L 0.84375 -5.1875 Z M 0.84375 0.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-1">
|
||||
<path style="stroke:none;" d="M 4.28125 -5.640625 L 4.28125 -4.875 C 3.976562 -5.019531 3.691406 -5.125 3.421875 -5.1875 C 3.160156 -5.257812 2.910156 -5.296875 2.671875 -5.296875 C 2.234375 -5.296875 1.898438 -5.210938 1.671875 -5.046875 C 1.441406 -4.878906 1.328125 -4.644531 1.328125 -4.34375 C 1.328125 -4.082031 1.398438 -3.882812 1.546875 -3.75 C 1.703125 -3.625 2 -3.519531 2.4375 -3.4375 L 2.90625 -3.34375 C 3.5 -3.226562 3.9375 -3.03125 4.21875 -2.75 C 4.5 -2.46875 4.640625 -2.085938 4.640625 -1.609375 C 4.640625 -1.046875 4.445312 -0.617188 4.0625 -0.328125 C 3.6875 -0.0351562 3.132812 0.109375 2.40625 0.109375 C 2.125 0.109375 1.828125 0.078125 1.515625 0.015625 C 1.203125 -0.046875 0.878906 -0.140625 0.546875 -0.265625 L 0.546875 -1.078125 C 0.867188 -0.890625 1.179688 -0.75 1.484375 -0.65625 C 1.796875 -0.570312 2.101562 -0.53125 2.40625 -0.53125 C 2.851562 -0.53125 3.195312 -0.617188 3.4375 -0.796875 C 3.6875 -0.972656 3.8125 -1.222656 3.8125 -1.546875 C 3.8125 -1.835938 3.722656 -2.0625 3.546875 -2.21875 C 3.367188 -2.382812 3.082031 -2.507812 2.6875 -2.59375 L 2.203125 -2.6875 C 1.609375 -2.800781 1.179688 -2.984375 0.921875 -3.234375 C 0.660156 -3.484375 0.53125 -3.832031 0.53125 -4.28125 C 0.53125 -4.789062 0.710938 -5.191406 1.078125 -5.484375 C 1.441406 -5.785156 1.941406 -5.9375 2.578125 -5.9375 C 2.847656 -5.9375 3.125 -5.910156 3.40625 -5.859375 C 3.695312 -5.816406 3.988281 -5.742188 4.28125 -5.640625 Z M 4.28125 -5.640625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-2">
|
||||
<path style="stroke:none;" d="M 4.5 -2.375 L 4.5 -2.015625 L 1.1875 -2.015625 C 1.21875 -1.523438 1.367188 -1.148438 1.640625 -0.890625 C 1.910156 -0.628906 2.28125 -0.5 2.75 -0.5 C 3.03125 -0.5 3.300781 -0.53125 3.5625 -0.59375 C 3.820312 -0.664062 4.078125 -0.769531 4.328125 -0.90625 L 4.328125 -0.21875 C 4.066406 -0.113281 3.800781 -0.0351562 3.53125 0.015625 C 3.257812 0.078125 2.988281 0.109375 2.71875 0.109375 C 2.019531 0.109375 1.460938 -0.09375 1.046875 -0.5 C 0.640625 -0.90625 0.4375 -1.453125 0.4375 -2.140625 C 0.4375 -2.859375 0.628906 -3.425781 1.015625 -3.84375 C 1.410156 -4.269531 1.9375 -4.484375 2.59375 -4.484375 C 3.175781 -4.484375 3.640625 -4.289062 3.984375 -3.90625 C 4.328125 -3.53125 4.5 -3.019531 4.5 -2.375 Z M 3.78125 -2.578125 C 3.769531 -2.972656 3.65625 -3.285156 3.4375 -3.515625 C 3.226562 -3.753906 2.945312 -3.875 2.59375 -3.875 C 2.195312 -3.875 1.875 -3.757812 1.625 -3.53125 C 1.382812 -3.300781 1.25 -2.984375 1.21875 -2.578125 Z M 3.78125 -2.578125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-3">
|
||||
<path style="stroke:none;" d="M 3.296875 -3.703125 C 3.210938 -3.753906 3.125 -3.789062 3.03125 -3.8125 C 2.9375 -3.832031 2.832031 -3.84375 2.71875 -3.84375 C 2.3125 -3.84375 2 -3.707031 1.78125 -3.4375 C 1.5625 -3.175781 1.453125 -2.800781 1.453125 -2.3125 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.597656 -3.960938 1.789062 -4.15625 2.03125 -4.28125 C 2.28125 -4.414062 2.578125 -4.484375 2.921875 -4.484375 C 2.972656 -4.484375 3.023438 -4.476562 3.078125 -4.46875 C 3.140625 -4.46875 3.207031 -4.457031 3.28125 -4.4375 Z M 3.296875 -3.703125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-4">
|
||||
<path style="stroke:none;" d="M 0.234375 -4.375 L 1 -4.375 L 2.375 -0.703125 L 3.734375 -4.375 L 4.5 -4.375 L 2.859375 0 L 1.875 0 Z M 0.234375 -4.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-5">
|
||||
<path style="stroke:none;" d="M 0.9375 -1 L 1.765625 -1 L 1.765625 0 L 0.9375 0 Z M 0.9375 -4.140625 L 1.765625 -4.140625 L 1.765625 -3.140625 L 0.9375 -3.140625 Z M 0.9375 -4.140625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-6">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-7">
|
||||
<path style="stroke:none;" d="M 3.640625 -2.234375 C 3.640625 -2.753906 3.53125 -3.15625 3.3125 -3.4375 C 3.09375 -3.726562 2.789062 -3.875 2.40625 -3.875 C 2.019531 -3.875 1.71875 -3.726562 1.5 -3.4375 C 1.289062 -3.15625 1.1875 -2.753906 1.1875 -2.234375 C 1.1875 -1.722656 1.289062 -1.320312 1.5 -1.03125 C 1.71875 -0.75 2.019531 -0.609375 2.40625 -0.609375 C 2.789062 -0.609375 3.09375 -0.75 3.3125 -1.03125 C 3.53125 -1.320312 3.640625 -1.722656 3.640625 -2.234375 Z M 4.359375 -0.546875 C 4.359375 0.203125 4.191406 0.757812 3.859375 1.125 C 3.523438 1.488281 3.019531 1.671875 2.34375 1.671875 C 2.082031 1.671875 1.835938 1.648438 1.609375 1.609375 C 1.390625 1.566406 1.175781 1.507812 0.96875 1.4375 L 0.96875 0.734375 C 1.175781 0.847656 1.382812 0.929688 1.59375 0.984375 C 1.800781 1.046875 2.007812 1.078125 2.21875 1.078125 C 2.695312 1.078125 3.050781 0.953125 3.28125 0.703125 C 3.519531 0.453125 3.640625 0.078125 3.640625 -0.421875 L 3.640625 -0.765625 C 3.484375 -0.515625 3.289062 -0.320312 3.0625 -0.1875 C 2.832031 -0.0625 2.554688 0 2.234375 0 C 1.691406 0 1.253906 -0.203125 0.921875 -0.609375 C 0.597656 -1.023438 0.4375 -1.566406 0.4375 -2.234375 C 0.4375 -2.910156 0.597656 -3.453125 0.921875 -3.859375 C 1.253906 -4.273438 1.691406 -4.484375 2.234375 -4.484375 C 2.554688 -4.484375 2.832031 -4.414062 3.0625 -4.28125 C 3.289062 -4.15625 3.484375 -3.96875 3.640625 -3.71875 L 3.640625 -4.375 L 4.359375 -4.375 Z M 4.359375 -0.546875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-8">
|
||||
<path style="stroke:none;" d="M 2.453125 -3.875 C 2.066406 -3.875 1.757812 -3.722656 1.53125 -3.421875 C 1.3125 -3.117188 1.203125 -2.707031 1.203125 -2.1875 C 1.203125 -1.664062 1.3125 -1.253906 1.53125 -0.953125 C 1.757812 -0.648438 2.066406 -0.5 2.453125 -0.5 C 2.835938 -0.5 3.140625 -0.648438 3.359375 -0.953125 C 3.585938 -1.253906 3.703125 -1.664062 3.703125 -2.1875 C 3.703125 -2.707031 3.585938 -3.117188 3.359375 -3.421875 C 3.140625 -3.722656 2.835938 -3.875 2.453125 -3.875 Z M 2.453125 -4.484375 C 3.078125 -4.484375 3.566406 -4.28125 3.921875 -3.875 C 4.273438 -3.46875 4.453125 -2.90625 4.453125 -2.1875 C 4.453125 -1.46875 4.273438 -0.90625 3.921875 -0.5 C 3.566406 -0.09375 3.078125 0.109375 2.453125 0.109375 C 1.828125 0.109375 1.332031 -0.09375 0.96875 -0.5 C 0.613281 -0.90625 0.4375 -1.46875 0.4375 -2.1875 C 0.4375 -2.90625 0.613281 -3.46875 0.96875 -3.875 C 1.332031 -4.28125 1.828125 -4.484375 2.453125 -4.484375 Z M 2.453125 -4.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-9">
|
||||
<path style="stroke:none;" d="M 1.46875 -5.625 L 1.46875 -4.375 L 2.953125 -4.375 L 2.953125 -3.8125 L 1.46875 -3.8125 L 1.46875 -1.4375 C 1.46875 -1.082031 1.515625 -0.851562 1.609375 -0.75 C 1.710938 -0.65625 1.910156 -0.609375 2.203125 -0.609375 L 2.953125 -0.609375 L 2.953125 0 L 2.203125 0 C 1.648438 0 1.269531 -0.101562 1.0625 -0.3125 C 0.851562 -0.519531 0.75 -0.894531 0.75 -1.4375 L 0.75 -3.8125 L 0.21875 -3.8125 L 0.21875 -4.375 L 0.75 -4.375 L 0.75 -5.625 Z M 1.46875 -5.625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-10">
|
||||
<path style="stroke:none;" d="M 3.90625 -4.203125 L 3.90625 -3.53125 C 3.695312 -3.644531 3.488281 -3.726562 3.28125 -3.78125 C 3.082031 -3.84375 2.878906 -3.875 2.671875 -3.875 C 2.203125 -3.875 1.835938 -3.722656 1.578125 -3.421875 C 1.328125 -3.128906 1.203125 -2.71875 1.203125 -2.1875 C 1.203125 -1.65625 1.328125 -1.238281 1.578125 -0.9375 C 1.835938 -0.644531 2.203125 -0.5 2.671875 -0.5 C 2.878906 -0.5 3.082031 -0.523438 3.28125 -0.578125 C 3.488281 -0.640625 3.695312 -0.722656 3.90625 -0.828125 L 3.90625 -0.171875 C 3.707031 -0.078125 3.5 -0.0078125 3.28125 0.03125 C 3.0625 0.0820312 2.832031 0.109375 2.59375 0.109375 C 1.9375 0.109375 1.410156 -0.09375 1.015625 -0.5 C 0.628906 -0.914062 0.4375 -1.476562 0.4375 -2.1875 C 0.4375 -2.894531 0.632812 -3.453125 1.03125 -3.859375 C 1.425781 -4.273438 1.960938 -4.484375 2.640625 -4.484375 C 2.859375 -4.484375 3.070312 -4.457031 3.28125 -4.40625 C 3.5 -4.363281 3.707031 -4.296875 3.90625 -4.203125 Z M 3.90625 -4.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-11">
|
||||
<path style="stroke:none;" d="M 4.390625 -2.640625 L 4.390625 0 L 3.671875 0 L 3.671875 -2.625 C 3.671875 -3.03125 3.585938 -3.335938 3.421875 -3.546875 C 3.265625 -3.753906 3.023438 -3.859375 2.703125 -3.859375 C 2.316406 -3.859375 2.007812 -3.734375 1.78125 -3.484375 C 1.5625 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.285156 -4.414062 2.554688 -4.484375 2.859375 -4.484375 C 3.367188 -4.484375 3.75 -4.328125 4 -4.015625 C 4.257812 -3.703125 4.390625 -3.242188 4.390625 -2.640625 Z M 4.390625 -2.640625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-12">
|
||||
<path style="stroke:none;" d="M 0.75 -4.375 L 1.46875 -4.375 L 1.46875 0 L 0.75 0 Z M 0.75 -6.078125 L 1.46875 -6.078125 L 1.46875 -5.171875 L 0.75 -5.171875 Z M 0.75 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-13">
|
||||
<path style="stroke:none;" d="M 2.96875 -6.078125 L 2.96875 -5.484375 L 2.28125 -5.484375 C 2.019531 -5.484375 1.835938 -5.429688 1.734375 -5.328125 C 1.640625 -5.222656 1.59375 -5.035156 1.59375 -4.765625 L 1.59375 -4.375 L 2.78125 -4.375 L 2.78125 -3.8125 L 1.59375 -3.8125 L 1.59375 0 L 0.875 0 L 0.875 -3.8125 L 0.1875 -3.8125 L 0.1875 -4.375 L 0.875 -4.375 L 0.875 -4.6875 C 0.875 -5.164062 0.984375 -5.515625 1.203125 -5.734375 C 1.429688 -5.960938 1.796875 -6.078125 2.296875 -6.078125 Z M 2.96875 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-14">
|
||||
<path style="stroke:none;" d="M 4.15625 -3.53125 C 4.34375 -3.851562 4.5625 -4.09375 4.8125 -4.25 C 5.0625 -4.40625 5.351562 -4.484375 5.6875 -4.484375 C 6.144531 -4.484375 6.492188 -4.320312 6.734375 -4 C 6.984375 -3.6875 7.109375 -3.234375 7.109375 -2.640625 L 7.109375 0 L 6.390625 0 L 6.390625 -2.625 C 6.390625 -3.039062 6.316406 -3.347656 6.171875 -3.546875 C 6.023438 -3.753906 5.796875 -3.859375 5.484375 -3.859375 C 5.117188 -3.859375 4.828125 -3.734375 4.609375 -3.484375 C 4.390625 -3.234375 4.28125 -2.894531 4.28125 -2.46875 L 4.28125 0 L 3.5625 0 L 3.5625 -2.625 C 3.5625 -3.039062 3.484375 -3.347656 3.328125 -3.546875 C 3.179688 -3.753906 2.957031 -3.859375 2.65625 -3.859375 C 2.28125 -3.859375 1.984375 -3.734375 1.765625 -3.484375 C 1.554688 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.273438 -4.414062 2.546875 -4.484375 2.859375 -4.484375 C 3.171875 -4.484375 3.4375 -4.398438 3.65625 -4.234375 C 3.882812 -4.078125 4.050781 -3.84375 4.15625 -3.53125 Z M 4.15625 -3.53125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-15">
|
||||
<path style="stroke:none;" d="M 0.75 -6.078125 L 1.46875 -6.078125 L 1.46875 0 L 0.75 0 Z M 0.75 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-16">
|
||||
<path style="stroke:none;" d="M 3.640625 -3.71875 L 3.640625 -6.078125 L 4.359375 -6.078125 L 4.359375 0 L 3.640625 0 L 3.640625 -0.65625 C 3.484375 -0.394531 3.289062 -0.203125 3.0625 -0.078125 C 2.832031 0.046875 2.554688 0.109375 2.234375 0.109375 C 1.703125 0.109375 1.269531 -0.0976562 0.9375 -0.515625 C 0.601562 -0.941406 0.4375 -1.5 0.4375 -2.1875 C 0.4375 -2.875 0.601562 -3.425781 0.9375 -3.84375 C 1.269531 -4.269531 1.703125 -4.484375 2.234375 -4.484375 C 2.554688 -4.484375 2.832031 -4.421875 3.0625 -4.296875 C 3.289062 -4.171875 3.484375 -3.976562 3.640625 -3.71875 Z M 1.1875 -2.1875 C 1.1875 -1.65625 1.296875 -1.238281 1.515625 -0.9375 C 1.734375 -0.632812 2.03125 -0.484375 2.40625 -0.484375 C 2.789062 -0.484375 3.09375 -0.632812 3.3125 -0.9375 C 3.53125 -1.238281 3.640625 -1.65625 3.640625 -2.1875 C 3.640625 -2.71875 3.53125 -3.128906 3.3125 -3.421875 C 3.09375 -3.722656 2.789062 -3.875 2.40625 -3.875 C 2.03125 -3.875 1.734375 -3.722656 1.515625 -3.421875 C 1.296875 -3.128906 1.1875 -2.71875 1.1875 -2.1875 Z M 1.1875 -2.1875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-17">
|
||||
<path style="stroke:none;" d="M 3.890625 -2.1875 C 3.890625 -2.71875 3.78125 -3.128906 3.5625 -3.421875 C 3.351562 -3.722656 3.054688 -3.875 2.671875 -3.875 C 2.296875 -3.875 2 -3.722656 1.78125 -3.421875 C 1.5625 -3.128906 1.453125 -2.71875 1.453125 -2.1875 C 1.453125 -1.65625 1.5625 -1.238281 1.78125 -0.9375 C 2 -0.632812 2.296875 -0.484375 2.671875 -0.484375 C 3.054688 -0.484375 3.351562 -0.632812 3.5625 -0.9375 C 3.78125 -1.238281 3.890625 -1.65625 3.890625 -2.1875 Z M 1.453125 -3.71875 C 1.597656 -3.976562 1.785156 -4.171875 2.015625 -4.296875 C 2.253906 -4.421875 2.53125 -4.484375 2.84375 -4.484375 C 3.375 -4.484375 3.804688 -4.269531 4.140625 -3.84375 C 4.472656 -3.425781 4.640625 -2.875 4.640625 -2.1875 C 4.640625 -1.5 4.472656 -0.941406 4.140625 -0.515625 C 3.804688 -0.0976562 3.375 0.109375 2.84375 0.109375 C 2.53125 0.109375 2.253906 0.046875 2.015625 -0.078125 C 1.785156 -0.203125 1.597656 -0.394531 1.453125 -0.65625 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 Z M 1.453125 -3.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-18">
|
||||
<path style="stroke:none;" d="M 0.859375 -1 L 1.6875 -1 L 1.6875 0 L 0.859375 0 Z M 0.859375 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-19">
|
||||
<path style="stroke:none;" d="M 0.78125 -5.828125 L 4.46875 -5.828125 L 4.46875 -5.171875 L 1.578125 -5.171875 L 1.578125 -3.4375 L 4.359375 -3.4375 L 4.359375 -2.78125 L 1.578125 -2.78125 L 1.578125 -0.671875 L 4.546875 -0.671875 L 4.546875 0 L 0.78125 0 Z M 0.78125 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-20">
|
||||
<path style="stroke:none;" d="M 4.390625 -4.375 L 2.8125 -2.25 L 4.46875 0 L 3.625 0 L 2.359375 -1.71875 L 1.078125 0 L 0.234375 0 L 1.9375 -2.296875 L 0.375 -4.375 L 1.21875 -4.375 L 2.390625 -2.8125 L 3.546875 -4.375 Z M 4.390625 -4.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-21">
|
||||
<path style="stroke:none;" d="M 0.6875 -1.734375 L 0.6875 -4.375 L 1.40625 -4.375 L 1.40625 -1.75 C 1.40625 -1.34375 1.484375 -1.035156 1.640625 -0.828125 C 1.804688 -0.617188 2.050781 -0.515625 2.375 -0.515625 C 2.757812 -0.515625 3.0625 -0.632812 3.28125 -0.875 C 3.507812 -1.125 3.625 -1.460938 3.625 -1.890625 L 3.625 -4.375 L 4.34375 -4.375 L 4.34375 0 L 3.625 0 L 3.625 -0.671875 C 3.445312 -0.410156 3.242188 -0.210938 3.015625 -0.078125 C 2.785156 0.046875 2.519531 0.109375 2.21875 0.109375 C 1.71875 0.109375 1.335938 -0.046875 1.078125 -0.359375 C 0.816406 -0.671875 0.6875 -1.128906 0.6875 -1.734375 Z M 2.484375 -4.484375 Z M 2.484375 -4.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-22">
|
||||
<path style="stroke:none;" d="M 4.078125 1.328125 L 4.078125 1.890625 L -0.078125 1.890625 L -0.078125 1.328125 Z M 4.078125 1.328125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-23">
|
||||
<path style="stroke:none;" d="M 3.546875 -4.25 L 3.546875 -3.5625 C 3.335938 -3.664062 3.125 -3.742188 2.90625 -3.796875 C 2.6875 -3.847656 2.460938 -3.875 2.234375 -3.875 C 1.878906 -3.875 1.609375 -3.816406 1.421875 -3.703125 C 1.242188 -3.597656 1.15625 -3.4375 1.15625 -3.21875 C 1.15625 -3.050781 1.21875 -2.921875 1.34375 -2.828125 C 1.476562 -2.734375 1.738281 -2.644531 2.125 -2.5625 L 2.375 -2.5 C 2.882812 -2.394531 3.242188 -2.242188 3.453125 -2.046875 C 3.671875 -1.847656 3.78125 -1.566406 3.78125 -1.203125 C 3.78125 -0.796875 3.617188 -0.472656 3.296875 -0.234375 C 2.972656 -0.00390625 2.53125 0.109375 1.96875 0.109375 C 1.738281 0.109375 1.492188 0.0820312 1.234375 0.03125 C 0.984375 -0.0078125 0.71875 -0.0703125 0.4375 -0.15625 L 0.4375 -0.90625 C 0.695312 -0.769531 0.957031 -0.664062 1.21875 -0.59375 C 1.476562 -0.519531 1.734375 -0.484375 1.984375 -0.484375 C 2.328125 -0.484375 2.585938 -0.539062 2.765625 -0.65625 C 2.953125 -0.78125 3.046875 -0.945312 3.046875 -1.15625 C 3.046875 -1.351562 2.976562 -1.503906 2.84375 -1.609375 C 2.707031 -1.710938 2.421875 -1.8125 1.984375 -1.90625 L 1.734375 -1.96875 C 1.285156 -2.0625 0.960938 -2.203125 0.765625 -2.390625 C 0.566406 -2.585938 0.46875 -2.851562 0.46875 -3.1875 C 0.46875 -3.601562 0.613281 -3.921875 0.90625 -4.140625 C 1.195312 -4.367188 1.609375 -4.484375 2.140625 -4.484375 C 2.410156 -4.484375 2.660156 -4.460938 2.890625 -4.421875 C 3.128906 -4.378906 3.347656 -4.320312 3.546875 -4.25 Z M 3.546875 -4.25 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-24">
|
||||
<path style="stroke:none;" d="M 5.15625 -5.390625 L 5.15625 -4.546875 C 4.882812 -4.796875 4.597656 -4.984375 4.296875 -5.109375 C 4.003906 -5.234375 3.6875 -5.296875 3.34375 -5.296875 C 2.675781 -5.296875 2.164062 -5.085938 1.8125 -4.671875 C 1.457031 -4.265625 1.28125 -3.675781 1.28125 -2.90625 C 1.28125 -2.144531 1.457031 -1.554688 1.8125 -1.140625 C 2.164062 -0.734375 2.675781 -0.53125 3.34375 -0.53125 C 3.6875 -0.53125 4.003906 -0.59375 4.296875 -0.71875 C 4.597656 -0.84375 4.882812 -1.03125 5.15625 -1.28125 L 5.15625 -0.453125 C 4.875 -0.265625 4.578125 -0.125 4.265625 -0.03125 C 3.960938 0.0625 3.640625 0.109375 3.296875 0.109375 C 2.410156 0.109375 1.710938 -0.160156 1.203125 -0.703125 C 0.703125 -1.242188 0.453125 -1.976562 0.453125 -2.90625 C 0.453125 -3.84375 0.703125 -4.582031 1.203125 -5.125 C 1.710938 -5.664062 2.410156 -5.9375 3.296875 -5.9375 C 3.648438 -5.9375 3.976562 -5.890625 4.28125 -5.796875 C 4.59375 -5.703125 4.882812 -5.566406 5.15625 -5.390625 Z M 5.15625 -5.390625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-25">
|
||||
<path style="stroke:none;" d="M 1.4375 -5.828125 L 1.4375 -3.671875 L 0.765625 -3.671875 L 0.765625 -5.828125 Z M 2.90625 -5.828125 L 2.90625 -3.671875 L 2.25 -3.671875 L 2.25 -5.828125 Z M 2.90625 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-26">
|
||||
<path style="stroke:none;" d="M 0.78125 -5.828125 L 1.578125 -5.828125 L 1.578125 -3.4375 L 4.4375 -3.4375 L 4.4375 -5.828125 L 5.234375 -5.828125 L 5.234375 0 L 4.4375 0 L 4.4375 -2.78125 L 1.578125 -2.78125 L 1.578125 0 L 0.78125 0 Z M 0.78125 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-27">
|
||||
<path style="stroke:none;" d="M 1.453125 -0.65625 L 1.453125 1.671875 L 0.734375 1.671875 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.71875 C 1.597656 -3.976562 1.785156 -4.171875 2.015625 -4.296875 C 2.253906 -4.421875 2.53125 -4.484375 2.84375 -4.484375 C 3.375 -4.484375 3.804688 -4.269531 4.140625 -3.84375 C 4.472656 -3.425781 4.640625 -2.875 4.640625 -2.1875 C 4.640625 -1.5 4.472656 -0.941406 4.140625 -0.515625 C 3.804688 -0.0976562 3.375 0.109375 2.84375 0.109375 C 2.53125 0.109375 2.253906 0.046875 2.015625 -0.078125 C 1.785156 -0.203125 1.597656 -0.394531 1.453125 -0.65625 Z M 3.890625 -2.1875 C 3.890625 -2.71875 3.78125 -3.128906 3.5625 -3.421875 C 3.351562 -3.722656 3.054688 -3.875 2.671875 -3.875 C 2.296875 -3.875 2 -3.722656 1.78125 -3.421875 C 1.5625 -3.128906 1.453125 -2.71875 1.453125 -2.1875 C 1.453125 -1.65625 1.5625 -1.238281 1.78125 -0.9375 C 2 -0.632812 2.296875 -0.484375 2.671875 -0.484375 C 3.054688 -0.484375 3.351562 -0.632812 3.5625 -0.9375 C 3.78125 -1.238281 3.890625 -1.65625 3.890625 -2.1875 Z M 3.890625 -2.1875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-28">
|
||||
<path style="stroke:none;" d="M 2.75 -2.203125 C 2.164062 -2.203125 1.757812 -2.132812 1.53125 -2 C 1.3125 -1.863281 1.203125 -1.640625 1.203125 -1.328125 C 1.203125 -1.066406 1.285156 -0.859375 1.453125 -0.703125 C 1.617188 -0.554688 1.847656 -0.484375 2.140625 -0.484375 C 2.535156 -0.484375 2.851562 -0.625 3.09375 -0.90625 C 3.332031 -1.195312 3.453125 -1.578125 3.453125 -2.046875 L 3.453125 -2.203125 Z M 4.171875 -2.5 L 4.171875 0 L 3.453125 0 L 3.453125 -0.671875 C 3.296875 -0.398438 3.09375 -0.203125 2.84375 -0.078125 C 2.601562 0.046875 2.304688 0.109375 1.953125 0.109375 C 1.503906 0.109375 1.144531 -0.015625 0.875 -0.265625 C 0.613281 -0.515625 0.484375 -0.851562 0.484375 -1.28125 C 0.484375 -1.769531 0.644531 -2.140625 0.96875 -2.390625 C 1.300781 -2.640625 1.796875 -2.765625 2.453125 -2.765625 L 3.453125 -2.765625 L 3.453125 -2.828125 C 3.453125 -3.160156 3.34375 -3.414062 3.125 -3.59375 C 2.914062 -3.78125 2.613281 -3.875 2.21875 -3.875 C 1.96875 -3.875 1.722656 -3.84375 1.484375 -3.78125 C 1.242188 -3.71875 1.015625 -3.628906 0.796875 -3.515625 L 0.796875 -4.171875 C 1.066406 -4.273438 1.320312 -4.351562 1.5625 -4.40625 C 1.8125 -4.457031 2.054688 -4.484375 2.296875 -4.484375 C 2.921875 -4.484375 3.390625 -4.316406 3.703125 -3.984375 C 4.015625 -3.660156 4.171875 -3.164062 4.171875 -2.5 Z M 4.171875 -2.5 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 588.042969 6 L 597.65625 6 L 597.65625 19 L 588.042969 19 Z M 588.042969 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip2">
|
||||
<path d="M 731 6 L 733.875 6 L 733.875 19 L 731 19 Z M 731 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip3">
|
||||
<path d="M 974.046875 6 L 978.160156 6 L 978.160156 19 L 974.046875 19 Z M 974.046875 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip4">
|
||||
<path d="M 1003.039062 6 L 1004.738281 6 L 1004.738281 19 L 1003.039062 19 Z M 1003.039062 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip5">
|
||||
<path d="M 1176 6 L 1179.425781 6 L 1179.425781 19 L 1176 19 Z M 1176 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip6">
|
||||
<path d="M 1198.246094 6 L 1229.460938 6 L 1229.460938 19 L 1198.246094 19 Z M 1198.246094 6 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip7">
|
||||
<path d="M 580.164062 49 L 628 49 L 628 59 L 580.164062 59 Z M 580.164062 49 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip8">
|
||||
<path d="M 980 48 L 996.039062 48 L 996.039062 59 L 980 59 Z M 980 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip9">
|
||||
<path d="M 1006 48 L 1006.328125 48 L 1006.328125 59 L 1006 59 Z M 1006 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip10">
|
||||
<path d="M 1016.539062 48 L 1058 48 L 1058 59 L 1016.539062 59 Z M 1016.539062 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip11">
|
||||
<path d="M 1067.246094 48 L 1098 48 L 1098 59 L 1067.246094 59 Z M 1067.246094 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip12">
|
||||
<path d="M 1174.039062 48 L 1228.273438 48 L 1228.273438 61 L 1174.039062 61 Z M 1174.039062 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip13">
|
||||
<path d="M 1236 48 L 1244.597656 48 L 1244.597656 59 L 1236 59 Z M 1236 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip14">
|
||||
<path d="M 1257 48 L 1262.09375 48 L 1262.09375 59 L 1257 59 Z M 1257 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip15">
|
||||
<path d="M 608 81 L 630.199219 81 L 630.199219 93 L 608 93 Z M 608 81 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip16">
|
||||
<path d="M 939.054688 81 L 968.039062 81 L 968.039062 93 L 939.054688 93 Z M 939.054688 81 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip17">
|
||||
<path d="M 970.039062 81 L 1011 81 L 1011 93 L 970.039062 93 Z M 970.039062 81 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip18">
|
||||
<path d="M 759.25 112 L 797 112 L 797 123 L 759.25 123 Z M 759.25 112 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip19">
|
||||
<path d="M 673.429688 101 L 811 101 L 811 110 L 673.429688 110 Z M 673.429688 101 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip20">
|
||||
<path d="M 1170 69 L 1193.144531 69 L 1193.144531 77 L 1170 77 Z M 1170 69 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip21">
|
||||
<path d="M 152.046875 71 L 195 71 L 195 78 L 152.046875 78 Z M 152.046875 71 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip22">
|
||||
<path d="M 199.238281 37 L 311 37 L 311 46 L 199.238281 46 Z M 199.238281 37 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip23">
|
||||
<path d="M 1030.417969 37 L 1062.695312 37 L 1062.695312 45 L 1030.417969 45 Z M 1030.417969 37 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip24">
|
||||
<path d="M 1168.152344 37 L 1209 37 L 1209 45 L 1168.152344 45 Z M 1168.152344 37 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip25">
|
||||
<path d="M 1234 38 L 1245.207031 38 L 1245.207031 46 L 1234 46 Z M 1234 38 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface2">
|
||||
<rect x="0" y="0" width="1280" height="152" style="fill:rgb(90%,90%,90%);fill-opacity:1;stroke:none;"/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 586.042969 4 L 595.855469 4 L 595.855469 132 L 586.042969 132 Z M 586.042969 4 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 728.445312 4 L 732.074219 4 L 732.074219 132 L 728.445312 132 Z M 728.445312 4 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 972.046875 4 L 976.359375 4 L 976.359375 132 L 972.046875 132 Z M 972.046875 4 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 1001.039062 4 L 1002.9375 4 L 1002.9375 132 L 1001.039062 132 Z M 1001.039062 4 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 1173.941406 4 L 1177.625 4 L 1177.625 132 L 1173.941406 132 Z M 1173.941406 4 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(90%,90%,45%);fill-opacity:1;" d="M 1196.246094 4 L 1227.660156 4 L 1227.660156 132 L 1196.246094 132 Z M 1196.246094 4 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 4 0 L 4 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 46.1875 0 L 46.1875 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 88.371094 0 L 88.371094 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 130.558594 0 L 130.558594 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 172.742188 0 L 172.742188 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 214.929688 0 L 214.929688 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 257.113281 0 L 257.113281 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.300781 0 L 299.300781 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 341.484375 0 L 341.484375 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 383.671875 0 L 383.671875 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 425.855469 0 L 425.855469 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 468.042969 0 L 468.042969 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 510.226562 0 L 510.226562 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 552.414062 0 L 552.414062 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 594.601562 0 L 594.601562 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 636.785156 0 L 636.785156 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 678.972656 0 L 678.972656 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 721.15625 0 L 721.15625 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 763.34375 0 L 763.34375 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 805.527344 0 L 805.527344 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 847.714844 0 L 847.714844 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 889.898438 0 L 889.898438 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 932.085938 0 L 932.085938 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 974.269531 0 L 974.269531 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1016.457031 0 L 1016.457031 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1058.640625 0 L 1058.640625 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1100.828125 0 L 1100.828125 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1143.015625 0 L 1143.015625 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1185.199219 0 L 1185.199219 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1227.386719 0 L 1227.386719 152 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1269.570312 0 L 1269.570312 152 "/>
|
||||
<g style="fill:rgb(40%,40%,40%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="4" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-2" x="11.582031" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-3" x="18.935547" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-4" x="25.533203" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="33.138672" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-6" x="36.953125" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-7" x="44.570312" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="49.503906" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="52.837891" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="60.455078" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="64.269531" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="71.886719" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-10" x="75.220703" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="82.322266" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="85.65625" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="91.908203" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-12" x="95.242188" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-13" x="102.583984" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-14" x="110.189453" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="114.232422" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-15" x="118.046875" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-16" x="125.681641" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="133.316406" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-17" x="137.130859" y="147.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="144.736328" y="147.503906"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="588.042969" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="594.294922" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="601.900391" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="608.152344" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="615.769531" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="623.152344" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="630.757812" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="638.375" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="642.705078" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="650.322266" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="657.664062" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="669.353516" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="676.707031" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="680.041016" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#clip2)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="730.445312" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="736.697266" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="744.302734" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="750.554688" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="758.171875" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="765.554688" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="773.160156" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="780.777344" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="785.107422" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="792.724609" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="800.066406" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="811.755859" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="819.109375" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="822.443359" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#clip3)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="974.046875" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="980.298828" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="987.904297" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="994.15625" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="1001.773438" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1009.15625" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1016.761719" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="1024.378906" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1028.708984" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="1036.326172" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="1043.667969" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="1055.357422" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="1062.710938" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1066.044922" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#clip4)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="1003.039062" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="1009.291016" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="1016.896484" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="1023.148438" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="1030.765625" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1038.148438" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1045.753906" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="1053.371094" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1057.701172" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="1065.318359" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="1072.660156" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="1084.349609" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="1091.703125" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1095.037109" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#clip5)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="1175.941406" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="1182.193359" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="1189.798828" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="1196.050781" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="1203.667969" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1211.050781" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1218.65625" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="1226.273438" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1230.603516" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="1238.220703" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="1245.5625" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="1257.251953" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="1264.605469" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1267.939453" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<g clip-path="url(#clip6)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-11" x="1198.246094" y="16"/>
|
||||
<use xlink:href="#glyph0-17" x="1204.498047" y="16"/>
|
||||
<use xlink:href="#glyph0-11" x="1212.103516" y="16"/>
|
||||
<use xlink:href="#glyph0-18" x="1218.355469" y="16"/>
|
||||
<use xlink:href="#glyph0-19" x="1225.972656" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1233.355469" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1240.960938" y="16"/>
|
||||
<use xlink:href="#glyph0-20" x="1248.578125" y="16"/>
|
||||
<use xlink:href="#glyph0-9" x="1252.908203" y="16"/>
|
||||
<use xlink:href="#glyph0-12" x="1260.525391" y="16"/>
|
||||
<use xlink:href="#glyph0-21" x="1267.867188" y="16"/>
|
||||
<use xlink:href="#glyph0-2" x="1279.556641" y="16"/>
|
||||
<use xlink:href="#glyph0-8" x="1286.910156" y="16"/>
|
||||
<use xlink:href="#glyph0-13" x="1290.244141" y="16"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 5.941406 46 L 13.273438 46 L 13.273438 60 L 5.941406 60 Z M 5.941406 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 13.273438 46 L 138.445312 46 L 138.445312 60 L 13.273438 60 Z M 13.273438 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 138.445312 46 L 169.574219 46 L 169.574219 60 L 138.445312 60 Z M 138.445312 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 169.574219 46 L 173.832031 46 L 173.832031 60 L 169.574219 60 Z M 169.574219 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 173.832031 46 L 252.480469 46 L 252.480469 60 L 173.832031 60 Z M 173.832031 46 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="175.832031" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="180.537109" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="185.470703" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="192.824219" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="199.421875" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="206.804688" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="210.138672" y="58"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 252.476562 46 L 578.164062 46 L 578.164062 60 L 252.476562 60 Z M 252.476562 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 578.164062 46 L 732.695312 46 L 732.695312 60 L 578.164062 60 Z M 578.164062 46 "/>
|
||||
<g clip-path="url(#clip7)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="580.164062" y="58"/>
|
||||
<use xlink:href="#glyph0-12" x="586.761719" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="594.103516" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="601.708984" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="609.314453" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="616.697266" y="58"/>
|
||||
<use xlink:href="#glyph0-22" x="623.294922" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 732.695312 46 L 755.976562 46 L 755.976562 60 L 732.695312 60 Z M 732.695312 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 755.976562 46 L 976.964844 46 L 976.964844 60 L 755.976562 60 Z M 755.976562 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 976.964844 46 L 977.816406 46 L 977.816406 60 L 976.964844 60 Z M 976.964844 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 977.820312 46 L 996.039062 46 L 996.039062 60 L 977.820312 60 Z M 977.820312 46 "/>
|
||||
<g clip-path="url(#clip8)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-7" x="979.820312" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="984.753906" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="992.136719" y="58"/>
|
||||
<use xlink:href="#glyph0-9" x="999.490234" y="58"/>
|
||||
<use xlink:href="#glyph0-10" x="1007.107422" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 996.039062 46 L 999.808594 46 L 999.808594 60 L 996.039062 60 Z M 996.039062 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 999.808594 46 L 1003.238281 46 L 1003.238281 60 L 999.808594 60 Z M 999.808594 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1003.238281 46 L 1003.773438 46 L 1003.773438 60 L 1003.238281 60 Z M 1003.238281 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1003.777344 46 L 1006.328125 46 L 1006.328125 60 L 1003.777344 60 Z M 1003.777344 46 "/>
|
||||
<g clip-path="url(#clip9)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-7" x="1005.777344" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1010.710938" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1018.09375" y="58"/>
|
||||
<use xlink:href="#glyph0-9" x="1025.447266" y="58"/>
|
||||
<use xlink:href="#glyph0-10" x="1033.064453" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1006.328125 46 L 1014.539062 46 L 1014.539062 60 L 1006.328125 60 Z M 1006.328125 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1014.539062 46 L 1058.179688 46 L 1058.179688 60 L 1014.539062 60 Z M 1014.539062 46 "/>
|
||||
<g clip-path="url(#clip10)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="1016.539062" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="1021.244141" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1026.177734" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="1033.53125" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1040.128906" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1047.511719" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="1050.845703" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1058.179688 46 L 1065.246094 46 L 1065.246094 60 L 1058.179688 60 Z M 1058.179688 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1065.246094 46 L 1156.160156 46 L 1156.160156 60 L 1065.246094 60 Z M 1065.246094 46 "/>
|
||||
<g clip-path="url(#clip11)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="1067.246094" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1073.84375" y="58"/>
|
||||
<use xlink:href="#glyph0-12" x="1077.177734" y="58"/>
|
||||
<use xlink:href="#glyph0-11" x="1084.519531" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1090.771484" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1156.160156 46 L 1172.039062 46 L 1172.039062 60 L 1156.160156 60 Z M 1156.160156 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1172.039062 46 L 1228.273438 46 L 1228.273438 60 L 1172.039062 60 Z M 1172.039062 46 "/>
|
||||
<g clip-path="url(#clip12)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-24" x="1174.039062" y="58"/>
|
||||
<use xlink:href="#glyph0-25" x="1181.65625" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1191.470703" y="58"/>
|
||||
<use xlink:href="#glyph0-22" x="1194.804688" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="1199.509766" y="58"/>
|
||||
<use xlink:href="#glyph0-4" x="1206.107422" y="58"/>
|
||||
<use xlink:href="#glyph0-26" x="1213.712891" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1217.527344" y="58"/>
|
||||
<use xlink:href="#glyph0-25" x="1224.880859" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1234.695312" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1242.048828" y="58"/>
|
||||
<use xlink:href="#glyph0-22" x="1245.382812" y="58"/>
|
||||
<use xlink:href="#glyph0-27" x="1250.087891" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1256.087891" y="58"/>
|
||||
<use xlink:href="#glyph0-9" x="1259.421875" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1267.039062" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1270.373047" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1228.269531 46 L 1233.5625 46 L 1233.5625 60 L 1228.269531 60 Z M 1228.269531 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1233.566406 46 L 1244.597656 46 L 1244.597656 60 L 1233.566406 60 Z M 1233.566406 46 "/>
|
||||
<g clip-path="url(#clip13)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="1235.566406" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1242.164062" y="58"/>
|
||||
<use xlink:href="#glyph0-12" x="1245.498047" y="58"/>
|
||||
<use xlink:href="#glyph0-11" x="1252.839844" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1259.091797" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1244.597656 46 L 1254.722656 46 L 1254.722656 60 L 1244.597656 60 Z M 1244.597656 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1254.722656 46 L 1262.09375 46 L 1262.09375 60 L 1254.722656 60 Z M 1254.722656 46 "/>
|
||||
<g clip-path="url(#clip14)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="1256.722656" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="1263.320312" y="58"/>
|
||||
<use xlink:href="#glyph0-12" x="1266.654297" y="58"/>
|
||||
<use xlink:href="#glyph0-11" x="1273.996094" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1280.248047" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1262.089844 46 L 1247.964844 46 L 1247.964844 60 L 1262.089844 60 Z M 1262.089844 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 138.445312 78 L 139.664062 78 L 139.664062 92 L 138.445312 92 Z M 138.445312 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 139.664062 78 L 166.859375 78 L 166.859375 92 L 139.664062 92 Z M 139.664062 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 166.863281 78 L 603.738281 78 L 603.738281 92 L 166.863281 92 Z M 166.863281 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 603.738281 78 L 605.601562 78 L 605.601562 92 L 603.738281 92 Z M 603.738281 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 605.601562 78 L 630.199219 78 L 630.199219 92 L 605.601562 92 Z M 605.601562 78 "/>
|
||||
<g clip-path="url(#clip15)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-2" x="607.601562" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="614.955078" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="621.552734" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="628.150391" y="90"/>
|
||||
<use xlink:href="#glyph0-18" x="635.533203" y="90"/>
|
||||
<use xlink:href="#glyph0-22" x="643.150391" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 630.199219 78 L 646.222656 78 L 646.222656 92 L 630.199219 92 Z M 630.199219 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 646.222656 78 L 723.402344 78 L 723.402344 92 L 646.222656 92 Z M 646.222656 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 723.402344 78 L 726.738281 78 L 726.738281 92 L 723.402344 92 Z M 723.402344 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 726.738281 78 L 935.714844 78 L 935.714844 92 L 726.738281 92 Z M 726.738281 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 935.714844 78 L 937.054688 78 L 937.054688 92 L 935.714844 92 Z M 935.714844 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 937.054688 78 L 968.039062 78 L 968.039062 92 L 937.054688 92 Z M 937.054688 78 "/>
|
||||
<g clip-path="url(#clip16)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-2" x="939.054688" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="946.408203" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="953.005859" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="959.603516" y="90"/>
|
||||
<use xlink:href="#glyph0-18" x="966.986328" y="90"/>
|
||||
<use xlink:href="#glyph0-22" x="974.603516" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 968.039062 78 L 1178.621094 78 L 1178.621094 92 L 968.039062 92 Z M 968.039062 78 "/>
|
||||
<g clip-path="url(#clip17)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-2" x="970.039062" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="977.392578" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="983.990234" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="990.587891" y="90"/>
|
||||
<use xlink:href="#glyph0-18" x="997.970703" y="90"/>
|
||||
<use xlink:href="#glyph0-22" x="1005.587891" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1178.621094 78 L 1179.300781 78 L 1179.300781 92 L 1178.621094 92 Z M 1178.621094 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1179.300781 78 L 1228.269531 78 L 1228.269531 92 L 1179.300781 92 Z M 1179.300781 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1228.269531 78 L 1195.445312 78 L 1195.445312 92 L 1228.269531 92 Z M 1228.269531 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 646.222656 110 L 647.367188 110 L 647.367188 124 L 646.222656 124 Z M 646.222656 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 647.367188 110 L 658.933594 110 L 658.933594 124 L 647.367188 124 Z M 647.367188 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 658.933594 110 L 703.359375 110 L 703.359375 124 L 658.933594 124 Z M 658.933594 110 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-22" x="660.933594" y="122"/>
|
||||
<use xlink:href="#glyph0-7" x="665.638672" y="122"/>
|
||||
<use xlink:href="#glyph0-2" x="670.572266" y="122"/>
|
||||
<use xlink:href="#glyph0-3" x="677.925781" y="122"/>
|
||||
<use xlink:href="#glyph0-19" x="684.523438" y="122"/>
|
||||
<use xlink:href="#glyph0-23" x="691.90625" y="122"/>
|
||||
<use xlink:href="#glyph0-13" x="695.240234" y="122"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 703.359375 110 L 721.449219 110 L 721.449219 124 L 703.359375 124 Z M 703.359375 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 721.449219 110 L 756.730469 110 L 756.730469 124 L 721.449219 124 Z M 721.449219 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 756.726562 110 L 757.25 110 L 757.25 124 L 756.726562 124 Z M 756.726562 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 757.25 110 L 828.3125 110 L 828.3125 124 L 757.25 124 Z M 757.25 110 "/>
|
||||
<g clip-path="url(#clip18)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-25" x="759.25" y="122"/>
|
||||
<use xlink:href="#glyph0-7" x="769.064453" y="122"/>
|
||||
<use xlink:href="#glyph0-8" x="773.998047" y="122"/>
|
||||
<use xlink:href="#glyph0-22" x="777.332031" y="122"/>
|
||||
<use xlink:href="#glyph0-19" x="782.037109" y="122"/>
|
||||
<use xlink:href="#glyph0-10" x="789.419922" y="122"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 828.3125 110 L 833.761719 110 L 833.761719 124 L 828.3125 124 Z M 828.3125 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 833.761719 110 L 931.601562 110 L 931.601562 124 L 833.761719 124 Z M 833.761719 110 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-3" x="835.761719" y="122"/>
|
||||
<use xlink:href="#glyph0-23" x="842.359375" y="122"/>
|
||||
<use xlink:href="#glyph0-12" x="845.693359" y="122"/>
|
||||
<use xlink:href="#glyph0-11" x="853.035156" y="122"/>
|
||||
<use xlink:href="#glyph0-19" x="859.287109" y="122"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 931.605469 110 L 935.714844 110 L 935.714844 124 L 931.605469 124 Z M 931.605469 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 935.714844 110 L 934.558594 110 L 934.558594 124 L 935.714844 124 Z M 935.714844 110 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 671.429688 113 L 671.429688 107 "/>
|
||||
<g clip-path="url(#clip19)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="673.429688" y="108"/>
|
||||
<use xlink:href="#glyph1-2" x="678.507812" y="108"/>
|
||||
<use xlink:href="#glyph1-3" x="683.429688" y="108"/>
|
||||
<use xlink:href="#glyph1-4" x="686.71875" y="108"/>
|
||||
<use xlink:href="#glyph1-2" x="691.453125" y="108"/>
|
||||
<use xlink:href="#glyph1-3" x="696.375" y="108"/>
|
||||
<use xlink:href="#glyph1-5" x="699.664062" y="108"/>
|
||||
<use xlink:href="#glyph1-6" x="702.359375" y="108"/>
|
||||
<use xlink:href="#glyph1-7" x="704.902344" y="108"/>
|
||||
<use xlink:href="#glyph1-8" x="709.980469" y="108"/>
|
||||
<use xlink:href="#glyph1-9" x="714.875" y="108"/>
|
||||
<use xlink:href="#glyph1-6" x="718.011719" y="108"/>
|
||||
<use xlink:href="#glyph1-10" x="720.554688" y="108"/>
|
||||
<use xlink:href="#glyph1-8" x="724.953125" y="108"/>
|
||||
<use xlink:href="#glyph1-11" x="729.847656" y="108"/>
|
||||
<use xlink:href="#glyph1-11" x="734.917969" y="108"/>
|
||||
<use xlink:href="#glyph1-2" x="739.988281" y="108"/>
|
||||
<use xlink:href="#glyph1-10" x="744.910156" y="108"/>
|
||||
<use xlink:href="#glyph1-9" x="749.308594" y="108"/>
|
||||
<use xlink:href="#glyph1-12" x="752.445312" y="108"/>
|
||||
<use xlink:href="#glyph1-8" x="754.667969" y="108"/>
|
||||
<use xlink:href="#glyph1-11" x="759.5625" y="108"/>
|
||||
<use xlink:href="#glyph1-6" x="764.632812" y="108"/>
|
||||
<use xlink:href="#glyph1-13" x="767.175781" y="108"/>
|
||||
<use xlink:href="#glyph1-3" x="769.992188" y="108"/>
|
||||
<use xlink:href="#glyph1-8" x="773.28125" y="108"/>
|
||||
<use xlink:href="#glyph1-14" x="778.175781" y="108"/>
|
||||
<use xlink:href="#glyph1-6" x="785.96875" y="108"/>
|
||||
<use xlink:href="#glyph1-10" x="788.511719" y="108"/>
|
||||
<use xlink:href="#glyph1-15" x="792.910156" y="108"/>
|
||||
<use xlink:href="#glyph1-12" x="795.132812" y="108"/>
|
||||
<use xlink:href="#glyph1-2" x="797.355469" y="108"/>
|
||||
<use xlink:href="#glyph1-11" x="802.277344" y="108"/>
|
||||
<use xlink:href="#glyph1-9" x="807.347656" y="108"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 646.222656 78 L 646.222656 124 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(80%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1167.78125 68 L 1167.78125 132 "/>
|
||||
<g clip-path="url(#clip20)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(80%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="1169.78125" y="76"/>
|
||||
<use xlink:href="#glyph1-9" x="1174.859375" y="76"/>
|
||||
<use xlink:href="#glyph1-16" x="1177.996094" y="76"/>
|
||||
<use xlink:href="#glyph1-15" x="1183.074219" y="76"/>
|
||||
<use xlink:href="#glyph1-12" x="1185.296875" y="76"/>
|
||||
<use xlink:href="#glyph1-17" x="1187.519531" y="76"/>
|
||||
<use xlink:href="#glyph1-18" x="1192.597656" y="76"/>
|
||||
<use xlink:href="#glyph1-19" x="1195.140625" y="76"/>
|
||||
<use xlink:href="#glyph1-20" x="1200.195312" y="76"/>
|
||||
<use xlink:href="#glyph1-12" x="1204.929688" y="76"/>
|
||||
<use xlink:href="#glyph1-9" x="1207.152344" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 154.046875 68 L 150.046875 68 L 150.046875 128 L 154.046875 128 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1189.144531 68 L 1193.144531 68 L 1193.144531 128 L 1189.144531 128 "/>
|
||||
<g clip-path="url(#clip21)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-3" x="152.046875" y="76"/>
|
||||
<use xlink:href="#glyph1-21" x="155.335938" y="76"/>
|
||||
<use xlink:href="#glyph1-11" x="160.40625" y="76"/>
|
||||
<use xlink:href="#glyph1-22" x="165.476562" y="76"/>
|
||||
<use xlink:href="#glyph1-23" x="169.476562" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="173.644531" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="178.566406" y="76"/>
|
||||
<use xlink:href="#glyph1-4" x="181.855469" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="186.589844" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="191.511719" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.445312 46 L 138.445312 92 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 197.238281 49 L 197.238281 43 "/>
|
||||
<g clip-path="url(#clip22)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-24" x="199.238281" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="204.824219" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="207.046875" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="209.269531" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="214.191406" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="219.261719" y="44"/>
|
||||
<use xlink:href="#glyph1-5" x="222.398438" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="225.09375" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="227.636719" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="232.035156" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="236.929688" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="242" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="247.070312" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="251.992188" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="256.390625" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="259.527344" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="261.75" y="44"/>
|
||||
<use xlink:href="#glyph1-7" x="266.820312" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="271.898438" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="274.441406" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="277.578125" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="282.472656" y="44"/>
|
||||
<use xlink:href="#glyph1-23" x="285.015625" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="289.183594" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="294.105469" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="297.394531" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="302.128906" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="307.050781" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1028.417969 49 L 1028.417969 43 "/>
|
||||
<g clip-path="url(#clip23)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-24" x="1030.417969" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="1036.003906" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="1038.226562" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1040.449219" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="1045.371094" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1050.441406" y="44"/>
|
||||
<use xlink:href="#glyph1-5" x="1053.578125" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1056.273438" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="1058.816406" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1062.105469" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1067.027344" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1071.425781" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="1076.347656" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="1078.570312" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1083.304688" y="44"/>
|
||||
<use xlink:href="#glyph1-16" x="1088.226562" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1093.304688" y="44"/>
|
||||
<use xlink:href="#glyph1-25" x="1095.847656" y="44"/>
|
||||
<use xlink:href="#glyph1-26" x="1099.527344" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1105.542969" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="1110.464844" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="1112.6875" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="1114.910156" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1119.804688" y="44"/>
|
||||
<use xlink:href="#glyph1-13" x="1122.347656" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="1125.164062" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="1128.453125" y="44"/>
|
||||
<use xlink:href="#glyph1-14" x="1133.347656" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1141.140625" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1066.691406 36 L 1062.691406 36 L 1062.691406 64 L 1066.691406 64 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1153.382812 36 L 1157.382812 36 L 1157.382812 64 L 1153.382812 64 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-27" x="1064.691406" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="1069.769531" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="1073.058594" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1077.953125" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1081.089844" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1086.011719" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1090.410156" y="44"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 174.824219 36 L 170.824219 36 L 170.824219 64 L 174.824219 64 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1154.925781 36 L 1158.925781 36 L 1158.925781 64 L 1154.925781 64 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-10" x="172.824219" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="177.222656" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="179.445312" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="181.667969" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="186.589844" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="191.660156" y="44"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(80%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1166.152344 36 L 1166.152344 132 "/>
|
||||
<g clip-path="url(#clip24)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(80%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="1168.152344" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1173.230469" y="44"/>
|
||||
<use xlink:href="#glyph1-16" x="1176.367188" y="44"/>
|
||||
<use xlink:href="#glyph1-15" x="1181.445312" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="1183.667969" y="44"/>
|
||||
<use xlink:href="#glyph1-17" x="1185.890625" y="44"/>
|
||||
<use xlink:href="#glyph1-18" x="1190.96875" y="44"/>
|
||||
<use xlink:href="#glyph1-19" x="1193.511719" y="44"/>
|
||||
<use xlink:href="#glyph1-20" x="1198.566406" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="1203.300781" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1205.523438" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1235.625 36 L 1231.625 36 L 1231.625 64 L 1235.625 64 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1241.207031 36 L 1245.207031 36 L 1245.207031 64 L 1241.207031 64 "/>
|
||||
<g clip-path="url(#clip25)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-27" x="1233.625" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="1238.703125" y="44"/>
|
||||
<use xlink:href="#glyph1-8" x="1241.992188" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1246.886719" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="1250.023438" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1254.945312" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="1259.34375" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 24.957031 36 L 20.957031 36 L 20.957031 128 L 24.957031 128 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1242.046875 36 L 1246.046875 36 L 1246.046875 128 L 1242.046875 128 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-14" x="22.957031" y="44"/>
|
||||
<use xlink:href="#glyph1-28" x="30.75" y="44"/>
|
||||
<use xlink:href="#glyph1-12" x="35.652344" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="37.875" y="44"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 5.941406 46 L 5.941406 60 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 84 KiB |
BIN
doc/traces/switch-mock.fxt
Normal file
BIN
doc/traces/switch-mock.fxt
Normal file
Binary file not shown.
530
doc/traces/switch-mock.svg
Normal file
530
doc/traces/switch-mock.svg
Normal file
@ -0,0 +1,530 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1280pt" height="184pt" viewBox="0 0 1280 184" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d="M 0.59375 2.125 L 0.59375 -8.46875 L 6.59375 -8.46875 L 6.59375 2.125 Z M 1.265625 1.453125 L 5.9375 1.453125 L 5.9375 -7.78125 L 1.265625 -7.78125 Z M 1.265625 1.453125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 1.171875 -8.75 L 6.703125 -8.75 L 6.703125 -7.75 L 2.359375 -7.75 L 2.359375 -5.15625 L 6.53125 -5.15625 L 6.53125 -4.171875 L 2.359375 -4.171875 L 2.359375 -1 L 6.8125 -1 L 6.8125 0 L 1.171875 0 Z M 1.171875 -8.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 4.109375 -3.296875 C 3.242188 -3.296875 2.640625 -3.195312 2.296875 -3 C 1.960938 -2.800781 1.796875 -2.460938 1.796875 -1.984375 C 1.796875 -1.597656 1.921875 -1.289062 2.171875 -1.0625 C 2.429688 -0.84375 2.773438 -0.734375 3.203125 -0.734375 C 3.804688 -0.734375 4.285156 -0.941406 4.640625 -1.359375 C 5.003906 -1.785156 5.1875 -2.351562 5.1875 -3.0625 L 5.1875 -3.296875 Z M 6.265625 -3.75 L 6.265625 0 L 5.1875 0 L 5.1875 -1 C 4.9375 -0.601562 4.628906 -0.304688 4.265625 -0.109375 C 3.898438 0.078125 3.453125 0.171875 2.921875 0.171875 C 2.242188 0.171875 1.707031 -0.015625 1.3125 -0.390625 C 0.914062 -0.773438 0.71875 -1.28125 0.71875 -1.90625 C 0.71875 -2.644531 0.960938 -3.203125 1.453125 -3.578125 C 1.953125 -3.953125 2.691406 -4.140625 3.671875 -4.140625 L 5.1875 -4.140625 L 5.1875 -4.25 C 5.1875 -4.75 5.019531 -5.132812 4.6875 -5.40625 C 4.363281 -5.675781 3.910156 -5.8125 3.328125 -5.8125 C 2.953125 -5.8125 2.582031 -5.765625 2.21875 -5.671875 C 1.863281 -5.578125 1.523438 -5.441406 1.203125 -5.265625 L 1.203125 -6.265625 C 1.597656 -6.421875 1.976562 -6.535156 2.34375 -6.609375 C 2.71875 -6.679688 3.082031 -6.71875 3.4375 -6.71875 C 4.382812 -6.71875 5.09375 -6.472656 5.5625 -5.984375 C 6.03125 -5.492188 6.265625 -4.75 6.265625 -3.75 Z M 6.265625 -3.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 5.859375 -6.3125 L 5.859375 -5.296875 C 5.546875 -5.472656 5.238281 -5.601562 4.9375 -5.6875 C 4.632812 -5.769531 4.328125 -5.8125 4.015625 -5.8125 C 3.304688 -5.8125 2.757812 -5.585938 2.375 -5.140625 C 1.988281 -4.703125 1.796875 -4.082031 1.796875 -3.28125 C 1.796875 -2.476562 1.988281 -1.851562 2.375 -1.40625 C 2.757812 -0.96875 3.304688 -0.75 4.015625 -0.75 C 4.328125 -0.75 4.632812 -0.789062 4.9375 -0.875 C 5.238281 -0.957031 5.546875 -1.082031 5.859375 -1.25 L 5.859375 -0.25 C 5.554688 -0.113281 5.242188 -0.0078125 4.921875 0.0625 C 4.597656 0.132812 4.253906 0.171875 3.890625 0.171875 C 2.898438 0.171875 2.113281 -0.132812 1.53125 -0.75 C 0.945312 -1.375 0.65625 -2.21875 0.65625 -3.28125 C 0.65625 -4.34375 0.945312 -5.179688 1.53125 -5.796875 C 2.125 -6.410156 2.9375 -6.71875 3.96875 -6.71875 C 4.289062 -6.71875 4.609375 -6.679688 4.921875 -6.609375 C 5.242188 -6.546875 5.554688 -6.445312 5.859375 -6.3125 Z M 5.859375 -6.3125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -9.125 L 2.171875 -9.125 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 5.453125 -3.359375 C 5.453125 -4.140625 5.289062 -4.742188 4.96875 -5.171875 C 4.644531 -5.597656 4.191406 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.597656 2.265625 -5.171875 C 1.941406 -4.742188 1.78125 -4.140625 1.78125 -3.359375 C 1.78125 -2.578125 1.941406 -1.972656 2.265625 -1.546875 C 2.585938 -1.117188 3.035156 -0.90625 3.609375 -0.90625 C 4.191406 -0.90625 4.644531 -1.117188 4.96875 -1.546875 C 5.289062 -1.972656 5.453125 -2.578125 5.453125 -3.359375 Z M 6.53125 -0.8125 C 6.53125 0.300781 6.28125 1.128906 5.78125 1.671875 C 5.289062 2.222656 4.53125 2.5 3.5 2.5 C 3.125 2.5 2.765625 2.46875 2.421875 2.40625 C 2.085938 2.351562 1.765625 2.269531 1.453125 2.15625 L 1.453125 1.109375 C 1.765625 1.273438 2.078125 1.398438 2.390625 1.484375 C 2.703125 1.566406 3.015625 1.609375 3.328125 1.609375 C 4.035156 1.609375 4.566406 1.421875 4.921875 1.046875 C 5.273438 0.679688 5.453125 0.125 5.453125 -0.625 L 5.453125 -1.15625 C 5.222656 -0.769531 4.9375 -0.476562 4.59375 -0.28125 C 4.25 -0.09375 3.832031 0 3.34375 0 C 2.539062 0 1.890625 -0.304688 1.390625 -0.921875 C 0.898438 -1.535156 0.65625 -2.347656 0.65625 -3.359375 C 0.65625 -4.367188 0.898438 -5.179688 1.390625 -5.796875 C 1.890625 -6.410156 2.539062 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.617188 4.59375 -6.421875 C 4.9375 -6.234375 5.222656 -5.945312 5.453125 -5.5625 L 5.453125 -6.5625 L 6.53125 -6.5625 Z M 6.53125 -0.8125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-7">
|
||||
<path style="stroke:none;" d="M 4.9375 -5.5625 C 4.8125 -5.625 4.675781 -5.671875 4.53125 -5.703125 C 4.394531 -5.742188 4.238281 -5.765625 4.0625 -5.765625 C 3.457031 -5.765625 2.988281 -5.566406 2.65625 -5.171875 C 2.332031 -4.773438 2.171875 -4.203125 2.171875 -3.453125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.398438 -5.941406 2.695312 -6.234375 3.0625 -6.421875 C 3.425781 -6.617188 3.867188 -6.71875 4.390625 -6.71875 C 4.460938 -6.71875 4.539062 -6.710938 4.625 -6.703125 C 4.71875 -6.691406 4.816406 -6.675781 4.921875 -6.65625 Z M 4.9375 -5.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-8">
|
||||
<path style="stroke:none;" d="M 1.125 -6.5625 L 2.203125 -6.5625 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 -7.75 L 1.125 -7.75 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-9">
|
||||
<path style="stroke:none;" d="M 5.453125 -5.5625 L 5.453125 -9.125 L 6.53125 -9.125 L 6.53125 0 L 5.453125 0 L 5.453125 -0.984375 C 5.222656 -0.597656 4.9375 -0.304688 4.59375 -0.109375 C 4.25 0.078125 3.832031 0.171875 3.34375 0.171875 C 2.550781 0.171875 1.90625 -0.144531 1.40625 -0.78125 C 0.90625 -1.414062 0.65625 -2.25 0.65625 -3.28125 C 0.65625 -4.3125 0.90625 -5.140625 1.40625 -5.765625 C 1.90625 -6.398438 2.550781 -6.71875 3.34375 -6.71875 C 3.832031 -6.71875 4.25 -6.625 4.59375 -6.4375 C 4.9375 -6.25 5.222656 -5.957031 5.453125 -5.5625 Z M 1.78125 -3.28125 C 1.78125 -2.488281 1.941406 -1.863281 2.265625 -1.40625 C 2.585938 -0.957031 3.035156 -0.734375 3.609375 -0.734375 C 4.179688 -0.734375 4.628906 -0.957031 4.953125 -1.40625 C 5.285156 -1.863281 5.453125 -2.488281 5.453125 -3.28125 C 5.453125 -4.070312 5.285156 -4.691406 4.953125 -5.140625 C 4.628906 -5.585938 4.179688 -5.8125 3.609375 -5.8125 C 3.035156 -5.8125 2.585938 -5.585938 2.265625 -5.140625 C 1.941406 -4.691406 1.78125 -4.070312 1.78125 -3.28125 Z M 1.78125 -3.28125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-10">
|
||||
<path style="stroke:none;" d="M 0.359375 -6.5625 L 1.5 -6.5625 L 3.546875 -1.0625 L 5.609375 -6.5625 L 6.75 -6.5625 L 4.28125 0 L 2.8125 0 Z M 0.359375 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-11">
|
||||
<path style="stroke:none;" d="M 5.3125 -6.375 L 5.3125 -5.34375 C 5.007812 -5.5 4.691406 -5.613281 4.359375 -5.6875 C 4.035156 -5.769531 3.695312 -5.8125 3.34375 -5.8125 C 2.8125 -5.8125 2.410156 -5.726562 2.140625 -5.5625 C 1.867188 -5.40625 1.734375 -5.160156 1.734375 -4.828125 C 1.734375 -4.578125 1.828125 -4.378906 2.015625 -4.234375 C 2.210938 -4.097656 2.601562 -3.96875 3.1875 -3.84375 L 3.546875 -3.75 C 4.316406 -3.59375 4.863281 -3.363281 5.1875 -3.0625 C 5.507812 -2.757812 5.671875 -2.34375 5.671875 -1.8125 C 5.671875 -1.195312 5.425781 -0.710938 4.9375 -0.359375 C 4.457031 -0.00390625 3.796875 0.171875 2.953125 0.171875 C 2.597656 0.171875 2.226562 0.132812 1.84375 0.0625 C 1.46875 0 1.070312 -0.0976562 0.65625 -0.234375 L 0.65625 -1.359375 C 1.050781 -1.148438 1.441406 -0.992188 1.828125 -0.890625 C 2.210938 -0.785156 2.597656 -0.734375 2.984375 -0.734375 C 3.484375 -0.734375 3.867188 -0.816406 4.140625 -0.984375 C 4.421875 -1.160156 4.5625 -1.410156 4.5625 -1.734375 C 4.5625 -2.023438 4.460938 -2.25 4.265625 -2.40625 C 4.066406 -2.5625 3.632812 -2.710938 2.96875 -2.859375 L 2.59375 -2.9375 C 1.925781 -3.082031 1.441406 -3.300781 1.140625 -3.59375 C 0.847656 -3.882812 0.703125 -4.28125 0.703125 -4.78125 C 0.703125 -5.40625 0.921875 -5.882812 1.359375 -6.21875 C 1.796875 -6.550781 2.414062 -6.71875 3.21875 -6.71875 C 3.613281 -6.71875 3.988281 -6.6875 4.34375 -6.625 C 4.695312 -6.570312 5.019531 -6.488281 5.3125 -6.375 Z M 5.3125 -6.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-12">
|
||||
<path style="stroke:none;" d="M 3.671875 -5.8125 C 3.097656 -5.8125 2.640625 -5.582031 2.296875 -5.125 C 1.960938 -4.675781 1.796875 -4.0625 1.796875 -3.28125 C 1.796875 -2.488281 1.960938 -1.867188 2.296875 -1.421875 C 2.628906 -0.972656 3.085938 -0.75 3.671875 -0.75 C 4.242188 -0.75 4.695312 -0.972656 5.03125 -1.421875 C 5.375 -1.878906 5.546875 -2.5 5.546875 -3.28125 C 5.546875 -4.050781 5.375 -4.664062 5.03125 -5.125 C 4.695312 -5.582031 4.242188 -5.8125 3.671875 -5.8125 Z M 3.671875 -6.71875 C 4.609375 -6.71875 5.34375 -6.410156 5.875 -5.796875 C 6.414062 -5.191406 6.6875 -4.351562 6.6875 -3.28125 C 6.6875 -2.207031 6.414062 -1.363281 5.875 -0.75 C 5.34375 -0.132812 4.609375 0.171875 3.671875 0.171875 C 2.734375 0.171875 1.992188 -0.132812 1.453125 -0.75 C 0.921875 -1.363281 0.65625 -2.207031 0.65625 -3.28125 C 0.65625 -4.351562 0.921875 -5.191406 1.453125 -5.796875 C 1.992188 -6.410156 2.734375 -6.71875 3.671875 -6.71875 Z M 3.671875 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-13">
|
||||
<path style="stroke:none;" d="M 6.59375 -3.96875 L 6.59375 0 L 5.515625 0 L 5.515625 -3.921875 C 5.515625 -4.546875 5.390625 -5.007812 5.140625 -5.3125 C 4.898438 -5.625 4.539062 -5.78125 4.0625 -5.78125 C 3.476562 -5.78125 3.015625 -5.59375 2.671875 -5.21875 C 2.335938 -4.851562 2.171875 -4.347656 2.171875 -3.703125 L 2.171875 0 L 1.09375 0 L 1.09375 -6.5625 L 2.171875 -6.5625 L 2.171875 -5.546875 C 2.429688 -5.941406 2.734375 -6.234375 3.078125 -6.421875 C 3.429688 -6.617188 3.835938 -6.71875 4.296875 -6.71875 C 5.046875 -6.71875 5.613281 -6.484375 6 -6.015625 C 6.394531 -5.554688 6.59375 -4.875 6.59375 -3.96875 Z M 6.59375 -3.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-14">
|
||||
<path style="stroke:none;" d="M 1.40625 -1.484375 L 2.640625 -1.484375 L 2.640625 0 L 1.40625 0 Z M 1.40625 -6.203125 L 2.640625 -6.203125 L 2.640625 -4.71875 L 1.40625 -4.71875 Z M 1.40625 -6.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-15">
|
||||
<path style="stroke:none;" d="M 1.484375 -1 L 3.421875 -1 L 3.421875 -7.671875 L 1.3125 -7.25 L 1.3125 -8.328125 L 3.40625 -8.75 L 4.59375 -8.75 L 4.59375 -1 L 6.53125 -1 L 6.53125 0 L 1.484375 0 Z M 1.484375 -1 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-16">
|
||||
<path style="stroke:none;" d="M 3.8125 -7.96875 C 3.207031 -7.96875 2.75 -7.664062 2.4375 -7.0625 C 2.132812 -6.46875 1.984375 -5.566406 1.984375 -4.359375 C 1.984375 -3.160156 2.132812 -2.257812 2.4375 -1.65625 C 2.75 -1.0625 3.207031 -0.765625 3.8125 -0.765625 C 4.425781 -0.765625 4.882812 -1.0625 5.1875 -1.65625 C 5.5 -2.257812 5.65625 -3.160156 5.65625 -4.359375 C 5.65625 -5.566406 5.5 -6.46875 5.1875 -7.0625 C 4.882812 -7.664062 4.425781 -7.96875 3.8125 -7.96875 Z M 3.8125 -8.90625 C 4.789062 -8.90625 5.539062 -8.515625 6.0625 -7.734375 C 6.582031 -6.960938 6.84375 -5.835938 6.84375 -4.359375 C 6.84375 -2.890625 6.582031 -1.765625 6.0625 -0.984375 C 5.539062 -0.210938 4.789062 0.171875 3.8125 0.171875 C 2.832031 0.171875 2.082031 -0.210938 1.5625 -0.984375 C 1.050781 -1.765625 0.796875 -2.890625 0.796875 -4.359375 C 0.796875 -5.835938 1.050781 -6.960938 1.5625 -7.734375 C 2.082031 -8.515625 2.832031 -8.90625 3.8125 -8.90625 Z M 3.8125 -8.90625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-17">
|
||||
<path style="stroke:none;" d="M 1.015625 -2.59375 L 1.015625 -6.5625 L 2.09375 -6.5625 L 2.09375 -2.625 C 2.09375 -2.007812 2.210938 -1.546875 2.453125 -1.234375 C 2.703125 -0.921875 3.066406 -0.765625 3.546875 -0.765625 C 4.128906 -0.765625 4.585938 -0.945312 4.921875 -1.3125 C 5.265625 -1.6875 5.4375 -2.195312 5.4375 -2.84375 L 5.4375 -6.5625 L 6.515625 -6.5625 L 6.515625 0 L 5.4375 0 L 5.4375 -1.015625 C 5.175781 -0.609375 4.875 -0.304688 4.53125 -0.109375 C 4.1875 0.078125 3.785156 0.171875 3.328125 0.171875 C 2.566406 0.171875 1.988281 -0.0625 1.59375 -0.53125 C 1.207031 -1 1.015625 -1.6875 1.015625 -2.59375 Z M 3.734375 -6.71875 Z M 3.734375 -6.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-18">
|
||||
<path style="stroke:none;" d="M 2.203125 -8.421875 L 2.203125 -6.5625 L 4.421875 -6.5625 L 4.421875 -5.71875 L 2.203125 -5.71875 L 2.203125 -2.15625 C 2.203125 -1.625 2.273438 -1.28125 2.421875 -1.125 C 2.566406 -0.976562 2.863281 -0.90625 3.3125 -0.90625 L 4.421875 -0.90625 L 4.421875 0 L 3.3125 0 C 2.476562 0 1.898438 -0.15625 1.578125 -0.46875 C 1.265625 -0.78125 1.109375 -1.34375 1.109375 -2.15625 L 1.109375 -5.71875 L 0.328125 -5.71875 L 0.328125 -6.5625 L 1.109375 -6.5625 L 1.109375 -8.421875 Z M 2.203125 -8.421875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-19">
|
||||
<path style="stroke:none;" d="M 6.75 -3.546875 L 6.75 -3.03125 L 1.78125 -3.03125 C 1.832031 -2.28125 2.054688 -1.710938 2.453125 -1.328125 C 2.859375 -0.941406 3.414062 -0.75 4.125 -0.75 C 4.539062 -0.75 4.941406 -0.796875 5.328125 -0.890625 C 5.722656 -0.992188 6.113281 -1.148438 6.5 -1.359375 L 6.5 -0.328125 C 6.101562 -0.171875 5.703125 -0.0507812 5.296875 0.03125 C 4.890625 0.125 4.476562 0.171875 4.0625 0.171875 C 3.019531 0.171875 2.191406 -0.128906 1.578125 -0.734375 C 0.960938 -1.347656 0.65625 -2.175781 0.65625 -3.21875 C 0.65625 -4.289062 0.945312 -5.140625 1.53125 -5.765625 C 2.113281 -6.398438 2.894531 -6.71875 3.875 -6.71875 C 4.757812 -6.71875 5.457031 -6.429688 5.96875 -5.859375 C 6.488281 -5.296875 6.75 -4.523438 6.75 -3.546875 Z M 5.671875 -3.875 C 5.660156 -4.457031 5.492188 -4.925781 5.171875 -5.28125 C 4.847656 -5.632812 4.421875 -5.8125 3.890625 -5.8125 C 3.285156 -5.8125 2.800781 -5.640625 2.4375 -5.296875 C 2.082031 -4.953125 1.878906 -4.472656 1.828125 -3.859375 Z M 5.671875 -3.875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-20">
|
||||
<path style="stroke:none;" d="M 1.125 -9.125 L 2.203125 -9.125 L 2.203125 0 L 1.125 0 Z M 1.125 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-21">
|
||||
<path style="stroke:none;" d="M 6.421875 -8.46875 L 6.421875 -7.3125 C 5.972656 -7.519531 5.546875 -7.675781 5.140625 -7.78125 C 4.742188 -7.894531 4.363281 -7.953125 4 -7.953125 C 3.351562 -7.953125 2.851562 -7.828125 2.5 -7.578125 C 2.15625 -7.328125 1.984375 -6.96875 1.984375 -6.5 C 1.984375 -6.113281 2.097656 -5.820312 2.328125 -5.625 C 2.554688 -5.425781 3 -5.269531 3.65625 -5.15625 L 4.359375 -5 C 5.242188 -4.832031 5.894531 -4.535156 6.3125 -4.109375 C 6.738281 -3.691406 6.953125 -3.128906 6.953125 -2.421875 C 6.953125 -1.566406 6.664062 -0.921875 6.09375 -0.484375 C 5.53125 -0.046875 4.695312 0.171875 3.59375 0.171875 C 3.1875 0.171875 2.75 0.125 2.28125 0.03125 C 1.8125 -0.0625 1.328125 -0.203125 0.828125 -0.390625 L 0.828125 -1.609375 C 1.304688 -1.335938 1.773438 -1.132812 2.234375 -1 C 2.703125 -0.863281 3.15625 -0.796875 3.59375 -0.796875 C 4.269531 -0.796875 4.789062 -0.925781 5.15625 -1.1875 C 5.53125 -1.457031 5.71875 -1.835938 5.71875 -2.328125 C 5.71875 -2.753906 5.582031 -3.085938 5.3125 -3.328125 C 5.050781 -3.578125 4.617188 -3.757812 4.015625 -3.875 L 3.296875 -4.015625 C 2.410156 -4.191406 1.769531 -4.46875 1.375 -4.84375 C 0.988281 -5.21875 0.796875 -5.738281 0.796875 -6.40625 C 0.796875 -7.1875 1.066406 -7.796875 1.609375 -8.234375 C 2.148438 -8.679688 2.898438 -8.90625 3.859375 -8.90625 C 4.273438 -8.90625 4.691406 -8.867188 5.109375 -8.796875 C 5.535156 -8.722656 5.972656 -8.613281 6.421875 -8.46875 Z M 6.421875 -8.46875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-22">
|
||||
<path style="stroke:none;" d="M 0.5 -6.5625 L 1.578125 -6.5625 L 2.9375 -1.4375 L 4.265625 -6.5625 L 5.546875 -6.5625 L 6.890625 -1.4375 L 8.234375 -6.5625 L 9.3125 -6.5625 L 7.59375 0 L 6.328125 0 L 4.90625 -5.375 L 3.5 0 L 2.21875 0 Z M 0.5 -6.5625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-23">
|
||||
<path style="stroke:none;" d="M 1.28125 -1.484375 L 2.515625 -1.484375 L 2.515625 0 L 1.28125 0 Z M 1.28125 -1.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-24">
|
||||
<path style="stroke:none;" d="M 6.125 2 L 6.125 2.828125 L -0.125 2.828125 L -0.125 2 Z M 6.125 2 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-0">
|
||||
<path style="stroke:none;" d="M 0.40625 1.421875 L 0.40625 -5.640625 L 4.40625 -5.640625 L 4.40625 1.421875 Z M 0.84375 0.96875 L 3.953125 0.96875 L 3.953125 -5.1875 L 0.84375 -5.1875 Z M 0.84375 0.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-1">
|
||||
<path style="stroke:none;" d="M 0.78125 -5.828125 L 1.578125 -5.828125 L 1.578125 -0.40625 C 1.578125 0.300781 1.441406 0.8125 1.171875 1.125 C 0.910156 1.445312 0.484375 1.609375 -0.109375 1.609375 L -0.421875 1.609375 L -0.421875 0.9375 L -0.171875 0.9375 C 0.179688 0.9375 0.425781 0.835938 0.5625 0.640625 C 0.707031 0.453125 0.78125 0.101562 0.78125 -0.40625 Z M 0.78125 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-2">
|
||||
<path style="stroke:none;" d="M 2.453125 -3.875 C 2.066406 -3.875 1.757812 -3.722656 1.53125 -3.421875 C 1.3125 -3.117188 1.203125 -2.707031 1.203125 -2.1875 C 1.203125 -1.664062 1.3125 -1.253906 1.53125 -0.953125 C 1.757812 -0.648438 2.066406 -0.5 2.453125 -0.5 C 2.835938 -0.5 3.140625 -0.648438 3.359375 -0.953125 C 3.585938 -1.253906 3.703125 -1.664062 3.703125 -2.1875 C 3.703125 -2.707031 3.585938 -3.117188 3.359375 -3.421875 C 3.140625 -3.722656 2.835938 -3.875 2.453125 -3.875 Z M 2.453125 -4.484375 C 3.078125 -4.484375 3.566406 -4.28125 3.921875 -3.875 C 4.273438 -3.46875 4.453125 -2.90625 4.453125 -2.1875 C 4.453125 -1.46875 4.273438 -0.90625 3.921875 -0.5 C 3.566406 -0.09375 3.078125 0.109375 2.453125 0.109375 C 1.828125 0.109375 1.332031 -0.09375 0.96875 -0.5 C 0.613281 -0.90625 0.4375 -1.46875 0.4375 -2.1875 C 0.4375 -2.90625 0.613281 -3.46875 0.96875 -3.875 C 1.332031 -4.28125 1.828125 -4.484375 2.453125 -4.484375 Z M 2.453125 -4.484375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-3">
|
||||
<path style="stroke:none;" d="M 3.890625 -2.1875 C 3.890625 -2.71875 3.78125 -3.128906 3.5625 -3.421875 C 3.351562 -3.722656 3.054688 -3.875 2.671875 -3.875 C 2.296875 -3.875 2 -3.722656 1.78125 -3.421875 C 1.5625 -3.128906 1.453125 -2.71875 1.453125 -2.1875 C 1.453125 -1.65625 1.5625 -1.238281 1.78125 -0.9375 C 2 -0.632812 2.296875 -0.484375 2.671875 -0.484375 C 3.054688 -0.484375 3.351562 -0.632812 3.5625 -0.9375 C 3.78125 -1.238281 3.890625 -1.65625 3.890625 -2.1875 Z M 1.453125 -3.71875 C 1.597656 -3.976562 1.785156 -4.171875 2.015625 -4.296875 C 2.253906 -4.421875 2.53125 -4.484375 2.84375 -4.484375 C 3.375 -4.484375 3.804688 -4.269531 4.140625 -3.84375 C 4.472656 -3.425781 4.640625 -2.875 4.640625 -2.1875 C 4.640625 -1.5 4.472656 -0.941406 4.140625 -0.515625 C 3.804688 -0.0976562 3.375 0.109375 2.84375 0.109375 C 2.53125 0.109375 2.253906 0.046875 2.015625 -0.078125 C 1.785156 -0.203125 1.597656 -0.394531 1.453125 -0.65625 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 Z M 1.453125 -3.71875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-4">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-5">
|
||||
<path style="stroke:none;" d="M 1 -0.671875 L 2.28125 -0.671875 L 2.28125 -5.109375 L 0.875 -4.828125 L 0.875 -5.546875 L 2.28125 -5.828125 L 3.0625 -5.828125 L 3.0625 -0.671875 L 4.359375 -0.671875 L 4.359375 0 L 1 0 Z M 1 -0.671875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-6">
|
||||
<path style="stroke:none;" d="M 3.546875 -4.25 L 3.546875 -3.5625 C 3.335938 -3.664062 3.125 -3.742188 2.90625 -3.796875 C 2.6875 -3.847656 2.460938 -3.875 2.234375 -3.875 C 1.878906 -3.875 1.609375 -3.816406 1.421875 -3.703125 C 1.242188 -3.597656 1.15625 -3.4375 1.15625 -3.21875 C 1.15625 -3.050781 1.21875 -2.921875 1.34375 -2.828125 C 1.476562 -2.734375 1.738281 -2.644531 2.125 -2.5625 L 2.375 -2.5 C 2.882812 -2.394531 3.242188 -2.242188 3.453125 -2.046875 C 3.671875 -1.847656 3.78125 -1.566406 3.78125 -1.203125 C 3.78125 -0.796875 3.617188 -0.472656 3.296875 -0.234375 C 2.972656 -0.00390625 2.53125 0.109375 1.96875 0.109375 C 1.738281 0.109375 1.492188 0.0820312 1.234375 0.03125 C 0.984375 -0.0078125 0.71875 -0.0703125 0.4375 -0.15625 L 0.4375 -0.90625 C 0.695312 -0.769531 0.957031 -0.664062 1.21875 -0.59375 C 1.476562 -0.519531 1.734375 -0.484375 1.984375 -0.484375 C 2.328125 -0.484375 2.585938 -0.539062 2.765625 -0.65625 C 2.953125 -0.78125 3.046875 -0.945312 3.046875 -1.15625 C 3.046875 -1.351562 2.976562 -1.503906 2.84375 -1.609375 C 2.707031 -1.710938 2.421875 -1.8125 1.984375 -1.90625 L 1.734375 -1.96875 C 1.285156 -2.0625 0.960938 -2.203125 0.765625 -2.390625 C 0.566406 -2.585938 0.46875 -2.851562 0.46875 -3.1875 C 0.46875 -3.601562 0.613281 -3.921875 0.90625 -4.140625 C 1.195312 -4.367188 1.609375 -4.484375 2.140625 -4.484375 C 2.410156 -4.484375 2.660156 -4.460938 2.890625 -4.421875 C 3.128906 -4.378906 3.347656 -4.320312 3.546875 -4.25 Z M 3.546875 -4.25 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-7">
|
||||
<path style="stroke:none;" d="M 1.46875 -5.625 L 1.46875 -4.375 L 2.953125 -4.375 L 2.953125 -3.8125 L 1.46875 -3.8125 L 1.46875 -1.4375 C 1.46875 -1.082031 1.515625 -0.851562 1.609375 -0.75 C 1.710938 -0.65625 1.910156 -0.609375 2.203125 -0.609375 L 2.953125 -0.609375 L 2.953125 0 L 2.203125 0 C 1.648438 0 1.269531 -0.101562 1.0625 -0.3125 C 0.851562 -0.519531 0.75 -0.894531 0.75 -1.4375 L 0.75 -3.8125 L 0.21875 -3.8125 L 0.21875 -4.375 L 0.75 -4.375 L 0.75 -5.625 Z M 1.46875 -5.625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-8">
|
||||
<path style="stroke:none;" d="M 2.75 -2.203125 C 2.164062 -2.203125 1.757812 -2.132812 1.53125 -2 C 1.3125 -1.863281 1.203125 -1.640625 1.203125 -1.328125 C 1.203125 -1.066406 1.285156 -0.859375 1.453125 -0.703125 C 1.617188 -0.554688 1.847656 -0.484375 2.140625 -0.484375 C 2.535156 -0.484375 2.851562 -0.625 3.09375 -0.90625 C 3.332031 -1.195312 3.453125 -1.578125 3.453125 -2.046875 L 3.453125 -2.203125 Z M 4.171875 -2.5 L 4.171875 0 L 3.453125 0 L 3.453125 -0.671875 C 3.296875 -0.398438 3.09375 -0.203125 2.84375 -0.078125 C 2.601562 0.046875 2.304688 0.109375 1.953125 0.109375 C 1.503906 0.109375 1.144531 -0.015625 0.875 -0.265625 C 0.613281 -0.515625 0.484375 -0.851562 0.484375 -1.28125 C 0.484375 -1.769531 0.644531 -2.140625 0.96875 -2.390625 C 1.300781 -2.640625 1.796875 -2.765625 2.453125 -2.765625 L 3.453125 -2.765625 L 3.453125 -2.828125 C 3.453125 -3.160156 3.34375 -3.414062 3.125 -3.59375 C 2.914062 -3.78125 2.613281 -3.875 2.21875 -3.875 C 1.96875 -3.875 1.722656 -3.84375 1.484375 -3.78125 C 1.242188 -3.71875 1.015625 -3.628906 0.796875 -3.515625 L 0.796875 -4.171875 C 1.066406 -4.273438 1.320312 -4.351562 1.5625 -4.40625 C 1.8125 -4.457031 2.054688 -4.484375 2.296875 -4.484375 C 2.921875 -4.484375 3.390625 -4.316406 3.703125 -3.984375 C 4.015625 -3.660156 4.171875 -3.164062 4.171875 -2.5 Z M 4.171875 -2.5 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-9">
|
||||
<path style="stroke:none;" d="M 3.296875 -3.703125 C 3.210938 -3.753906 3.125 -3.789062 3.03125 -3.8125 C 2.9375 -3.832031 2.832031 -3.84375 2.71875 -3.84375 C 2.3125 -3.84375 2 -3.707031 1.78125 -3.4375 C 1.5625 -3.175781 1.453125 -2.800781 1.453125 -2.3125 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.597656 -3.960938 1.789062 -4.15625 2.03125 -4.28125 C 2.28125 -4.414062 2.578125 -4.484375 2.921875 -4.484375 C 2.972656 -4.484375 3.023438 -4.476562 3.078125 -4.46875 C 3.140625 -4.46875 3.207031 -4.457031 3.28125 -4.4375 Z M 3.296875 -3.703125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-10">
|
||||
<path style="stroke:none;" d="M 0.75 -4.375 L 1.46875 -4.375 L 1.46875 0 L 0.75 0 Z M 0.75 -6.078125 L 1.46875 -6.078125 L 1.46875 -5.171875 L 0.75 -5.171875 Z M 0.75 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-11">
|
||||
<path style="stroke:none;" d="M 4.390625 -2.640625 L 4.390625 0 L 3.671875 0 L 3.671875 -2.625 C 3.671875 -3.03125 3.585938 -3.335938 3.421875 -3.546875 C 3.265625 -3.753906 3.023438 -3.859375 2.703125 -3.859375 C 2.316406 -3.859375 2.007812 -3.734375 1.78125 -3.484375 C 1.5625 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -4.375 L 1.453125 -4.375 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.285156 -4.414062 2.554688 -4.484375 2.859375 -4.484375 C 3.367188 -4.484375 3.75 -4.328125 4 -4.015625 C 4.257812 -3.703125 4.390625 -3.242188 4.390625 -2.640625 Z M 4.390625 -2.640625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-12">
|
||||
<path style="stroke:none;" d="M 3.640625 -2.234375 C 3.640625 -2.753906 3.53125 -3.15625 3.3125 -3.4375 C 3.09375 -3.726562 2.789062 -3.875 2.40625 -3.875 C 2.019531 -3.875 1.71875 -3.726562 1.5 -3.4375 C 1.289062 -3.15625 1.1875 -2.753906 1.1875 -2.234375 C 1.1875 -1.722656 1.289062 -1.320312 1.5 -1.03125 C 1.71875 -0.75 2.019531 -0.609375 2.40625 -0.609375 C 2.789062 -0.609375 3.09375 -0.75 3.3125 -1.03125 C 3.53125 -1.320312 3.640625 -1.722656 3.640625 -2.234375 Z M 4.359375 -0.546875 C 4.359375 0.203125 4.191406 0.757812 3.859375 1.125 C 3.523438 1.488281 3.019531 1.671875 2.34375 1.671875 C 2.082031 1.671875 1.835938 1.648438 1.609375 1.609375 C 1.390625 1.566406 1.175781 1.507812 0.96875 1.4375 L 0.96875 0.734375 C 1.175781 0.847656 1.382812 0.929688 1.59375 0.984375 C 1.800781 1.046875 2.007812 1.078125 2.21875 1.078125 C 2.695312 1.078125 3.050781 0.953125 3.28125 0.703125 C 3.519531 0.453125 3.640625 0.078125 3.640625 -0.421875 L 3.640625 -0.765625 C 3.484375 -0.515625 3.289062 -0.320312 3.0625 -0.1875 C 2.832031 -0.0625 2.554688 0 2.234375 0 C 1.691406 0 1.253906 -0.203125 0.921875 -0.609375 C 0.597656 -1.023438 0.4375 -1.566406 0.4375 -2.234375 C 0.4375 -2.910156 0.597656 -3.453125 0.921875 -3.859375 C 1.253906 -4.273438 1.691406 -4.484375 2.234375 -4.484375 C 2.554688 -4.484375 2.832031 -4.414062 3.0625 -4.28125 C 3.289062 -4.15625 3.484375 -3.96875 3.640625 -3.71875 L 3.640625 -4.375 L 4.359375 -4.375 Z M 4.359375 -0.546875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-13">
|
||||
<path style="stroke:none;" d="M 3.640625 -3.71875 L 3.640625 -6.078125 L 4.359375 -6.078125 L 4.359375 0 L 3.640625 0 L 3.640625 -0.65625 C 3.484375 -0.394531 3.289062 -0.203125 3.0625 -0.078125 C 2.832031 0.046875 2.554688 0.109375 2.234375 0.109375 C 1.703125 0.109375 1.269531 -0.0976562 0.9375 -0.515625 C 0.601562 -0.941406 0.4375 -1.5 0.4375 -2.1875 C 0.4375 -2.875 0.601562 -3.425781 0.9375 -3.84375 C 1.269531 -4.269531 1.703125 -4.484375 2.234375 -4.484375 C 2.554688 -4.484375 2.832031 -4.421875 3.0625 -4.296875 C 3.289062 -4.171875 3.484375 -3.976562 3.640625 -3.71875 Z M 1.1875 -2.1875 C 1.1875 -1.65625 1.296875 -1.238281 1.515625 -0.9375 C 1.734375 -0.632812 2.03125 -0.484375 2.40625 -0.484375 C 2.789062 -0.484375 3.09375 -0.632812 3.3125 -0.9375 C 3.53125 -1.238281 3.640625 -1.65625 3.640625 -2.1875 C 3.640625 -2.71875 3.53125 -3.128906 3.3125 -3.421875 C 3.09375 -3.722656 2.789062 -3.875 2.40625 -3.875 C 2.03125 -3.875 1.734375 -3.722656 1.515625 -3.421875 C 1.296875 -3.128906 1.1875 -2.71875 1.1875 -2.1875 Z M 1.1875 -2.1875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-14">
|
||||
<path style="stroke:none;" d="M 4.5 -2.375 L 4.5 -2.015625 L 1.1875 -2.015625 C 1.21875 -1.523438 1.367188 -1.148438 1.640625 -0.890625 C 1.910156 -0.628906 2.28125 -0.5 2.75 -0.5 C 3.03125 -0.5 3.300781 -0.53125 3.5625 -0.59375 C 3.820312 -0.664062 4.078125 -0.769531 4.328125 -0.90625 L 4.328125 -0.21875 C 4.066406 -0.113281 3.800781 -0.0351562 3.53125 0.015625 C 3.257812 0.078125 2.988281 0.109375 2.71875 0.109375 C 2.019531 0.109375 1.460938 -0.09375 1.046875 -0.5 C 0.640625 -0.90625 0.4375 -1.453125 0.4375 -2.140625 C 0.4375 -2.859375 0.628906 -3.425781 1.015625 -3.84375 C 1.410156 -4.269531 1.9375 -4.484375 2.59375 -4.484375 C 3.175781 -4.484375 3.640625 -4.289062 3.984375 -3.90625 C 4.328125 -3.53125 4.5 -3.019531 4.5 -2.375 Z M 3.78125 -2.578125 C 3.769531 -2.972656 3.65625 -3.285156 3.4375 -3.515625 C 3.226562 -3.753906 2.945312 -3.875 2.59375 -3.875 C 2.195312 -3.875 1.875 -3.757812 1.625 -3.53125 C 1.382812 -3.300781 1.25 -2.984375 1.21875 -2.578125 Z M 3.78125 -2.578125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-15">
|
||||
<path style="stroke:none;" d="M 1.53125 -0.671875 L 4.296875 -0.671875 L 4.296875 0 L 0.59375 0 L 0.59375 -0.671875 C 0.882812 -0.972656 1.289062 -1.382812 1.8125 -1.90625 C 2.332031 -2.4375 2.65625 -2.773438 2.78125 -2.921875 C 3.039062 -3.203125 3.21875 -3.441406 3.3125 -3.640625 C 3.414062 -3.835938 3.46875 -4.03125 3.46875 -4.21875 C 3.46875 -4.53125 3.359375 -4.785156 3.140625 -4.984375 C 2.921875 -5.179688 2.640625 -5.28125 2.296875 -5.28125 C 2.046875 -5.28125 1.78125 -5.234375 1.5 -5.140625 C 1.226562 -5.054688 0.9375 -4.925781 0.625 -4.75 L 0.625 -5.546875 C 0.945312 -5.679688 1.242188 -5.78125 1.515625 -5.84375 C 1.796875 -5.90625 2.050781 -5.9375 2.28125 -5.9375 C 2.882812 -5.9375 3.363281 -5.785156 3.71875 -5.484375 C 4.082031 -5.179688 4.265625 -4.78125 4.265625 -4.28125 C 4.265625 -4.039062 4.21875 -3.8125 4.125 -3.59375 C 4.03125 -3.375 3.867188 -3.117188 3.640625 -2.828125 C 3.566406 -2.753906 3.351562 -2.535156 3 -2.171875 C 2.65625 -1.816406 2.164062 -1.316406 1.53125 -0.671875 Z M 1.53125 -0.671875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-16">
|
||||
<path style="stroke:none;" d="M 3.25 -3.140625 C 3.625 -3.066406 3.914062 -2.898438 4.125 -2.640625 C 4.34375 -2.390625 4.453125 -2.078125 4.453125 -1.703125 C 4.453125 -1.117188 4.253906 -0.671875 3.859375 -0.359375 C 3.460938 -0.046875 2.898438 0.109375 2.171875 0.109375 C 1.921875 0.109375 1.664062 0.0820312 1.40625 0.03125 C 1.15625 -0.0078125 0.890625 -0.078125 0.609375 -0.171875 L 0.609375 -0.9375 C 0.828125 -0.8125 1.066406 -0.710938 1.328125 -0.640625 C 1.585938 -0.578125 1.859375 -0.546875 2.140625 -0.546875 C 2.640625 -0.546875 3.019531 -0.644531 3.28125 -0.84375 C 3.539062 -1.039062 3.671875 -1.328125 3.671875 -1.703125 C 3.671875 -2.046875 3.546875 -2.3125 3.296875 -2.5 C 3.054688 -2.695312 2.722656 -2.796875 2.296875 -2.796875 L 1.625 -2.796875 L 1.625 -3.4375 L 2.328125 -3.4375 C 2.710938 -3.4375 3.007812 -3.515625 3.21875 -3.671875 C 3.425781 -3.828125 3.53125 -4.050781 3.53125 -4.34375 C 3.53125 -4.644531 3.421875 -4.875 3.203125 -5.03125 C 2.992188 -5.195312 2.691406 -5.28125 2.296875 -5.28125 C 2.078125 -5.28125 1.84375 -5.253906 1.59375 -5.203125 C 1.351562 -5.160156 1.082031 -5.085938 0.78125 -4.984375 L 0.78125 -5.6875 C 1.082031 -5.769531 1.363281 -5.832031 1.625 -5.875 C 1.882812 -5.914062 2.132812 -5.9375 2.375 -5.9375 C 2.96875 -5.9375 3.4375 -5.800781 3.78125 -5.53125 C 4.132812 -5.257812 4.3125 -4.890625 4.3125 -4.421875 C 4.3125 -4.097656 4.21875 -3.828125 4.03125 -3.609375 C 3.851562 -3.390625 3.59375 -3.234375 3.25 -3.140625 Z M 3.25 -3.140625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-17">
|
||||
<path style="stroke:none;" d="M 2.734375 -5.0625 L 1.671875 -2.15625 L 3.8125 -2.15625 Z M 2.296875 -5.828125 L 3.1875 -5.828125 L 5.40625 0 L 4.59375 0 L 4.0625 -1.5 L 1.421875 -1.5 L 0.890625 0 L 0.0625 0 Z M 2.296875 -5.828125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-18">
|
||||
<path style="stroke:none;" d="M 0.75 -6.078125 L 1.46875 -6.078125 L 1.46875 0 L 0.75 0 Z M 0.75 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-19">
|
||||
<path style="stroke:none;" d="M 3.90625 -4.203125 L 3.90625 -3.53125 C 3.695312 -3.644531 3.488281 -3.726562 3.28125 -3.78125 C 3.082031 -3.84375 2.878906 -3.875 2.671875 -3.875 C 2.203125 -3.875 1.835938 -3.722656 1.578125 -3.421875 C 1.328125 -3.128906 1.203125 -2.71875 1.203125 -2.1875 C 1.203125 -1.65625 1.328125 -1.238281 1.578125 -0.9375 C 1.835938 -0.644531 2.203125 -0.5 2.671875 -0.5 C 2.878906 -0.5 3.082031 -0.523438 3.28125 -0.578125 C 3.488281 -0.640625 3.695312 -0.722656 3.90625 -0.828125 L 3.90625 -0.171875 C 3.707031 -0.078125 3.5 -0.0078125 3.28125 0.03125 C 3.0625 0.0820312 2.832031 0.109375 2.59375 0.109375 C 1.9375 0.109375 1.410156 -0.09375 1.015625 -0.5 C 0.628906 -0.914062 0.4375 -1.476562 0.4375 -2.1875 C 0.4375 -2.894531 0.632812 -3.453125 1.03125 -3.859375 C 1.425781 -4.273438 1.960938 -4.484375 2.640625 -4.484375 C 2.859375 -4.484375 3.070312 -4.457031 3.28125 -4.40625 C 3.5 -4.363281 3.707031 -4.296875 3.90625 -4.203125 Z M 3.90625 -4.203125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-20">
|
||||
<path style="stroke:none;" d="M 4.390625 -2.640625 L 4.390625 0 L 3.671875 0 L 3.671875 -2.625 C 3.671875 -3.03125 3.585938 -3.335938 3.421875 -3.546875 C 3.265625 -3.753906 3.023438 -3.859375 2.703125 -3.859375 C 2.316406 -3.859375 2.007812 -3.734375 1.78125 -3.484375 C 1.5625 -3.234375 1.453125 -2.894531 1.453125 -2.46875 L 1.453125 0 L 0.734375 0 L 0.734375 -6.078125 L 1.453125 -6.078125 L 1.453125 -3.703125 C 1.617188 -3.960938 1.816406 -4.15625 2.046875 -4.28125 C 2.285156 -4.414062 2.554688 -4.484375 2.859375 -4.484375 C 3.367188 -4.484375 3.75 -4.328125 4 -4.015625 C 4.257812 -3.703125 4.390625 -3.242188 4.390625 -2.640625 Z M 4.390625 -2.640625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-21">
|
||||
<path style="stroke:none;" d="M 2.96875 -6.078125 L 2.96875 -5.484375 L 2.28125 -5.484375 C 2.019531 -5.484375 1.835938 -5.429688 1.734375 -5.328125 C 1.640625 -5.222656 1.59375 -5.035156 1.59375 -4.765625 L 1.59375 -4.375 L 2.78125 -4.375 L 2.78125 -3.8125 L 1.59375 -3.8125 L 1.59375 0 L 0.875 0 L 0.875 -3.8125 L 0.1875 -3.8125 L 0.1875 -4.375 L 0.875 -4.375 L 0.875 -4.6875 C 0.875 -5.164062 0.984375 -5.515625 1.203125 -5.734375 C 1.429688 -5.960938 1.796875 -6.078125 2.296875 -6.078125 Z M 2.96875 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-22">
|
||||
<path style="stroke:none;" d="M 0.734375 -6.078125 L 1.453125 -6.078125 L 1.453125 -2.484375 L 3.59375 -4.375 L 4.515625 -4.375 L 2.1875 -2.328125 L 4.609375 0 L 3.671875 0 L 1.453125 -2.140625 L 1.453125 0 L 0.734375 0 Z M 0.734375 -6.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-23">
|
||||
<path style="stroke:none;" d="M 0.34375 -4.375 L 1.0625 -4.375 L 1.953125 -0.96875 L 2.84375 -4.375 L 3.703125 -4.375 L 4.59375 -0.96875 L 5.484375 -4.375 L 6.203125 -4.375 L 5.0625 0 L 4.21875 0 L 3.28125 -3.59375 L 2.328125 0 L 1.484375 0 Z M 0.34375 -4.375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-24">
|
||||
<path style="stroke:none;" d="M 4.28125 -5.640625 L 4.28125 -4.875 C 3.976562 -5.019531 3.691406 -5.125 3.421875 -5.1875 C 3.160156 -5.257812 2.910156 -5.296875 2.671875 -5.296875 C 2.234375 -5.296875 1.898438 -5.210938 1.671875 -5.046875 C 1.441406 -4.878906 1.328125 -4.644531 1.328125 -4.34375 C 1.328125 -4.082031 1.398438 -3.882812 1.546875 -3.75 C 1.703125 -3.625 2 -3.519531 2.4375 -3.4375 L 2.90625 -3.34375 C 3.5 -3.226562 3.9375 -3.03125 4.21875 -2.75 C 4.5 -2.46875 4.640625 -2.085938 4.640625 -1.609375 C 4.640625 -1.046875 4.445312 -0.617188 4.0625 -0.328125 C 3.6875 -0.0351562 3.132812 0.109375 2.40625 0.109375 C 2.125 0.109375 1.828125 0.078125 1.515625 0.015625 C 1.203125 -0.046875 0.878906 -0.140625 0.546875 -0.265625 L 0.546875 -1.078125 C 0.867188 -0.890625 1.179688 -0.75 1.484375 -0.65625 C 1.796875 -0.570312 2.101562 -0.53125 2.40625 -0.53125 C 2.851562 -0.53125 3.195312 -0.617188 3.4375 -0.796875 C 3.6875 -0.972656 3.8125 -1.222656 3.8125 -1.546875 C 3.8125 -1.835938 3.722656 -2.0625 3.546875 -2.21875 C 3.367188 -2.382812 3.082031 -2.507812 2.6875 -2.59375 L 2.203125 -2.6875 C 1.609375 -2.800781 1.179688 -2.984375 0.921875 -3.234375 C 0.660156 -3.484375 0.53125 -3.832031 0.53125 -4.28125 C 0.53125 -4.789062 0.710938 -5.191406 1.078125 -5.484375 C 1.441406 -5.785156 1.941406 -5.9375 2.578125 -5.9375 C 2.847656 -5.9375 3.125 -5.910156 3.40625 -5.859375 C 3.695312 -5.816406 3.988281 -5.742188 4.28125 -5.640625 Z M 4.28125 -5.640625 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 1149.457031 48 L 1191 48 L 1191 59 L 1149.457031 59 Z M 1149.457031 48 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip2">
|
||||
<path d="M 168.484375 80 L 210 80 L 210 91 L 168.484375 91 Z M 168.484375 80 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip3">
|
||||
<path d="M 945.597656 80 L 987 80 L 987 91 L 945.597656 91 Z M 945.597656 80 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip4">
|
||||
<path d="M 250.011719 69 L 303 69 L 303 78 L 250.011719 78 Z M 250.011719 69 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip5">
|
||||
<path d="M 979.003906 69 L 1003.683594 69 L 1003.683594 77 L 979.003906 77 Z M 979.003906 69 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip6">
|
||||
<path d="M 1018.117188 112 L 1060 112 L 1060 123 L 1018.117188 123 Z M 1018.117188 112 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip7">
|
||||
<path d="M 583.375 101 L 637 101 L 637 110 L 583.375 110 Z M 583.375 101 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip8">
|
||||
<path d="M 1049.300781 101 L 1070.394531 101 L 1070.394531 109 L 1049.300781 109 Z M 1049.300781 101 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip9">
|
||||
<path d="M 1082.304688 144 L 1124 144 L 1124 155 L 1082.304688 155 Z M 1082.304688 144 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip10">
|
||||
<path d="M 819.433594 133 L 873 133 L 873 142 L 819.433594 142 Z M 819.433594 133 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip11">
|
||||
<path d="M 1112 133 L 1132.316406 133 L 1132.316406 141 L 1112 141 Z M 1112 133 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip12">
|
||||
<path d="M 901.039062 37 L 985 37 L 985 45 L 901.039062 45 Z M 901.039062 37 "/>
|
||||
</clipPath>
|
||||
<clipPath id="clip13">
|
||||
<path d="M 1179.296875 37 L 1200.945312 37 L 1200.945312 45 L 1179.296875 45 Z M 1179.296875 37 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface2">
|
||||
<rect x="0" y="0" width="1280" height="184" style="fill:rgb(90%,90%,90%);fill-opacity:1;stroke:none;"/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 4 0 L 4 184 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 195.652344 0 L 195.652344 184 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 387.304688 0 L 387.304688 184 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 578.957031 0 L 578.957031 184 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 770.613281 0 L 770.613281 184 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 962.265625 0 L 962.265625 184 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(70%,70%,70%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1153.917969 0 L 1153.917969 184 "/>
|
||||
<g style="fill:rgb(40%,40%,40%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="4" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-2" x="11.582031" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-3" x="18.935547" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-4" x="25.533203" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="33.138672" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-6" x="36.953125" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-7" x="44.570312" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="49.503906" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="52.837891" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="60.455078" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-9" x="64.269531" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="71.886719" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-10" x="75.220703" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="82.322266" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="85.65625" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-8" x="91.908203" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-12" x="95.242188" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-13" x="102.583984" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-14" x="110.189453" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="114.232422" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-15" x="118.046875" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-16" x="125.681641" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-5" x="133.316406" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-17" x="137.130859" y="179.503906"/>
|
||||
<use xlink:href="#glyph0-11" x="144.736328" y="179.503906"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 10.746094 46 L 18.640625 46 L 18.640625 60 L 10.746094 60 Z M 10.746094 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 18.640625 46 L 59.882812 46 L 59.882812 60 L 18.640625 60 Z M 18.640625 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 59.886719 46 L 491.21875 46 L 491.21875 60 L 59.886719 60 Z M 59.886719 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 491.21875 46 L 523.03125 46 L 523.03125 60 L 491.21875 60 Z M 491.21875 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 523.035156 46 L 618.25 46 L 618.25 60 L 523.035156 60 Z M 523.035156 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 618.246094 46 L 621.214844 46 L 621.214844 60 L 618.246094 60 Z M 618.246094 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 621.21875 46 L 864.0625 46 L 864.0625 60 L 621.21875 60 Z M 621.21875 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 864.0625 46 L 871 46 L 871 60 L 864.0625 60 Z M 864.0625 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 871 46 L 918.414062 46 L 918.414062 60 L 871 60 Z M 871 46 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="873" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="877.705078" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="882.638672" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="889.992188" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="896.589844" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="903.972656" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="907.306641" y="58"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 918.414062 46 L 927.882812 46 L 927.882812 60 L 918.414062 60 Z M 918.414062 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 927.882812 46 L 1134.214844 46 L 1134.214844 60 L 927.882812 60 Z M 927.882812 46 "/>
|
||||
<g style="fill:rgb(100%,100%,100%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-21" x="929.882812" y="58"/>
|
||||
<use xlink:href="#glyph0-22" x="937.5" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="947.314453" y="58"/>
|
||||
<use xlink:href="#glyph0-18" x="950.648438" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="955.353516" y="58"/>
|
||||
<use xlink:href="#glyph0-4" x="961.951172" y="58"/>
|
||||
<use xlink:href="#glyph0-23" x="969.556641" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="973.371094" y="58"/>
|
||||
<use xlink:href="#glyph0-22" x="980.724609" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="990.539062" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="997.892578" y="58"/>
|
||||
<use xlink:href="#glyph0-18" x="1001.226562" y="58"/>
|
||||
<use xlink:href="#glyph0-24" x="1005.931641" y="58"/>
|
||||
<use xlink:href="#glyph0-8" x="1011.931641" y="58"/>
|
||||
<use xlink:href="#glyph0-9" x="1015.265625" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="1022.882812" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1026.216797" y="58"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1134.214844 46 L 1147.457031 46 L 1147.457031 60 L 1134.214844 60 Z M 1134.214844 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1147.457031 46 L 1196.730469 46 L 1196.730469 60 L 1147.457031 60 Z M 1147.457031 46 "/>
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="1149.457031" y="58"/>
|
||||
<use xlink:href="#glyph0-7" x="1154.162109" y="58"/>
|
||||
<use xlink:href="#glyph0-2" x="1159.095703" y="58"/>
|
||||
<use xlink:href="#glyph0-3" x="1166.449219" y="58"/>
|
||||
<use xlink:href="#glyph0-19" x="1173.046875" y="58"/>
|
||||
<use xlink:href="#glyph0-20" x="1180.429688" y="58"/>
|
||||
<use xlink:href="#glyph0-13" x="1183.763672" y="58"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1196.730469 46 L 1200.945312 46 L 1200.945312 60 L 1196.730469 60 Z M 1196.730469 46 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 59.886719 78 L 62.914062 78 L 62.914062 92 L 59.886719 92 Z M 59.886719 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 62.914062 78 L 166.484375 78 L 166.484375 92 L 62.914062 92 Z M 62.914062 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 166.484375 78 L 471.960938 78 L 471.960938 92 L 166.484375 92 Z M 166.484375 78 "/>
|
||||
<g clip-path="url(#clip2)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="168.484375" y="90"/>
|
||||
<use xlink:href="#glyph0-7" x="173.189453" y="90"/>
|
||||
<use xlink:href="#glyph0-2" x="178.123047" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="185.476562" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="192.074219" y="90"/>
|
||||
<use xlink:href="#glyph0-20" x="199.457031" y="90"/>
|
||||
<use xlink:href="#glyph0-13" x="202.791016" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 471.957031 78 L 483.074219 78 L 483.074219 92 L 471.957031 92 Z M 471.957031 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 483.074219 78 L 932.367188 78 L 932.367188 92 L 483.074219 92 Z M 483.074219 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 932.367188 78 L 943.597656 78 L 943.597656 92 L 932.367188 92 Z M 932.367188 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 943.597656 78 L 996.683594 78 L 996.683594 92 L 943.597656 92 Z M 943.597656 78 "/>
|
||||
<g clip-path="url(#clip3)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="945.597656" y="90"/>
|
||||
<use xlink:href="#glyph0-7" x="950.302734" y="90"/>
|
||||
<use xlink:href="#glyph0-2" x="955.236328" y="90"/>
|
||||
<use xlink:href="#glyph0-3" x="962.589844" y="90"/>
|
||||
<use xlink:href="#glyph0-19" x="969.1875" y="90"/>
|
||||
<use xlink:href="#glyph0-20" x="976.570312" y="90"/>
|
||||
<use xlink:href="#glyph0-13" x="979.904297" y="90"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 996.683594 78 L 1006.457031 78 L 1006.457031 92 L 996.683594 92 Z M 996.683594 78 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1006.460938 78 L 1003.683594 78 L 1003.683594 92 L 1006.460938 92 Z M 1006.460938 78 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 248.011719 81 L 248.011719 75 "/>
|
||||
<g clip-path="url(#clip4)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="250.011719" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="252.371094" y="76"/>
|
||||
<use xlink:href="#glyph1-3" x="257.265625" y="76"/>
|
||||
<use xlink:href="#glyph1-4" x="262.34375" y="76"/>
|
||||
<use xlink:href="#glyph1-5" x="264.886719" y="76"/>
|
||||
<use xlink:href="#glyph1-4" x="269.976562" y="76"/>
|
||||
<use xlink:href="#glyph1-6" x="272.519531" y="76"/>
|
||||
<use xlink:href="#glyph1-7" x="276.6875" y="76"/>
|
||||
<use xlink:href="#glyph1-8" x="279.824219" y="76"/>
|
||||
<use xlink:href="#glyph1-9" x="284.726562" y="76"/>
|
||||
<use xlink:href="#glyph1-7" x="288.015625" y="76"/>
|
||||
<use xlink:href="#glyph1-10" x="291.152344" y="76"/>
|
||||
<use xlink:href="#glyph1-11" x="293.375" y="76"/>
|
||||
<use xlink:href="#glyph1-12" x="298.445312" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 977.003906 81 L 977.003906 75 "/>
|
||||
<g clip-path="url(#clip5)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-5" x="979.003906" y="76"/>
|
||||
<use xlink:href="#glyph1-4" x="984.09375" y="76"/>
|
||||
<use xlink:href="#glyph1-13" x="986.636719" y="76"/>
|
||||
<use xlink:href="#glyph1-2" x="991.714844" y="76"/>
|
||||
<use xlink:href="#glyph1-11" x="996.609375" y="76"/>
|
||||
<use xlink:href="#glyph1-14" x="1001.679688" y="76"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.886719 46 L 59.886719 92 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 523.035156 110 L 525.679688 110 L 525.679688 124 L 523.035156 124 Z M 523.035156 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 525.679688 110 L 544.980469 110 L 544.980469 124 L 525.679688 124 Z M 525.679688 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 544.976562 110 L 611.632812 110 L 611.632812 124 L 544.976562 124 Z M 544.976562 110 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="546.976562" y="122"/>
|
||||
<use xlink:href="#glyph0-7" x="551.681641" y="122"/>
|
||||
<use xlink:href="#glyph0-2" x="556.615234" y="122"/>
|
||||
<use xlink:href="#glyph0-3" x="563.96875" y="122"/>
|
||||
<use xlink:href="#glyph0-19" x="570.566406" y="122"/>
|
||||
<use xlink:href="#glyph0-20" x="577.949219" y="122"/>
|
||||
<use xlink:href="#glyph0-13" x="581.283203" y="122"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 611.636719 110 L 615.625 110 L 615.625 124 L 611.636719 124 Z M 611.636719 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 615.621094 110 L 1006.457031 110 L 1006.457031 124 L 615.621094 124 Z M 615.621094 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1006.460938 110 L 1016.121094 110 L 1016.121094 124 L 1006.460938 124 Z M 1006.460938 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1016.117188 110 L 1065.160156 110 L 1065.160156 124 L 1016.117188 124 Z M 1016.117188 110 "/>
|
||||
<g clip-path="url(#clip6)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="1018.117188" y="122"/>
|
||||
<use xlink:href="#glyph0-7" x="1022.822266" y="122"/>
|
||||
<use xlink:href="#glyph0-2" x="1027.755859" y="122"/>
|
||||
<use xlink:href="#glyph0-3" x="1035.109375" y="122"/>
|
||||
<use xlink:href="#glyph0-19" x="1041.707031" y="122"/>
|
||||
<use xlink:href="#glyph0-20" x="1049.089844" y="122"/>
|
||||
<use xlink:href="#glyph0-13" x="1052.423828" y="122"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1065.164062 110 L 1071.8125 110 L 1071.8125 124 L 1065.164062 124 Z M 1065.164062 110 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1071.8125 110 L 1070.394531 110 L 1070.394531 124 L 1071.8125 124 Z M 1071.8125 110 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 581.375 113 L 581.375 107 "/>
|
||||
<g clip-path="url(#clip7)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="583.375" y="108"/>
|
||||
<use xlink:href="#glyph1-2" x="585.734375" y="108"/>
|
||||
<use xlink:href="#glyph1-3" x="590.628906" y="108"/>
|
||||
<use xlink:href="#glyph1-4" x="595.707031" y="108"/>
|
||||
<use xlink:href="#glyph1-15" x="598.25" y="108"/>
|
||||
<use xlink:href="#glyph1-4" x="603.339844" y="108"/>
|
||||
<use xlink:href="#glyph1-6" x="605.882812" y="108"/>
|
||||
<use xlink:href="#glyph1-7" x="610.050781" y="108"/>
|
||||
<use xlink:href="#glyph1-8" x="613.1875" y="108"/>
|
||||
<use xlink:href="#glyph1-9" x="618.089844" y="108"/>
|
||||
<use xlink:href="#glyph1-7" x="621.378906" y="108"/>
|
||||
<use xlink:href="#glyph1-10" x="624.515625" y="108"/>
|
||||
<use xlink:href="#glyph1-11" x="626.738281" y="108"/>
|
||||
<use xlink:href="#glyph1-12" x="631.808594" y="108"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1047.300781 113 L 1047.300781 107 "/>
|
||||
<g clip-path="url(#clip8)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-15" x="1049.300781" y="108"/>
|
||||
<use xlink:href="#glyph1-4" x="1054.390625" y="108"/>
|
||||
<use xlink:href="#glyph1-13" x="1056.933594" y="108"/>
|
||||
<use xlink:href="#glyph1-2" x="1062.011719" y="108"/>
|
||||
<use xlink:href="#glyph1-11" x="1066.90625" y="108"/>
|
||||
<use xlink:href="#glyph1-14" x="1071.976562" y="108"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 523.035156 46 L 523.035156 124 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 621.21875 142 L 622.960938 142 L 622.960938 156 L 621.21875 156 Z M 621.21875 142 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 622.960938 142 L 634.785156 142 L 634.785156 156 L 622.960938 156 Z M 622.960938 142 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 634.785156 142 L 838.511719 142 L 838.511719 156 L 634.785156 156 Z M 634.785156 142 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="636.785156" y="154"/>
|
||||
<use xlink:href="#glyph0-7" x="641.490234" y="154"/>
|
||||
<use xlink:href="#glyph0-2" x="646.423828" y="154"/>
|
||||
<use xlink:href="#glyph0-3" x="653.777344" y="154"/>
|
||||
<use xlink:href="#glyph0-19" x="660.375" y="154"/>
|
||||
<use xlink:href="#glyph0-20" x="667.757812" y="154"/>
|
||||
<use xlink:href="#glyph0-13" x="671.091797" y="154"/>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 838.515625 142 L 861.878906 142 L 861.878906 156 L 838.515625 156 Z M 838.515625 142 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 861.875 142 L 1071.8125 142 L 1071.8125 156 L 861.875 156 Z M 861.875 142 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1071.8125 142 L 1080.300781 142 L 1080.300781 156 L 1071.8125 156 Z M 1071.8125 142 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50%,90%,50%);fill-opacity:1;" d="M 1080.304688 142 L 1126.570312 142 L 1126.570312 156 L 1080.304688 156 Z M 1080.304688 142 "/>
|
||||
<g clip-path="url(#clip9)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-18" x="1082.304688" y="154"/>
|
||||
<use xlink:href="#glyph0-7" x="1087.009766" y="154"/>
|
||||
<use xlink:href="#glyph0-2" x="1091.943359" y="154"/>
|
||||
<use xlink:href="#glyph0-3" x="1099.296875" y="154"/>
|
||||
<use xlink:href="#glyph0-19" x="1105.894531" y="154"/>
|
||||
<use xlink:href="#glyph0-20" x="1113.277344" y="154"/>
|
||||
<use xlink:href="#glyph0-13" x="1116.611328" y="154"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,80%,40%);fill-opacity:1;" d="M 1126.566406 142 L 1134.214844 142 L 1134.214844 156 L 1126.566406 156 Z M 1126.566406 142 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(40%,40%,40%);fill-opacity:1;" d="M 1134.214844 142 L 1132.316406 142 L 1132.316406 156 L 1134.214844 156 Z M 1134.214844 142 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 817.433594 145 L 817.433594 139 "/>
|
||||
<g clip-path="url(#clip10)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="819.433594" y="140"/>
|
||||
<use xlink:href="#glyph1-2" x="821.792969" y="140"/>
|
||||
<use xlink:href="#glyph1-3" x="826.6875" y="140"/>
|
||||
<use xlink:href="#glyph1-4" x="831.765625" y="140"/>
|
||||
<use xlink:href="#glyph1-16" x="834.308594" y="140"/>
|
||||
<use xlink:href="#glyph1-4" x="839.398438" y="140"/>
|
||||
<use xlink:href="#glyph1-6" x="841.941406" y="140"/>
|
||||
<use xlink:href="#glyph1-7" x="846.109375" y="140"/>
|
||||
<use xlink:href="#glyph1-8" x="849.246094" y="140"/>
|
||||
<use xlink:href="#glyph1-9" x="854.148438" y="140"/>
|
||||
<use xlink:href="#glyph1-7" x="857.4375" y="140"/>
|
||||
<use xlink:href="#glyph1-10" x="860.574219" y="140"/>
|
||||
<use xlink:href="#glyph1-11" x="862.796875" y="140"/>
|
||||
<use xlink:href="#glyph1-12" x="867.867188" y="140"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1109.605469 145 L 1109.605469 139 "/>
|
||||
<g clip-path="url(#clip11)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-16" x="1111.605469" y="140"/>
|
||||
<use xlink:href="#glyph1-4" x="1116.695312" y="140"/>
|
||||
<use xlink:href="#glyph1-13" x="1119.238281" y="140"/>
|
||||
<use xlink:href="#glyph1-2" x="1124.316406" y="140"/>
|
||||
<use xlink:href="#glyph1-11" x="1129.210938" y="140"/>
|
||||
<use xlink:href="#glyph1-14" x="1134.28125" y="140"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 621.21875 46 L 621.21875 156 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 899.039062 49 L 899.039062 43 "/>
|
||||
<g clip-path="url(#clip12)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-17" x="901.039062" y="44"/>
|
||||
<use xlink:href="#glyph1-18" x="906.511719" y="44"/>
|
||||
<use xlink:href="#glyph1-18" x="908.734375" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="910.957031" y="44"/>
|
||||
<use xlink:href="#glyph1-19" x="913.5" y="44"/>
|
||||
<use xlink:href="#glyph1-20" x="917.898438" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="922.96875" y="44"/>
|
||||
<use xlink:href="#glyph1-18" x="925.191406" y="44"/>
|
||||
<use xlink:href="#glyph1-13" x="927.414062" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="932.492188" y="44"/>
|
||||
<use xlink:href="#glyph1-21" x="935.035156" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="937.851562" y="44"/>
|
||||
<use xlink:href="#glyph1-3" x="940.074219" y="44"/>
|
||||
<use xlink:href="#glyph1-14" x="945.152344" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="950.074219" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="953.363281" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="957.53125" y="44"/>
|
||||
<use xlink:href="#glyph1-21" x="960.074219" y="44"/>
|
||||
<use xlink:href="#glyph1-2" x="962.890625" y="44"/>
|
||||
<use xlink:href="#glyph1-9" x="967.785156" y="44"/>
|
||||
<use xlink:href="#glyph1-22" x="971.074219" y="44"/>
|
||||
<use xlink:href="#glyph1-14" x="975.707031" y="44"/>
|
||||
<use xlink:href="#glyph1-13" x="980.628906" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 46.675781 36 L 42.675781 36 L 42.675781 160 L 46.675781 160 "/>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1138.78125 36 L 1142.78125 36 L 1142.78125 160 L 1138.78125 160 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-6" x="44.675781" y="44"/>
|
||||
<use xlink:href="#glyph1-23" x="48.84375" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="55.386719" y="44"/>
|
||||
<use xlink:href="#glyph1-7" x="57.609375" y="44"/>
|
||||
<use xlink:href="#glyph1-19" x="60.746094" y="44"/>
|
||||
<use xlink:href="#glyph1-20" x="65.144531" y="44"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 1177.296875 49 L 1177.296875 43 "/>
|
||||
<g clip-path="url(#clip13)" clip-rule="nonzero">
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-24" x="1179.296875" y="44"/>
|
||||
<use xlink:href="#glyph1-23" x="1184.375" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1190.917969" y="44"/>
|
||||
<use xlink:href="#glyph1-7" x="1193.140625" y="44"/>
|
||||
<use xlink:href="#glyph1-19" x="1196.277344" y="44"/>
|
||||
<use xlink:href="#glyph1-20" x="1200.675781" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="1205.746094" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1208.289062" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1210.511719" y="44"/>
|
||||
<use xlink:href="#glyph1-4" x="1214.679688" y="44"/>
|
||||
<use xlink:href="#glyph1-21" x="1217.222656" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1220.039062" y="44"/>
|
||||
<use xlink:href="#glyph1-11" x="1222.261719" y="44"/>
|
||||
<use xlink:href="#glyph1-10" x="1227.332031" y="44"/>
|
||||
<use xlink:href="#glyph1-6" x="1229.554688" y="44"/>
|
||||
<use xlink:href="#glyph1-20" x="1233.722656" y="44"/>
|
||||
<use xlink:href="#glyph1-14" x="1238.792969" y="44"/>
|
||||
<use xlink:href="#glyph1-13" x="1243.714844" y="44"/>
|
||||
</g>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(40%,80%,40%);stroke-opacity:1;stroke-miterlimit:10;" d="M 10.746094 46 L 10.746094 60 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 61 KiB |
3
dune
3
dune
@ -1,5 +1,6 @@
|
||||
(mdx
|
||||
(package eio_main)
|
||||
(deps (package eio_main))
|
||||
(deps (package eio_main) (package kcas) (env_var "EIO_BACKEND"))
|
||||
(preludes doc/prelude.ml)
|
||||
(enabled_if (<> %{os_type} "Win32"))
|
||||
(files README.md))
|
||||
|
60
dune-project
60
dune-project
@ -1,6 +1,7 @@
|
||||
(lang dune 3.0)
|
||||
(lang dune 3.9)
|
||||
(name eio)
|
||||
(formatting disabled)
|
||||
(subst disabled)
|
||||
(generate_opam_files true)
|
||||
(source (github ocaml-multicore/eio))
|
||||
(license ISC)
|
||||
@ -11,12 +12,9 @@
|
||||
(name eio)
|
||||
(synopsis "Effect-based direct-style IO API for OCaml")
|
||||
(description "An effect-based IO API for multicore OCaml with fibers.")
|
||||
(conflicts
|
||||
(ocaml-base-compiler (< 5.0.0~beta1))
|
||||
(ocaml-variants (< 5.0.0~beta1))
|
||||
(ocaml-system (< 5.0.0~beta1)))
|
||||
(conflicts (seq (< 0.3)))
|
||||
(depends
|
||||
(ocaml (>= 5.0.0))
|
||||
(ocaml (>= 5.2.0))
|
||||
(bigstringaf (>= 0.9.0))
|
||||
(cstruct (>= 6.0.1))
|
||||
lwt-dllist
|
||||
@ -24,39 +22,57 @@
|
||||
(psq (>= 0.2.0))
|
||||
(fmt (>= 0.8.9))
|
||||
(hmap (>= 0.8.1))
|
||||
(domain-local-await (>= 0.1.0))
|
||||
(crowbar (and (>= 0.2) :with-test))
|
||||
(mtime (>= 2.0.0))
|
||||
(mdx (and (>= 1.10.0) :with-test))
|
||||
(alcotest (and (>= 1.4.0) :with-test))
|
||||
(mdx (and (>= 2.4.1) :with-test))
|
||||
(dscheck (and (>= 0.1.0) :with-test))))
|
||||
(package
|
||||
(name eio_linux)
|
||||
(synopsis "Eio implementation for Linux using io-uring")
|
||||
(description "An eio implementation for Linux using io-uring.")
|
||||
(description "An Eio implementation for Linux using io-uring.")
|
||||
(allow_empty) ; Work-around for dune bug #6938
|
||||
(depends
|
||||
(alcotest (and (>= 1.4.0) :with-test))
|
||||
(alcotest (and (>= 1.7.0) :with-test))
|
||||
(eio (= :version))
|
||||
(mdx (and (>= 1.10.0) :with-test))
|
||||
(logs (>= 0.7.0))
|
||||
(mdx (and (>= 2.4.1) :with-test))
|
||||
(logs (and (>= 0.7.0) :with-test))
|
||||
(fmt (>= 0.8.9))
|
||||
(cmdliner (and (>= 1.1.0) :with-test))
|
||||
(uring (>= 0.5))))
|
||||
(uring (>= 0.9))))
|
||||
(package
|
||||
(name eio_luv)
|
||||
(synopsis "Eio implementation using luv (libuv)")
|
||||
(description "An eio implementation for most platforms, using luv.")
|
||||
(name eio_posix)
|
||||
(allow_empty) ; Work-around for dune bug #6938
|
||||
(synopsis "Eio implementation for POSIX systems")
|
||||
(description "An Eio implementation for most Unix-like platforms")
|
||||
(depends
|
||||
(eio (= :version))
|
||||
(luv (>= 0.5.11))
|
||||
(luv_unix (>= 0.5.0))
|
||||
(mdx (and (>= 1.10.0) :with-test))
|
||||
(iomux (>= 0.2))
|
||||
(mdx (and (>= 2.4.1) :with-test))
|
||||
(conf-bash :with-test)
|
||||
(fmt (>= 0.8.9))))
|
||||
(package
|
||||
(name eio_windows)
|
||||
(synopsis "Eio implementation for Windows")
|
||||
(description "An Eio implementation using OCaml's Unix.select")
|
||||
(allow_empty) ; Work-around for dune bug #6938
|
||||
(depends
|
||||
(eio (= :version))
|
||||
(fmt (>= 0.8.9))
|
||||
(kcas (and (>= 0.3.0) :with-test))
|
||||
(alcotest (and (>= 1.7.0) :with-test))))
|
||||
(package
|
||||
(name eio_main)
|
||||
(synopsis "Effect-based direct-style IO mainloop for OCaml")
|
||||
(description "Selects an appropriate Eio backend for the current platform.")
|
||||
(depends
|
||||
(eio_linux (and (= :version) (= :os "linux")))
|
||||
(mdx (and (>= 1.10.0) :with-test))
|
||||
(eio_luv (= :version))))
|
||||
(mdx (and (>= 2.4.1) :with-test))
|
||||
(kcas (and (>= 0.3.0) :with-test))
|
||||
(yojson (and (>= 2.0.2) :with-test))
|
||||
(eio_linux (and
|
||||
(= :version)
|
||||
(= :os "linux")
|
||||
(or (<> :os-distribution "centos") (> :os-version 7))))
|
||||
(eio_posix (and (= :version) (<> :os "win32")))
|
||||
(eio_windows (and (= :version) (= :os "win32")))))
|
||||
(using mdx 0.2)
|
||||
|
13
eio.opam
13
eio.opam
@ -9,8 +9,8 @@ homepage: "https://github.com/ocaml-multicore/eio"
|
||||
doc: "https://ocaml-multicore.github.io/eio/"
|
||||
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
|
||||
depends: [
|
||||
"dune" {>= "3.0"}
|
||||
"ocaml" {>= "5.0.0"}
|
||||
"dune" {>= "3.9"}
|
||||
"ocaml" {>= "5.2.0"}
|
||||
"bigstringaf" {>= "0.9.0"}
|
||||
"cstruct" {>= "6.0.1"}
|
||||
"lwt-dllist"
|
||||
@ -18,20 +18,17 @@ depends: [
|
||||
"psq" {>= "0.2.0"}
|
||||
"fmt" {>= "0.8.9"}
|
||||
"hmap" {>= "0.8.1"}
|
||||
"domain-local-await" {>= "0.1.0"}
|
||||
"crowbar" {>= "0.2" & with-test}
|
||||
"mtime" {>= "2.0.0"}
|
||||
"mdx" {>= "1.10.0" & with-test}
|
||||
"alcotest" {>= "1.4.0" & with-test}
|
||||
"mdx" {>= "2.4.1" & with-test}
|
||||
"dscheck" {>= "0.1.0" & with-test}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
conflicts: [
|
||||
"ocaml-base-compiler" {< "5.0.0~beta1"}
|
||||
"ocaml-variants" {< "5.0.0~beta1"}
|
||||
"ocaml-system" {< "5.0.0~beta1"}
|
||||
"seq" {< "0.3"}
|
||||
]
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
[
|
||||
"dune"
|
||||
"build"
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file is generated by dune, edit dune-project instead
|
||||
opam-version: "2.0"
|
||||
synopsis: "Eio implementation for Linux using io-uring"
|
||||
description: "An eio implementation for Linux using io-uring."
|
||||
description: "An Eio implementation for Linux using io-uring."
|
||||
maintainer: ["anil@recoil.org"]
|
||||
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
|
||||
license: "ISC"
|
||||
@ -9,18 +9,17 @@ homepage: "https://github.com/ocaml-multicore/eio"
|
||||
doc: "https://ocaml-multicore.github.io/eio/"
|
||||
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
|
||||
depends: [
|
||||
"dune" {>= "3.0"}
|
||||
"alcotest" {>= "1.4.0" & with-test}
|
||||
"dune" {>= "3.9"}
|
||||
"alcotest" {>= "1.7.0" & with-test}
|
||||
"eio" {= version}
|
||||
"mdx" {>= "1.10.0" & with-test}
|
||||
"logs" {>= "0.7.0"}
|
||||
"mdx" {>= "2.4.1" & with-test}
|
||||
"logs" {>= "0.7.0" & with-test}
|
||||
"fmt" {>= "0.8.9"}
|
||||
"cmdliner" {>= "1.1.0" & with-test}
|
||||
"uring" {>= "0.5"}
|
||||
"uring" {>= "0.9"}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
[
|
||||
"dune"
|
||||
"build"
|
||||
@ -34,3 +33,4 @@ build: [
|
||||
]
|
||||
]
|
||||
dev-repo: "git+https://github.com/ocaml-multicore/eio.git"
|
||||
available: [os = "linux"]
|
||||
|
1
eio_linux.opam.template
Normal file
1
eio_linux.opam.template
Normal file
@ -0,0 +1 @@
|
||||
available: [os = "linux"]
|
@ -9,14 +9,18 @@ homepage: "https://github.com/ocaml-multicore/eio"
|
||||
doc: "https://ocaml-multicore.github.io/eio/"
|
||||
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
|
||||
depends: [
|
||||
"dune" {>= "3.0"}
|
||||
"eio_linux" {= version & os = "linux"}
|
||||
"mdx" {>= "1.10.0" & with-test}
|
||||
"eio_luv" {= version}
|
||||
"dune" {>= "3.9"}
|
||||
"mdx" {>= "2.4.1" & with-test}
|
||||
"kcas" {>= "0.3.0" & with-test}
|
||||
"yojson" {>= "2.0.2" & with-test}
|
||||
"eio_linux"
|
||||
{= version & os = "linux" &
|
||||
(os-distribution != "centos" | os-version > "7")}
|
||||
"eio_posix" {= version & os != "win32"}
|
||||
"eio_windows" {= version & os = "win32"}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
[
|
||||
"dune"
|
||||
"build"
|
||||
@ -30,3 +34,4 @@ build: [
|
||||
]
|
||||
]
|
||||
dev-repo: "git+https://github.com/ocaml-multicore/eio.git"
|
||||
x-ci-accept-failures: ["macos-homebrew"]
|
||||
|
1
eio_main.opam.template
Normal file
1
eio_main.opam.template
Normal file
@ -0,0 +1 @@
|
||||
x-ci-accept-failures: ["macos-homebrew"]
|
@ -1,7 +1,7 @@
|
||||
# This file is generated by dune, edit dune-project instead
|
||||
opam-version: "2.0"
|
||||
synopsis: "Eio implementation using luv (libuv)"
|
||||
description: "An eio implementation for most platforms, using luv."
|
||||
synopsis: "Eio implementation for POSIX systems"
|
||||
description: "An Eio implementation for most Unix-like platforms"
|
||||
maintainer: ["anil@recoil.org"]
|
||||
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
|
||||
license: "ISC"
|
||||
@ -9,16 +9,15 @@ homepage: "https://github.com/ocaml-multicore/eio"
|
||||
doc: "https://ocaml-multicore.github.io/eio/"
|
||||
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
|
||||
depends: [
|
||||
"dune" {>= "3.0"}
|
||||
"dune" {>= "3.9"}
|
||||
"eio" {= version}
|
||||
"luv" {>= "0.5.11"}
|
||||
"luv_unix" {>= "0.5.0"}
|
||||
"mdx" {>= "1.10.0" & with-test}
|
||||
"iomux" {>= "0.2"}
|
||||
"mdx" {>= "2.4.1" & with-test}
|
||||
"conf-bash" {with-test}
|
||||
"fmt" {>= "0.8.9"}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
[
|
||||
"dune"
|
||||
"build"
|
33
eio_windows.opam
Normal file
33
eio_windows.opam
Normal file
@ -0,0 +1,33 @@
|
||||
# This file is generated by dune, edit dune-project instead
|
||||
opam-version: "2.0"
|
||||
synopsis: "Eio implementation for Windows"
|
||||
description: "An Eio implementation using OCaml's Unix.select"
|
||||
maintainer: ["anil@recoil.org"]
|
||||
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
|
||||
license: "ISC"
|
||||
homepage: "https://github.com/ocaml-multicore/eio"
|
||||
doc: "https://ocaml-multicore.github.io/eio/"
|
||||
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
|
||||
depends: [
|
||||
"dune" {>= "3.9"}
|
||||
"eio" {= version}
|
||||
"fmt" {>= "0.8.9"}
|
||||
"kcas" {>= "0.3.0" & with-test}
|
||||
"alcotest" {>= "1.7.0" & with-test}
|
||||
"odoc" {with-doc}
|
||||
]
|
||||
build: [
|
||||
[
|
||||
"dune"
|
||||
"build"
|
||||
"-p"
|
||||
name
|
||||
"-j"
|
||||
jobs
|
||||
"@install"
|
||||
"@runtest" {with-test}
|
||||
"@doc" {with-doc}
|
||||
]
|
||||
]
|
||||
dev-repo: "git+https://github.com/ocaml-multicore/eio.git"
|
||||
#available: [os = "win32"]
|
1
eio_windows.opam.template
Normal file
1
eio_windows.opam.template
Normal file
@ -0,0 +1 @@
|
||||
#available: [os = "win32"]
|
3
examples/both/dune
Normal file
3
examples/both/dune
Normal file
@ -0,0 +1,3 @@
|
||||
(executable
|
||||
(name main)
|
||||
(libraries eio_main))
|
7
examples/both/main.ml
Normal file
7
examples/both/main.ml
Normal file
@ -0,0 +1,7 @@
|
||||
open Eio.Std
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun _env ->
|
||||
Fiber.both
|
||||
(fun () -> for x = 1 to 3 do traceln "x = %d" x; Fiber.yield () done)
|
||||
(fun () -> for y = 1 to 3 do traceln "y = %d" y; Fiber.yield () done)
|
3
examples/capsicum/dune
Normal file
3
examples/capsicum/dune
Normal file
@ -0,0 +1,3 @@
|
||||
(executable
|
||||
(name main)
|
||||
(libraries eio_main))
|
40
examples/capsicum/main.ml
Normal file
40
examples/capsicum/main.ml
Normal file
@ -0,0 +1,40 @@
|
||||
open Eio.Std
|
||||
|
||||
let ( / ) = Eio.Path.( / )
|
||||
|
||||
let test_eio dir =
|
||||
traceln "Using the file-system via the directory resource works:";
|
||||
let test_file = dir / "capsicum-test.txt" in
|
||||
traceln "Writing %a..." Eio.Path.pp test_file;
|
||||
Eio.Path.save test_file "A test file" ~create:(`Exclusive 0o644);
|
||||
traceln "Read: %S" (Eio.Path.load test_file);
|
||||
Eio.Path.unlink test_file
|
||||
|
||||
let test_legacy () =
|
||||
traceln "Bypassing Eio and accessing other resources should fail in Capsicum mode:";
|
||||
let ch = open_in "/etc/passwd" in
|
||||
let len = in_channel_length ch in
|
||||
let data = really_input_string ch len in
|
||||
close_in ch;
|
||||
traceln "Was able to read /etc/passwd:@.%s" (String.trim data)
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
(* Parse command-line arguments *)
|
||||
let path =
|
||||
match Sys.argv with
|
||||
| [| _; dir |] -> Eio.Stdenv.fs env / dir
|
||||
| _ -> failwith "Usage: main.exe DIR"
|
||||
in
|
||||
if not (Eio.Path.is_directory path) then Fmt.failwith "%a is not a directory" Eio.Path.pp path;
|
||||
(* Get access to resources before calling cap_enter: *)
|
||||
Eio.Path.with_open_dir path @@ fun dir ->
|
||||
traceln "Opened directory %a" Eio.Path.pp path;
|
||||
(* Switch to capability mode, if possible: *)
|
||||
begin match Eio_unix.Cap.enter () with
|
||||
| Ok () -> traceln "Capsicum mode enabled"
|
||||
| Error `Not_supported -> traceln "!! CAPSICUM PROTECTION NOT AVAILABLE !!"
|
||||
end;
|
||||
(* Run tests: *)
|
||||
test_eio dir;
|
||||
test_legacy ()
|
3
examples/fs/dune
Normal file
3
examples/fs/dune
Normal file
@ -0,0 +1,3 @@
|
||||
(executable
|
||||
(name main)
|
||||
(libraries eio_main))
|
32
examples/fs/main.ml
Normal file
32
examples/fs/main.ml
Normal file
@ -0,0 +1,32 @@
|
||||
(* Walk the directory tree rooted at the current directory,
|
||||
showing a summary for any .mli files. *)
|
||||
|
||||
let ( / ) = Eio.Path.( / )
|
||||
|
||||
let is_doc_comment = String.starts_with ~prefix:"(** "
|
||||
|
||||
(* Print the first line of [t]'s doc-comment, if any *)
|
||||
let scan_mli t f =
|
||||
Eio.Path.with_lines t (fun lines ->
|
||||
Seq.find is_doc_comment lines
|
||||
|> Option.iter (fun line ->
|
||||
let stop = String.index_from_opt line 4 '*' |> Option.value ~default:(String.length line) in
|
||||
Format.fprintf f "%a: %s@." Eio.Path.pp t (String.sub line 4 (stop - 4))
|
||||
)
|
||||
)
|
||||
|
||||
(* Walk the tree rooted at [t] and scan any .mli files found. *)
|
||||
let rec scan t f =
|
||||
match Eio.Path.kind ~follow:false t with
|
||||
| `Directory ->
|
||||
Eio.Path.read_dir t |> List.iter (function
|
||||
| "_build" | "_opam" -> () (* Don't examine these directories *)
|
||||
| item when String.starts_with ~prefix:"." item -> () (* Skip hidden items *)
|
||||
| item -> scan (t / item) f
|
||||
)
|
||||
| `Regular_file when Filename.check_suffix (snd t) ".mli" -> scan_mli t f
|
||||
| _ -> ()
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
scan (Eio.Stdenv.cwd env) Format.std_formatter
|
@ -8,8 +8,8 @@ module Write = Eio.Buf_write
|
||||
|
||||
(* Connect to [addr] on [net], send a message and then read the reply. *)
|
||||
let run ~net ~addr =
|
||||
Switch.run ~name:"client" @@ fun sw ->
|
||||
traceln "Connecting to server at %a..." Eio.Net.Sockaddr.pp addr;
|
||||
Switch.run @@ fun sw ->
|
||||
let flow = Eio.Net.connect ~sw net addr in
|
||||
(* We use a buffered writer here so we can create the message in multiple
|
||||
steps but still send it efficiently as a single packet: *)
|
||||
|
@ -4,7 +4,7 @@ let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, 8080)
|
||||
|
||||
(* Run a server and a test client, communicating using [net]. *)
|
||||
let main ~net =
|
||||
Switch.run @@ fun sw ->
|
||||
Switch.run ~name:"main" @@ fun sw ->
|
||||
(* We create the listening socket first so that we can be sure it is ready
|
||||
as soon as the client wants to use it. *)
|
||||
let listening_socket = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in
|
||||
|
3
examples/signals/dune
Normal file
3
examples/signals/dune
Normal file
@ -0,0 +1,3 @@
|
||||
(executable
|
||||
(name main)
|
||||
(libraries eio_main))
|
28
examples/signals/main.ml
Normal file
28
examples/signals/main.ml
Normal file
@ -0,0 +1,28 @@
|
||||
open Eio.Std
|
||||
|
||||
let load_config () =
|
||||
(* A real system would load the file and then pass it to the running service
|
||||
somehow, but we're just demonstrating signal handling so just sleep to
|
||||
simulate some time taken to load the new configuration. *)
|
||||
Eio_unix.sleep 2.0
|
||||
|
||||
(* $MDX part-begin=main *)
|
||||
let main ~config_changed =
|
||||
Eio.Condition.loop_no_mutex config_changed (fun () ->
|
||||
traceln "Reading configuration ('kill -SIGHUP %d' to reload)..." (Unix.getpid ());
|
||||
load_config ();
|
||||
traceln "Finished reading configuration";
|
||||
None (* Keep waiting for futher changes *)
|
||||
)
|
||||
(* $MDX part-end *)
|
||||
|
||||
let () =
|
||||
Eio_main.run @@ fun _env ->
|
||||
let config_changed = Eio.Condition.create () in
|
||||
let handle_signal (_signum : int) =
|
||||
(* Warning: we're in a signal handler now.
|
||||
Most operations are unsafe here, except for Eio.Condition.broadcast! *)
|
||||
Eio.Condition.broadcast config_changed
|
||||
in
|
||||
Sys.set_signal Sys.sighup (Signal_handle handle_signal);
|
||||
main ~config_changed
|
3
examples/trace/dune
Normal file
3
examples/trace/dune
Normal file
@ -0,0 +1,3 @@
|
||||
(executable
|
||||
(name main)
|
||||
(libraries eio.runtime_events eio_main))
|
69
examples/trace/main.ml
Normal file
69
examples/trace/main.ml
Normal file
@ -0,0 +1,69 @@
|
||||
(* This example shows how to trace an Eio program.
|
||||
|
||||
The [main] function creates a listening socket and has a client connect and send a message,
|
||||
which is handled by a server fiber.
|
||||
|
||||
At the same time, another fiber is displaying trace events.
|
||||
For simplicity, this example runs the tracer in the same process as the program being traced,
|
||||
but typically they would be separate processes. *)
|
||||
|
||||
open Eio.Std
|
||||
|
||||
let callbacks =
|
||||
Runtime_events.Callbacks.create ()
|
||||
(* Uncomment to trace GC events too: *)
|
||||
(*
|
||||
~runtime_begin:(handle (fun f phase -> Fmt.pf f "begin %s" (Runtime_events.runtime_phase_name phase)))
|
||||
~runtime_end:(handle (fun f phase -> Fmt.pf f "end %s" (Runtime_events.runtime_phase_name phase)))
|
||||
*)
|
||||
~lost_events:(fun ring n -> traceln "ring %d lost %d events" ring n)
|
||||
|> Eio_runtime_events.add_callbacks
|
||||
(fun ring ts e ->
|
||||
(* Note: don't use traceln here, as it will just generate more log events! *)
|
||||
Fmt.epr "%9Ld:ring %d: %a@." (Runtime_events.Timestamp.to_int64 ts) ring Eio_runtime_events.pp_event e
|
||||
)
|
||||
(* (see lib_eio/runtime_events/eio_runtime_events.mli for more event types) *)
|
||||
|
||||
(* Read and display trace events from [cursor] until [finished]. *)
|
||||
let trace ~finished (clock, delay) cursor =
|
||||
traceln "tracer: starting";
|
||||
let rec aux () =
|
||||
let _ : int = Runtime_events.read_poll cursor callbacks None in
|
||||
if !finished then (
|
||||
traceln "tracer: stopping"
|
||||
) else (
|
||||
Eio.Time.Mono.sleep clock delay;
|
||||
aux ()
|
||||
)
|
||||
in
|
||||
aux ()
|
||||
|
||||
(* The program to be traced. *)
|
||||
let main net =
|
||||
Switch.run ~name:"main" @@ fun sw ->
|
||||
let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, 8123) in
|
||||
let s = Eio.Net.listen ~sw ~backlog:1 ~reuse_addr:true net addr in
|
||||
Fiber.both
|
||||
(fun () ->
|
||||
traceln "server: starting";
|
||||
let c, _addr = Eio.Net.accept ~sw s in
|
||||
traceln "server: got connection from client";
|
||||
let msg = Eio.Flow.read_all c in
|
||||
traceln "server: read %S from socket" msg
|
||||
)
|
||||
(fun () ->
|
||||
traceln "client: connecting socket...";
|
||||
let c = Eio.Net.connect ~sw net addr in
|
||||
Eio.Flow.copy_string "Hello" c;
|
||||
Eio.Flow.close c
|
||||
)
|
||||
|
||||
(* Enable tracing then run the [main] and [trace] fibers. *)
|
||||
let () =
|
||||
Runtime_events.start ();
|
||||
let cursor = Runtime_events.create_cursor None in (* Create a in-process cursor *)
|
||||
Eio_main.run @@ fun env ->
|
||||
let finished = ref false in
|
||||
Fiber.both
|
||||
(fun () -> trace ~finished (env#mono_clock, 0.01) cursor)
|
||||
(fun () -> main env#net; finished := true)
|
@ -1,4 +1,4 @@
|
||||
(tests
|
||||
(package eio)
|
||||
(libraries cstruct crowbar fmt eio eio.mock)
|
||||
(names fuzz_buf_read fuzz_buf_write))
|
||||
(libraries cstruct crowbar fmt eio eio.mock eio.unix)
|
||||
(names fuzz_buf_read fuzz_buf_write fuzz_inherit_fds))
|
||||
|
@ -26,26 +26,30 @@ exception Buffer_limit_exceeded = Buf_read.Buffer_limit_exceeded
|
||||
let initial_size = 10
|
||||
let max_size = 100
|
||||
|
||||
let mock_flow next = object (self)
|
||||
inherit Eio.Flow.source
|
||||
module Mock_flow = struct
|
||||
type t = string list ref
|
||||
|
||||
val mutable next = next
|
||||
|
||||
method read_into buf =
|
||||
match next with
|
||||
let rec single_read t buf =
|
||||
match !t with
|
||||
| [] ->
|
||||
raise End_of_file
|
||||
| "" :: xs ->
|
||||
next <- xs;
|
||||
self#read_into buf
|
||||
t := xs;
|
||||
single_read t buf
|
||||
| x :: xs ->
|
||||
let len = min (Cstruct.length buf) (String.length x) in
|
||||
Cstruct.blit_from_string x 0 buf 0 len;
|
||||
let x' = String.drop x len in
|
||||
next <- (if x' = "" then xs else x' :: xs);
|
||||
t := (if x' = "" then xs else x' :: xs);
|
||||
len
|
||||
|
||||
let read_methods = []
|
||||
end
|
||||
|
||||
let mock_flow =
|
||||
let ops = Eio.Flow.Pi.source (module Mock_flow) in
|
||||
fun chunks -> Eio.Resource.T (ref chunks, ops)
|
||||
|
||||
module Model = struct
|
||||
type t = string ref
|
||||
|
||||
|
46
fuzz/fuzz_inherit_fds.ml
Normal file
46
fuzz/fuzz_inherit_fds.ml
Normal file
@ -0,0 +1,46 @@
|
||||
module I = Eio_unix__Inherit_fds
|
||||
|
||||
module S = Set.Make(Int)
|
||||
|
||||
let pp f = function
|
||||
| `Cloexec x -> Fmt.pf f "close %d" x
|
||||
| `Keep x -> Fmt.pf f "keep %d" x
|
||||
|
||||
let rec has_duplicates ~seen = function
|
||||
| [] -> false
|
||||
| (dst, _) :: _ when S.mem dst seen -> true
|
||||
| (dst, _) :: xs -> has_duplicates xs ~seen:(S.add dst seen)
|
||||
|
||||
let inherit_fds mapping =
|
||||
let has_duplicates = has_duplicates ~seen:S.empty mapping in
|
||||
let fds = Hashtbl.create 10 in
|
||||
mapping |> List.iter (fun (_dst, src) ->
|
||||
Hashtbl.add fds src (`Cloexec src);
|
||||
);
|
||||
match I.plan mapping with
|
||||
| exception (Invalid_argument _) -> assert has_duplicates
|
||||
| plan ->
|
||||
assert (not has_duplicates);
|
||||
plan |> List.iter (fun {I.src; dst} ->
|
||||
(* Fmt.pr "%d -> %d@." src dst; *)
|
||||
let v =
|
||||
match Hashtbl.find fds src with
|
||||
| `Cloexec x | `Keep x ->
|
||||
if dst = -1 then `Cloexec x else `Keep x
|
||||
in
|
||||
Hashtbl.add fds dst v
|
||||
);
|
||||
mapping |> List.iter (fun (dst, src) ->
|
||||
let v = Hashtbl.find fds dst in
|
||||
Crowbar.check_eq ~pp v (`Keep src);
|
||||
Hashtbl.remove fds dst;
|
||||
);
|
||||
fds |> Hashtbl.iter (fun x -> function
|
||||
| `Cloexec _ -> ()
|
||||
| `Keep _ -> Fmt.failwith "%d should be close-on-exec!" x
|
||||
)
|
||||
|
||||
let fd = Crowbar.range 10 (* Restrict range to make cycles more likely *)
|
||||
|
||||
let () =
|
||||
Crowbar.(add_test ~name:"inherit_fds" [list (pair fd fd)] inherit_fds)
|
@ -1,11 +1,13 @@
|
||||
exception Buffer_limit_exceeded
|
||||
|
||||
open Std
|
||||
|
||||
type t = {
|
||||
mutable buf : Cstruct.buffer;
|
||||
mutable pos : int;
|
||||
mutable len : int;
|
||||
mutable flow : Flow.source option; (* None if we've seen eof *)
|
||||
mutable consumed : int; (* Total bytes consumed so far *)
|
||||
mutable flow : Flow.source_ty r option; (* None if we've seen eof *)
|
||||
mutable consumed : int; (* Total bytes consumed so far *)
|
||||
max_size : int;
|
||||
}
|
||||
|
||||
@ -45,7 +47,7 @@ open Syntax
|
||||
let capacity t = Bigarray.Array1.dim t.buf
|
||||
|
||||
let of_flow ?initial_size ~max_size flow =
|
||||
let flow = (flow :> Flow.source) in
|
||||
let flow = (flow :> Flow.source_ty r) in
|
||||
if max_size <= 0 then Fmt.invalid_arg "Max size %d should be positive!" max_size;
|
||||
let initial_size = Option.value initial_size ~default:(min 4096 max_size) in
|
||||
let buf = Bigarray.(Array1.create char c_layout initial_size) in
|
||||
@ -128,17 +130,28 @@ let ensure_slow_path t n =
|
||||
let ensure t n =
|
||||
if t.len < n then ensure_slow_path t n
|
||||
|
||||
let as_flow t =
|
||||
object
|
||||
inherit Flow.source
|
||||
module F = struct
|
||||
type nonrec t = t
|
||||
|
||||
method read_into dst =
|
||||
ensure t 1;
|
||||
let len = min (buffered_bytes t) (Cstruct.length dst) in
|
||||
Cstruct.blit (peek t) 0 dst 0 len;
|
||||
consume t len;
|
||||
len
|
||||
end
|
||||
let single_read t dst =
|
||||
ensure t 1;
|
||||
let len = min (buffered_bytes t) (Cstruct.length dst) in
|
||||
Cstruct.blit (peek t) 0 dst 0 len;
|
||||
consume t len;
|
||||
len
|
||||
|
||||
let rsb t fn =
|
||||
ensure t 1;
|
||||
let data = peek t in
|
||||
let sent = fn [data] in
|
||||
consume t sent
|
||||
|
||||
let read_methods = [Flow.Read_source_buffer rsb]
|
||||
end
|
||||
|
||||
let as_flow =
|
||||
let ops = Flow.Pi.source (module F) in
|
||||
fun t -> Resource.T (t, ops)
|
||||
|
||||
let get t i =
|
||||
Bigarray.Array1.get t.buf (t.pos + i)
|
||||
|
@ -9,6 +9,8 @@
|
||||
]}
|
||||
*)
|
||||
|
||||
open Std
|
||||
|
||||
type t
|
||||
(** An input buffer. *)
|
||||
|
||||
@ -21,18 +23,18 @@ type 'a parser = t -> 'a
|
||||
@raise End_of_file The flow ended without enough data to parse an ['a].
|
||||
@raise Buffer_limit_exceeded Parsing the value would exceed the configured size limit. *)
|
||||
|
||||
val parse : ?initial_size:int -> max_size:int -> 'a parser -> #Flow.source -> ('a, [> `Msg of string]) result
|
||||
val parse : ?initial_size:int -> max_size:int -> 'a parser -> _ Flow.source -> ('a, [> `Msg of string]) result
|
||||
(** [parse p flow ~max_size] uses [p] to parse everything in [flow].
|
||||
|
||||
It is a convenience function that does
|
||||
{[
|
||||
let buf = of_flow flow ~max_size in
|
||||
format_errors (p <* eof) buf
|
||||
format_errors (p <* end_of_input) buf
|
||||
]}
|
||||
|
||||
@param initial_size see {!of_flow}. *)
|
||||
|
||||
val parse_exn : ?initial_size:int -> max_size:int -> 'a parser -> #Flow.source -> 'a
|
||||
val parse_exn : ?initial_size:int -> max_size:int -> 'a parser -> _ Flow.source -> 'a
|
||||
(** [parse_exn] wraps {!parse}, but raises [Failure msg] if that returns [Error (`Msg msg)].
|
||||
|
||||
Catching exceptions with [parse] and then raising them might seem pointless,
|
||||
@ -46,7 +48,7 @@ val parse_string : 'a parser -> string -> ('a, [> `Msg of string]) result
|
||||
val parse_string_exn : 'a parser -> string -> 'a
|
||||
(** [parse_string_exn] is like {!parse_string}, but handles errors like {!parse_exn}. *)
|
||||
|
||||
val of_flow : ?initial_size:int -> max_size:int -> #Flow.source -> t
|
||||
val of_flow : ?initial_size:int -> max_size:int -> _ Flow.source -> t
|
||||
(** [of_flow ~max_size flow] is a buffered reader backed by [flow].
|
||||
|
||||
@param initial_size The initial amount of memory to allocate for the buffer.
|
||||
@ -68,7 +70,7 @@ val of_buffer : Cstruct.buffer -> t
|
||||
val of_string : string -> t
|
||||
(** [of_string s] is a reader that reads from [s]. *)
|
||||
|
||||
val as_flow : t -> Flow.source
|
||||
val as_flow : t -> Flow.source_ty r
|
||||
(** [as_flow t] is a buffered flow.
|
||||
|
||||
Reading from it will return data from the buffer,
|
||||
@ -216,6 +218,13 @@ val seq : ?stop:bool parser -> 'a parser -> 'a Seq.t parser
|
||||
It is not necessary to consume all the elements of the
|
||||
sequence.
|
||||
|
||||
Example ([head 4] is a parser that takes 4 lines):
|
||||
|
||||
{[
|
||||
let head n r =
|
||||
r |> Buf_read.(seq line) |> Seq.take n |> List.of_seq
|
||||
]}
|
||||
|
||||
@param stop This is used before parsing each item.
|
||||
The sequence ends if this returns [true].
|
||||
The default is {!at_end_of_input}. *)
|
||||
|
@ -163,7 +163,7 @@ type t =
|
||||
; mutable bytes_written : int (* Total written bytes. Wraps. *)
|
||||
; mutable state : state
|
||||
; mutable wake_writer : unit -> unit
|
||||
; id : Ctf.id
|
||||
; mutable printf : (Format.formatter * bool ref) option
|
||||
}
|
||||
(* Invariant: [write_pos >= scheduled_pos] *)
|
||||
|
||||
@ -378,7 +378,7 @@ let of_buffer ?sw buffer =
|
||||
; bytes_written = 0
|
||||
; state = Active
|
||||
; wake_writer = ignore
|
||||
; id = Ctf.mint_id ()
|
||||
; printf = None
|
||||
}
|
||||
in
|
||||
begin match sw with
|
||||
@ -418,6 +418,39 @@ let flush t =
|
||||
Promise.await_exn p
|
||||
)
|
||||
|
||||
let make_formatter t =
|
||||
Format.make_formatter
|
||||
(fun buf off len -> write_gen t buf ~off ~len ~blit:Bigstringaf.blit_from_string)
|
||||
(fun () -> flush t)
|
||||
|
||||
let printf t =
|
||||
let ppf, is_formatting =
|
||||
match t.printf with
|
||||
| Some (_, is_formatting as x) ->
|
||||
is_formatting := true;
|
||||
x
|
||||
| None ->
|
||||
let is_formatting = ref true in
|
||||
let ppf =
|
||||
Format.make_formatter
|
||||
(fun buf off len -> write_gen t buf ~off ~len ~blit:Bigstringaf.blit_from_string)
|
||||
(fun () ->
|
||||
(* As per the Format module manual, an explicit flush writes to the
|
||||
output channel and ensures that "all pending text is displayed"
|
||||
and "these explicit flush calls [...] could dramatically impact efficiency".
|
||||
Therefore it is clear that we need to call `flush t` instead of `flush_buffer t`. *)
|
||||
if !is_formatting then flush t)
|
||||
in
|
||||
t.printf <- Some (ppf, is_formatting);
|
||||
ppf, is_formatting
|
||||
in
|
||||
Format.kfprintf (fun ppf ->
|
||||
if not !is_formatting then raise (Sys_error "Buf_write.printf: invalid concurrent access");
|
||||
(* Ensure that [ppf]'s internal buffer is flushed to [t], but without flushing [t] itself: *)
|
||||
is_formatting := false;
|
||||
Format.pp_print_flush ppf ()
|
||||
) ppf
|
||||
|
||||
let rec shift_buffers t written =
|
||||
match Buffers.dequeue_exn t.scheduled with
|
||||
| { Cstruct.len; _ } as iovec ->
|
||||
@ -458,7 +491,7 @@ let rec await_batch t =
|
||||
| Closed, false -> raise End_of_file
|
||||
| (Active | Closed), true -> Buffers.to_list t.scheduled
|
||||
| Paused, _ | Active, false ->
|
||||
Suspend.enter (fun ctx enqueue ->
|
||||
Suspend.enter "Buf_write.await_batch" (fun ctx enqueue ->
|
||||
Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
t.wake_writer <- ignore;
|
||||
enqueue (Error ex)
|
||||
@ -471,27 +504,21 @@ let rec await_batch t =
|
||||
);
|
||||
await_batch t
|
||||
|
||||
let read_into t buf =
|
||||
let iovecs = await_batch t in
|
||||
let n, _iovecs = Cstruct.fillv ~src:iovecs ~dst:buf in
|
||||
shift t n;
|
||||
n
|
||||
|
||||
let read_source_buffer t fn =
|
||||
let iovecs = await_batch t in
|
||||
shift t (fn iovecs)
|
||||
|
||||
let as_flow t =
|
||||
object
|
||||
inherit Flow.source
|
||||
method! read_methods = [Flow.Read_source_buffer (read_source_buffer t)]
|
||||
method read_into = read_into t
|
||||
end
|
||||
(* We have to do our own copy, because we can't [shift] until the write is complete. *)
|
||||
let copy t flow =
|
||||
let rec aux () =
|
||||
let iovecs = await_batch t in
|
||||
let wrote = Flow.single_write flow iovecs in
|
||||
shift t wrote;
|
||||
aux ()
|
||||
in
|
||||
try aux ()
|
||||
with End_of_file -> ()
|
||||
|
||||
let with_flow ?(initial_size=0x1000) flow fn =
|
||||
Switch.run @@ fun sw ->
|
||||
Switch.run ~name:"Buf_write.with_flow" @@ fun sw ->
|
||||
let t = create ~sw initial_size in
|
||||
Fiber.fork ~sw (fun () -> Flow.copy (as_flow t) flow);
|
||||
Fiber.fork ~sw (fun () -> copy t flow);
|
||||
match fn t with
|
||||
| x ->
|
||||
close t;
|
||||
|
@ -46,7 +46,7 @@
|
||||
or application-specific output APIs.
|
||||
|
||||
A Buf_write serializer manages an internal buffer and a queue of output
|
||||
buffers. The output bufferes may be a sub range of the serializer's
|
||||
buffers. The output buffers may be a sub range of the serializer's
|
||||
internal buffer or one that is user-provided. Buffered writes such as
|
||||
{!string}, {!char}, {!cstruct}, etc., copy the source bytes into the
|
||||
serializer's internal buffer. Unbuffered writes are done with
|
||||
@ -85,7 +85,7 @@ exception Flush_aborted
|
||||
|
||||
(** {2 Running} *)
|
||||
|
||||
val with_flow : ?initial_size:int -> #Flow.sink -> (t -> 'a) -> 'a
|
||||
val with_flow : ?initial_size:int -> _ Flow.sink -> (t -> 'a) -> 'a
|
||||
(** [with_flow flow fn] runs [fn writer], where [writer] is a buffer that flushes to [flow].
|
||||
|
||||
Concurrently with [fn], it also runs a fiber that copies from [writer] to [flow].
|
||||
@ -123,6 +123,18 @@ val cstruct : t -> Cstruct.t -> unit
|
||||
It is safe to modify [cs] after this call returns.
|
||||
For large cstructs, it may be more efficient to use {!schedule_cstruct}. *)
|
||||
|
||||
val printf : t -> ('a, Format.formatter, unit) format -> 'a
|
||||
(** [printf t fmt ...] formats the arguments according to the format string [fmt].
|
||||
|
||||
It supports all formatting and pretty-printing features of the Format module.
|
||||
The formatter's internal buffer is flushed to [t] after the call, without flushing [t] itself.
|
||||
Explicit flushes (e.g. using [@.] or [%!]) perform a full (blocking) flush of [t]. *)
|
||||
|
||||
val make_formatter : t -> Format.formatter
|
||||
(** [make_formatter t] creates a new formatter that writes to [t].
|
||||
|
||||
Flushing the formatter also flushes [t] itself. *)
|
||||
|
||||
val write_gen
|
||||
: t
|
||||
-> blit:('a -> src_off:int -> Cstruct.buffer -> dst_off:int -> len:int -> unit)
|
||||
|
@ -1,10 +1,18 @@
|
||||
(* Import these directly because we copy this file for the dscheck tests. *)
|
||||
module Fiber_context = Eio__core.Private.Fiber_context
|
||||
module Suspend = Eio__core.Private.Suspend
|
||||
module Cancel = Eio__core.Cancel
|
||||
|
||||
type t = Broadcast.t
|
||||
|
||||
let create () = Broadcast.create ()
|
||||
|
||||
let lock_protected m =
|
||||
Cancel.protect (fun () -> Eio_mutex.lock m)
|
||||
|
||||
let await_generic ?mutex t =
|
||||
match
|
||||
Suspend.enter_unchecked (fun ctx enqueue ->
|
||||
Suspend.enter_unchecked "Condition.await" (fun ctx enqueue ->
|
||||
match Fiber_context.get_error ctx with
|
||||
| Some ex ->
|
||||
Option.iter Eio_mutex.unlock mutex;
|
||||
@ -21,13 +29,91 @@ let await_generic ?mutex t =
|
||||
)
|
||||
)
|
||||
with
|
||||
| () -> Option.iter Eio_mutex.lock mutex
|
||||
| () -> Option.iter lock_protected mutex
|
||||
| exception ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
Option.iter Eio_mutex.lock mutex;
|
||||
Option.iter lock_protected mutex;
|
||||
Printexc.raise_with_backtrace ex bt
|
||||
|
||||
let await t mutex = await_generic ~mutex t
|
||||
let await_no_mutex t = await_generic t
|
||||
|
||||
let broadcast = Broadcast.resume_all
|
||||
|
||||
type request = Broadcast.request option
|
||||
|
||||
let register_immediate = Broadcast.suspend
|
||||
|
||||
let cancel = function
|
||||
| Some request -> Broadcast.cancel request
|
||||
| None -> false
|
||||
|
||||
let ensure_cancelled x = ignore (cancel x : bool)
|
||||
|
||||
type state =
|
||||
| Init
|
||||
| Waiting of ((unit, exn) result -> unit)
|
||||
| Done
|
||||
|
||||
(* There main property want is that we don't suspend forever if a broadcast
|
||||
happened after [fn] started, or if the fiber is cancelled.
|
||||
|
||||
1. We start in the Init state.
|
||||
2. If a broadcast happens here we move to Done. If we later try to suspend, we'll resume immediately.
|
||||
3. We run [fn]. If a broadcast happens during this we'll transition to Done as before.
|
||||
4. If [fn] raises or wants to stop normally, we return without suspending at all.
|
||||
5. Otherwise, we suspend the fiber.
|
||||
6. We try to transition from Init to Waiting.
|
||||
If a broadcast transitioned to Done before this, we resume immediately.
|
||||
If a broadcast transitions afterwards, [wake] will see the [enqueue] function and wake us.
|
||||
Therefore, we can only sleep forever if a broadcast never happens after starting [fn].
|
||||
7. If the fiber is cancelled before suspending, we raise on suspend.
|
||||
If cancelled after suspending and before the request succeeds, we cancel the request and raise.
|
||||
If cancelled after the request succeeds, [wake] will resume us.
|
||||
*)
|
||||
let rec loop_no_mutex t fn =
|
||||
let state = Atomic.make Init in
|
||||
let wake () =
|
||||
match Atomic.exchange state Done with
|
||||
| Init -> () (* Broadcast happened before we suspended; suspend will notice *)
|
||||
| Waiting enqueue -> enqueue (Ok ())
|
||||
| Done -> assert false
|
||||
in
|
||||
let request = Broadcast.suspend t wake in
|
||||
(* Note: to avoid memory leaks, make sure that [request] is finished in all cases. *)
|
||||
match fn () with
|
||||
| exception ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
ensure_cancelled request;
|
||||
Printexc.raise_with_backtrace ex bt
|
||||
| Some x ->
|
||||
ensure_cancelled request;
|
||||
x
|
||||
| None ->
|
||||
Suspend.enter_unchecked "Condition.loop_no_mutex" (fun ctx enqueue ->
|
||||
match Fiber_context.get_error ctx with
|
||||
| Some ex ->
|
||||
ensure_cancelled request;
|
||||
(* If a broadcast already happened, we still cancel. *)
|
||||
enqueue (Error ex)
|
||||
| None ->
|
||||
let waiting = Waiting enqueue in
|
||||
if Atomic.compare_and_set state Init waiting then (
|
||||
(* We were in Init, so [wake] hasn't yet done anything.
|
||||
When it runs, it will resume us.
|
||||
We're also not currently cancelled, because we checked above
|
||||
and cancellations only come from the same thread. *)
|
||||
Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
if cancel request then (
|
||||
(* We could set the state to Done here, but there's no need;
|
||||
we're not racing with anything now. [wake] never runs. *)
|
||||
enqueue (Error ex)
|
||||
) (* else we already got resumed *)
|
||||
)
|
||||
) else (
|
||||
(* State is already Done, but [wake] couldn't wake us then
|
||||
because we hadn't moved to [waiting]. Resume now. *)
|
||||
enqueue (Ok ())
|
||||
)
|
||||
);
|
||||
loop_no_mutex t fn
|
||||
|
@ -16,7 +16,7 @@
|
||||
let await_x p =
|
||||
Eio.Mutex.use_ro mutex (fun () ->
|
||||
while not (p !x) do (* [x] cannot change, as mutex is locked. *)
|
||||
Eio.Condition.await ~mutex cond (* Mutex is unlocked while suspended. *)
|
||||
Eio.Condition.await cond mutex (* Mutex is unlocked while suspended. *)
|
||||
done
|
||||
)
|
||||
]}
|
||||
@ -60,7 +60,44 @@ val await_no_mutex : t -> unit
|
||||
i.e. you know the condition is still false, and no notification of a change can be sent
|
||||
until [await_no_mutex] has finished suspending the fiber. *)
|
||||
|
||||
val loop_no_mutex : t -> (unit -> 'a option) -> 'a
|
||||
(** [loop_no_mutex t update] runs [update ()] until it returns [Some x], then returns [x].
|
||||
|
||||
If [update ()] returns [None] then it waits until {!broadcast} is called before retrying.
|
||||
If {!broadcast} is called while [update] is running, [update] runs again immediately.
|
||||
|
||||
For example, if [broadcast config_changed] is performed after some configuration file is changed, then
|
||||
you can ensure [load_config] will always eventually have seen the latest configuration like this:
|
||||
|
||||
{[
|
||||
Fiber.fork_daemon ~sw (fun () ->
|
||||
loop_no_mutex config_changed (fun () -> load_config (); None)
|
||||
)
|
||||
]}
|
||||
|
||||
Note that, since there is no lock, [load_config] may see a half-written update if the configuration
|
||||
is changed again before it finishes reading it,
|
||||
so it should just log the error and wait to be called again. *)
|
||||
|
||||
val broadcast : t -> unit
|
||||
(** [broadcast t] wakes up any waiting fibers (by appending them to the run-queue to resume later).
|
||||
|
||||
If no fibers are waiting, nothing happens. *)
|
||||
|
||||
(** {2 Low-level API}
|
||||
|
||||
This is intended only for integrating Eio with other IO libraries. *)
|
||||
|
||||
type request
|
||||
|
||||
val register_immediate : t -> (unit -> unit) -> request
|
||||
(** [register_immediate t fn] will call [fn ()] the next time {!broadcast} is called.
|
||||
|
||||
[fn] runs immediately from the caller's context, which might not be an Eio thread, or may be a signal handler, etc.
|
||||
Therefore, care is needed here. This is typically used to send a wake-up event to some non-Eio library. *)
|
||||
|
||||
val cancel : request -> bool
|
||||
(** [cancel request] tries to cancel a request created with {!register_unsafe}.
|
||||
|
||||
It returns [true] if the request was cancelled (the callback will never be called),
|
||||
or [false] if the request was already complete (the callback has already been called). *)
|
||||
|
@ -1,5 +1,4 @@
|
||||
exception Cancelled = Exn.Cancelled
|
||||
exception Cancel_hook_failed = Exn.Cancel_hook_failed
|
||||
|
||||
type state =
|
||||
| On
|
||||
@ -15,6 +14,7 @@ type state =
|
||||
If a function can succeed in a separate domain,
|
||||
the user's cancel function is responsible for ensuring that this is done atomically. *)
|
||||
type t = {
|
||||
id : Trace.id;
|
||||
mutable state : state;
|
||||
children : t Lwt_dllist.t;
|
||||
fibers : fiber_context Lwt_dllist.t;
|
||||
@ -22,7 +22,7 @@ type t = {
|
||||
domain : Domain.id; (* Prevent access from other domains *)
|
||||
}
|
||||
and fiber_context = {
|
||||
tid : Ctf.id;
|
||||
tid : Trace.id;
|
||||
mutable cancel_context : t;
|
||||
mutable cancel_node : fiber_context Lwt_dllist.node option; (* Our entry in [cancel_context.fibers] *)
|
||||
mutable cancel_fn : exn -> unit; (* Encourage the current operation to finish *)
|
||||
@ -90,10 +90,12 @@ let move_fiber_to t fiber =
|
||||
fiber.cancel_node <- Some new_node
|
||||
|
||||
(* Note: the new value is not linked into the cancellation tree. *)
|
||||
let create ~protected =
|
||||
let create ~protected purpose =
|
||||
let children = Lwt_dllist.create () in
|
||||
let fibers = Lwt_dllist.create () in
|
||||
{ state = Finished; children; protected; fibers; domain = Domain.self () }
|
||||
let id = Trace.mint_id () in
|
||||
Trace.create_cc id purpose;
|
||||
{ id; state = Finished; children; protected; fibers; domain = Domain.self () }
|
||||
|
||||
(* Links [t] into the tree as a child of [parent] and returns a function to remove it again. *)
|
||||
let activate t ~parent =
|
||||
@ -107,19 +109,19 @@ let activate t ~parent =
|
||||
Lwt_dllist.remove node
|
||||
|
||||
(* Runs [fn] with a fresh cancellation context. *)
|
||||
let with_cc ~ctx:fiber ~parent ~protected fn =
|
||||
let with_cc ~ctx:fiber ~parent ~protected purpose fn =
|
||||
if not protected then check parent;
|
||||
let t = create ~protected in
|
||||
let t = create ~protected purpose in
|
||||
let deactivate = activate t ~parent in
|
||||
move_fiber_to t fiber;
|
||||
let cleanup () = move_fiber_to parent fiber; deactivate () in
|
||||
match fn t with
|
||||
| x -> cleanup (); x
|
||||
| exception ex -> cleanup (); raise ex
|
||||
| x -> cleanup (); Trace.exit_cc (); x
|
||||
| exception ex -> cleanup (); Trace.exit_cc (); raise ex
|
||||
|
||||
let protect fn =
|
||||
let ctx = Effect.perform Get_context in
|
||||
with_cc ~ctx ~parent:ctx.cancel_context ~protected:true @@ fun _ ->
|
||||
with_cc ~ctx ~parent:ctx.cancel_context ~protected:true Protect @@ fun _ ->
|
||||
(* Note: there is no need to check the new context after [fn] returns;
|
||||
the goal of cancellation is only to finish the thread promptly, not to report the error.
|
||||
We also do not check the parent context, to make sure the caller has a chance to handle the result. *)
|
||||
@ -136,6 +138,7 @@ let rec cancel_internal t ex acc_fibers =
|
||||
| On ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
t.state <- Cancelling (ex, bt);
|
||||
Trace.error t.id ex;
|
||||
let acc_fibers = Lwt_dllist.fold_r List.cons t.fibers acc_fibers in
|
||||
Lwt_dllist.fold_r (cancel_child ex) t.children acc_fibers
|
||||
and cancel_child ex t acc =
|
||||
@ -156,26 +159,34 @@ let cancel t ex =
|
||||
x.cancel_fn <- ignore;
|
||||
match fn cex with
|
||||
| () -> aux xs
|
||||
| exception ex2 -> ex2 :: aux xs
|
||||
| exception ex2 ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
(ex2, bt) :: aux xs
|
||||
in
|
||||
if fibers <> [] then (
|
||||
match aux fibers with
|
||||
| [] -> ()
|
||||
| exns -> raise (Cancel_hook_failed exns)
|
||||
| ex :: exs ->
|
||||
let ex, bt = List.fold_left Exn.combine ex exs in
|
||||
Printexc.raise_with_backtrace ex bt
|
||||
)
|
||||
|
||||
let sub fn =
|
||||
let sub_checked ?name purpose fn =
|
||||
let ctx = Effect.perform Get_context in
|
||||
let parent = ctx.cancel_context in
|
||||
with_cc ~ctx ~parent ~protected:false @@ fun t ->
|
||||
with_cc ~ctx ~parent ~protected:false purpose @@ fun t ->
|
||||
Option.iter (Trace.name t.id) name;
|
||||
fn t
|
||||
|
||||
let sub fn =
|
||||
sub_checked Sub fn
|
||||
|
||||
(* Like [sub], but it's OK if the new context is cancelled.
|
||||
(instead, return the parent context on exit so the caller can check that) *)
|
||||
let sub_unchecked fn =
|
||||
let sub_unchecked purpose fn =
|
||||
let ctx = Effect.perform Get_context in
|
||||
let parent = ctx.cancel_context in
|
||||
with_cc ~ctx ~parent ~protected:false @@ fun t ->
|
||||
with_cc ~ctx ~parent ~protected:false purpose @@ fun t ->
|
||||
fn t;
|
||||
parent
|
||||
|
||||
@ -194,18 +205,19 @@ module Fiber_context = struct
|
||||
t.cancel_fn <- ignore
|
||||
|
||||
let make ~cc ~vars =
|
||||
let tid = Ctf.mint_id () in
|
||||
Ctf.note_created tid Ctf.Task;
|
||||
let tid = Trace.mint_id () in
|
||||
Trace.create_fiber tid ~cc:cc.id;
|
||||
let t = { tid; cancel_context = cc; cancel_node = None; cancel_fn = ignore; vars } in
|
||||
t.cancel_node <- Some (Lwt_dllist.add_r t cc.fibers);
|
||||
t
|
||||
|
||||
let make_root () =
|
||||
let cc = create ~protected:false in
|
||||
let cc = create ~protected:false Root in
|
||||
cc.state <- On;
|
||||
make ~cc ~vars:Hmap.empty
|
||||
|
||||
let destroy t =
|
||||
Trace.exit_fiber t.tid;
|
||||
Option.iter Lwt_dllist.remove t.cancel_node
|
||||
|
||||
let vars t = t.vars
|
||||
|
@ -1,462 +0,0 @@
|
||||
(* Copyright (C) 2014, Thomas Leonard *)
|
||||
|
||||
(* Note: we expect some kind of logger to process the trace buffer to collect
|
||||
events, but currently we don't have any barriers to ensure that the buffer
|
||||
is in a consistent state (although it usually is). So for now, you should
|
||||
pause tracing before trying to parse the buffer. In particular, GC events
|
||||
complicate things because we may need to add a GC event while in the middle
|
||||
of adding some other event. *)
|
||||
|
||||
open Bigarray
|
||||
|
||||
module BS = struct
|
||||
(* Replacement for endianBigstring that avoids pulling in a Unix dependency *)
|
||||
|
||||
external set_64 : Cstruct.buffer -> int -> int64 -> unit = "%caml_bigstring_set64"
|
||||
external swap64 : int64 -> int64 = "%bswap_int64"
|
||||
external unsafe_chr : int -> char = "%identity"
|
||||
|
||||
let set_int8 s off v = Array1.set s off (unsafe_chr v)
|
||||
[@@ocaml.inline]
|
||||
|
||||
let set_int64_le s off v =
|
||||
if Sys.big_endian
|
||||
then set_64 s off (swap64 v)
|
||||
else set_64 s off v
|
||||
[@@ocaml.inline]
|
||||
end
|
||||
|
||||
type id = int
|
||||
|
||||
let last_id = ref 0
|
||||
|
||||
let mint_id () =
|
||||
incr last_id;
|
||||
!last_id
|
||||
|
||||
type hiatus_reason =
|
||||
| Wait_for_work
|
||||
| Suspend
|
||||
| Hibernate
|
||||
|
||||
type event =
|
||||
| Wait
|
||||
| Task
|
||||
| Bind
|
||||
| Try
|
||||
| Choose
|
||||
| Pick
|
||||
| Join
|
||||
| Map
|
||||
| Condition
|
||||
| On_success
|
||||
| On_failure
|
||||
| On_termination
|
||||
| On_any
|
||||
| Ignore_result
|
||||
| Async
|
||||
| Promise
|
||||
| Semaphore
|
||||
| Switch
|
||||
| Stream
|
||||
| Mutex
|
||||
|
||||
type log_buffer = (char, int8_unsigned_elt, c_layout) Array1.t
|
||||
|
||||
let current_thread = ref (-1)
|
||||
|
||||
let int_of_thread_type t =
|
||||
match t with
|
||||
| Wait -> 0
|
||||
| Task -> 1
|
||||
| Bind -> 2
|
||||
| Try -> 3
|
||||
| Choose -> 4
|
||||
| Pick -> 5
|
||||
| Join -> 6
|
||||
| Map -> 7
|
||||
| Condition -> 8
|
||||
| On_success -> 9
|
||||
| On_failure -> 10
|
||||
| On_termination -> 11
|
||||
| On_any -> 12
|
||||
| Ignore_result -> 13
|
||||
| Async -> 14
|
||||
| Promise -> 15
|
||||
| Semaphore -> 16
|
||||
| Switch -> 17
|
||||
| Stream -> 18
|
||||
| Mutex -> 19
|
||||
|
||||
module Packet = struct
|
||||
let magic = 0xc1fc1fc1l
|
||||
let uuid = "\x05\x88\x3b\x8d\x52\x1a\x48\x7b\xb3\x97\x45\x6a\xb1\x50\x68\x0c"
|
||||
|
||||
(*
|
||||
[%%cstruct
|
||||
type packet_header = {
|
||||
(* Stream header, repeated for each packet *)
|
||||
magic: uint32_t;
|
||||
uuid: uint8_t [@len 16];
|
||||
|
||||
(* Packet header *)
|
||||
size: uint32_t;
|
||||
stream_packet_count: uint16_t;
|
||||
content_size_low: uint16_t; (* 2x16 bit to avoid allocating an Int32 *)
|
||||
content_size_high: uint16_t;
|
||||
} [@@little_endian]
|
||||
]
|
||||
*)
|
||||
|
||||
(* Auto-generated code from the above (to avoid a dependency on ppxlib) *)
|
||||
let sizeof_packet_header = 30
|
||||
let set_packet_header_magic v x = Cstruct.LE.set_uint32 v 0 x
|
||||
let set_packet_header_uuid src srcoff dst = Cstruct.blit_from_string src srcoff dst 4 16
|
||||
let set_packet_header_size v x = Cstruct.LE.set_uint32 v 20 x
|
||||
let set_packet_header_stream_packet_count v x = Cstruct.LE.set_uint16 v 24 x
|
||||
let set_packet_header_content_size_low v x = Cstruct.LE.set_uint16 v 26 x
|
||||
let set_packet_header_content_size_high v x = Cstruct.LE.set_uint16 v 28 x
|
||||
(* End auto-generated code *)
|
||||
|
||||
type t = {
|
||||
packet_start : int;
|
||||
header : Cstruct.t;
|
||||
packet_end : int;
|
||||
}
|
||||
|
||||
let first_event packet =
|
||||
packet.packet_start + sizeof_packet_header
|
||||
|
||||
let packet_end packet =
|
||||
packet.packet_end
|
||||
|
||||
let set_content_end packet content_end =
|
||||
let header = packet.header in
|
||||
let bits = (content_end - packet.packet_start) * 8 in
|
||||
set_packet_header_content_size_low header (bits land 0xffff);
|
||||
set_packet_header_content_size_high header (bits lsr 16)
|
||||
|
||||
let clear ~count packet =
|
||||
let bits = sizeof_packet_header * 8 in
|
||||
let header = packet.header in
|
||||
set_packet_header_stream_packet_count header (count land 0xffff);
|
||||
set_packet_header_content_size_low header (bits land 0xffff);
|
||||
set_packet_header_content_size_high header (bits lsr 16)
|
||||
|
||||
let make ~count ~off ~len buffer =
|
||||
let header = Cstruct.of_bigarray ~off ~len:sizeof_packet_header buffer in
|
||||
set_packet_header_magic header magic;
|
||||
set_packet_header_uuid uuid 0 header;
|
||||
set_packet_header_size header (Int32.of_int (len * 8));
|
||||
let packet = {
|
||||
packet_start = off;
|
||||
header;
|
||||
packet_end = off + len;
|
||||
} in
|
||||
clear ~count packet;
|
||||
packet
|
||||
|
||||
end
|
||||
|
||||
module Control = struct
|
||||
(* Following LTT, our trace buffer is divided into a small number of
|
||||
* fixed-sized "packets", each of which contains many events. When there
|
||||
* isn't room in the current packet for the next event, we move to the next
|
||||
* packet. This wastes a few bytes at the end of each packet, but it allows
|
||||
* us to discard whole packets at a time when we need to overwrite something.
|
||||
*)
|
||||
type t = {
|
||||
log : log_buffer;
|
||||
|
||||
timestamper : log_buffer -> int -> unit; (* Write a timestamp at the given offset. *)
|
||||
|
||||
mutable next_event : int; (* Index to write next event (always < packet_end) *)
|
||||
mutable packet_end: int;
|
||||
packets : Packet.t array;
|
||||
mutable active_packet : int;
|
||||
|
||||
(* Each packet is numbered, making it easy to get the order when reading the
|
||||
* ring buffer and allowing for detection of missed packets. *)
|
||||
mutable next_stream_packet_count : int;
|
||||
}
|
||||
|
||||
let event_log = ref None
|
||||
|
||||
let stop log =
|
||||
match !event_log with
|
||||
| Some active when log == active ->
|
||||
event_log := None
|
||||
| _ -> failwith "Log is not currently tracing!"
|
||||
|
||||
let op_creates = 0
|
||||
(* let op_read = 1 *)
|
||||
let op_fulfills = 2
|
||||
let op_fails = 3
|
||||
(* let op_becomes = 4 *)
|
||||
let op_label = 5
|
||||
let op_increase = 6
|
||||
let op_switch = 7
|
||||
(* let op_gc = 8 *)
|
||||
(* let op_old_signal = 9 *)
|
||||
let op_try_read = 10
|
||||
let op_counter_value = 11
|
||||
let op_read_later = 12
|
||||
let op_signal = 13
|
||||
|
||||
let write64 log v i =
|
||||
BS.set_int64_le log i v;
|
||||
i + 8
|
||||
|
||||
let write8 log v i =
|
||||
BS.set_int8 log i v;
|
||||
i + 1
|
||||
|
||||
let write_string log v i =
|
||||
let l = String.length v in
|
||||
for idx = 0 to l - 1 do
|
||||
Array1.set log (i + idx) v.[idx]
|
||||
done;
|
||||
Array1.set log (i + l) '\x00';
|
||||
i + l + 1
|
||||
|
||||
(* The current packet is full. Move to the next one. *)
|
||||
let next_packet log =
|
||||
log.active_packet <- (log.active_packet + 1) mod Array.length log.packets;
|
||||
let packet = log.packets.(log.active_packet) in
|
||||
log.packet_end <- Packet.packet_end packet;
|
||||
log.next_event <- Packet.first_event packet;
|
||||
let count = log.next_stream_packet_count in
|
||||
Packet.clear packet ~count;
|
||||
log.next_stream_packet_count <- count + 1
|
||||
|
||||
let rec add_event log op len =
|
||||
(* Note: be careful about allocation here, as doing GC will add another event... *)
|
||||
let i = log.next_event in
|
||||
let new_i = i + 9 + len in
|
||||
(* >= rather than > is slightly wasteful, but avoids next_event overlapping the next packet *)
|
||||
if new_i >= log.packet_end then (
|
||||
(* Printf.printf "can't write %d at %d\n%!" (9 + len) i; *)
|
||||
let old_packet = log.packets.(log.active_packet) in
|
||||
assert (i > Packet.first_event old_packet);
|
||||
next_packet log;
|
||||
add_event log op len
|
||||
) else (
|
||||
(* Printf.printf "writing at %d\n%!" i; *)
|
||||
log.next_event <- new_i;
|
||||
Packet.set_content_end log.packets.(log.active_packet) new_i;
|
||||
log.timestamper log.log i;
|
||||
i + 8 |> write8 log.log op
|
||||
)
|
||||
|
||||
(* This is faster than [let end_event = ignore]! *)
|
||||
external end_event : int -> unit = "%ignore"
|
||||
(*
|
||||
let end_event i =
|
||||
match !event_log with
|
||||
| None -> assert false
|
||||
| Some log -> assert (i = log.next_event || log.next_event = 0)
|
||||
*)
|
||||
|
||||
let write_tid log tid =
|
||||
write64 log (Int64.of_int tid)
|
||||
|
||||
let note_created log child thread_type =
|
||||
add_event log op_creates 17
|
||||
|> write_tid log.log !current_thread
|
||||
|> write_tid log.log child
|
||||
|> write8 log.log (int_of_thread_type thread_type)
|
||||
|> end_event
|
||||
|
||||
let note_read log ~reader input =
|
||||
add_event log op_read_later 16
|
||||
|> write_tid log.log reader
|
||||
|> write_tid log.log input
|
||||
|> end_event
|
||||
|
||||
let note_try_read log thread input =
|
||||
add_event log op_try_read 16
|
||||
|> write_tid log.log thread
|
||||
|> write_tid log.log input
|
||||
|> end_event
|
||||
|
||||
let note_signal ~src log dst =
|
||||
add_event log op_signal 16
|
||||
|> write_tid log.log dst
|
||||
|> write_tid log.log src
|
||||
|> end_event
|
||||
|
||||
let note_resolved log p ~ex =
|
||||
match ex with
|
||||
| Some ex ->
|
||||
let msg = Printexc.to_string ex in
|
||||
add_event log op_fails (17 + String.length msg)
|
||||
|> write_tid log.log !current_thread
|
||||
|> write_tid log.log p
|
||||
|> write_string log.log msg
|
||||
|> end_event
|
||||
| None ->
|
||||
add_event log op_fulfills 16
|
||||
|> write_tid log.log !current_thread
|
||||
|> write_tid log.log p
|
||||
|> end_event
|
||||
|
||||
(*
|
||||
let note_becomes log input main =
|
||||
if main <> input then (
|
||||
add_event log op_becomes 16
|
||||
|> write64 log.log input
|
||||
|> write64 log.log main
|
||||
|> end_event
|
||||
)
|
||||
*)
|
||||
|
||||
let note_label log thread msg =
|
||||
add_event log op_label (9 + String.length msg)
|
||||
|> write_tid log.log thread
|
||||
|> write_string log.log msg
|
||||
|> end_event
|
||||
|
||||
let note_increase log counter amount =
|
||||
add_event log op_increase (17 + String.length counter)
|
||||
|> write_tid log.log !current_thread
|
||||
|> write64 log.log (Int64.of_int amount)
|
||||
|> write_string log.log counter
|
||||
|> end_event
|
||||
|
||||
let note_counter_value log counter value =
|
||||
add_event log op_counter_value (17 + String.length counter)
|
||||
|> write_tid log.log !current_thread
|
||||
|> write64 log.log (Int64.of_int value)
|
||||
|> write_string log.log counter
|
||||
|> end_event
|
||||
|
||||
let note_switch log new_current =
|
||||
if new_current <> !current_thread then (
|
||||
current_thread := new_current;
|
||||
add_event log op_switch 8
|
||||
|> write_tid log.log new_current
|
||||
|> end_event
|
||||
)
|
||||
|
||||
let note_suspend log () =
|
||||
current_thread := (-1);
|
||||
add_event log op_switch 8
|
||||
|> write_tid log.log (-1)
|
||||
|> end_event
|
||||
|
||||
(*
|
||||
let note_gc duration =
|
||||
match !event_log with
|
||||
| None -> ()
|
||||
| Some log ->
|
||||
add_event log op_gc 8
|
||||
|> write64 log.log (duration *. 1000000000. |> Int64.of_float)
|
||||
|> end_event
|
||||
*)
|
||||
|
||||
let make ~timestamper log =
|
||||
let size = Array1.dim log in
|
||||
let n_packets = 4 in
|
||||
let packet_size = size / n_packets in
|
||||
let packets = Array.init n_packets (fun i ->
|
||||
let off = i * packet_size in
|
||||
let len = if i = n_packets - 1 then size - off else packet_size in
|
||||
Packet.make ~count:i ~off ~len log
|
||||
) in
|
||||
let active_packet = 0 in
|
||||
{
|
||||
log;
|
||||
timestamper;
|
||||
packets;
|
||||
active_packet;
|
||||
packet_end = Packet.packet_end packets.(active_packet);
|
||||
next_event = Packet.first_event packets.(active_packet);
|
||||
next_stream_packet_count = 1;
|
||||
}
|
||||
|
||||
let start (log:t) =
|
||||
event_log := Some log;
|
||||
current_thread := -1
|
||||
end
|
||||
|
||||
let label name =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_label log !current_thread name
|
||||
|
||||
let note_fork () =
|
||||
let child = mint_id () in
|
||||
begin match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_created log child Task
|
||||
end;
|
||||
child
|
||||
|
||||
let note_created ?label id ty =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log ->
|
||||
Control.note_created log id ty;
|
||||
Option.iter (Control.note_label log id) label
|
||||
|
||||
let note_switch new_current =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_switch log new_current
|
||||
|
||||
let note_hiatus _reason =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_suspend log ()
|
||||
|
||||
let note_resume new_current =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_switch log new_current
|
||||
|
||||
let note_try_read input =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_try_read log !current_thread input
|
||||
|
||||
let note_read ?reader input =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log ->
|
||||
let reader =
|
||||
match reader with
|
||||
| None -> !current_thread
|
||||
| Some r -> r
|
||||
in
|
||||
Control.note_read log ~reader input
|
||||
|
||||
let note_resolved id ~ex =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_resolved log id ~ex
|
||||
|
||||
let note_signal ?src dst =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log ->
|
||||
let src =
|
||||
match src with
|
||||
| None -> !current_thread
|
||||
| Some x -> x
|
||||
in
|
||||
Control.note_signal ~src log dst
|
||||
|
||||
let note_increase counter amount =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_increase log counter amount
|
||||
|
||||
let note_counter_value counter value =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_counter_value log counter value
|
||||
|
||||
let should_resolve thread =
|
||||
match !Control.event_log with
|
||||
| None -> ()
|
||||
| Some log -> Control.note_label log thread "__should_resolve" (* Hack! *)
|
@ -1,110 +0,0 @@
|
||||
(** This library is used to write event traces in mirage-profile's CTF format. *)
|
||||
|
||||
type id = private int
|
||||
(** Each thread/fiber/promise is identified by a unique ID. *)
|
||||
|
||||
(** {2 Recording events}
|
||||
Libraries and applications can use these functions to make the traces more useful. *)
|
||||
|
||||
val label : string -> unit
|
||||
(** [label msg] attaches text [msg] to the current thread. *)
|
||||
|
||||
val note_increase : string -> int -> unit
|
||||
(** [note_increase counter delta] records that [counter] increased by [delta].
|
||||
If [delta] is negative, this records a decrease. *)
|
||||
|
||||
val note_counter_value : string -> int -> unit
|
||||
(** [note_counter_value counter value] records that [counter] is now [value]. *)
|
||||
|
||||
val should_resolve : id -> unit
|
||||
(** [should_resolve id] records that [id] is expected to resolve, and should be highlighted if it doesn't. *)
|
||||
|
||||
(** {2 Recording system events}
|
||||
These are normally only called by the scheduler. *)
|
||||
|
||||
type hiatus_reason =
|
||||
| Wait_for_work
|
||||
| Suspend
|
||||
| Hibernate
|
||||
|
||||
type event =
|
||||
| Wait
|
||||
| Task
|
||||
| Bind
|
||||
| Try
|
||||
| Choose
|
||||
| Pick
|
||||
| Join
|
||||
| Map
|
||||
| Condition
|
||||
| On_success
|
||||
| On_failure
|
||||
| On_termination
|
||||
| On_any
|
||||
| Ignore_result
|
||||
| Async
|
||||
| Promise
|
||||
| Semaphore
|
||||
| Switch
|
||||
| Stream
|
||||
| Mutex
|
||||
(** Types of threads or other recorded objects. *)
|
||||
|
||||
val mint_id : unit -> id
|
||||
(** [mint_id ()] is a fresh unique [id]. *)
|
||||
|
||||
val note_created : ?label:string -> id -> event -> unit
|
||||
(** [note_created t id ty] records the creation of [id]. *)
|
||||
|
||||
val note_read : ?reader:id -> id -> unit
|
||||
(** [note_read src] records that promise [src]'s value was read.
|
||||
@param reader The thread doing the read (default is the current thread). *)
|
||||
|
||||
val note_try_read : id -> unit
|
||||
(** [note_try_read src] records that the current thread wants to read from [src] (which is not currently ready). *)
|
||||
|
||||
val note_switch : id -> unit
|
||||
(** [note_switch id] records that [id] is now the current thread. *)
|
||||
|
||||
val note_hiatus : hiatus_reason -> unit
|
||||
(** [note_hiatus r] records that the system will sleep for reason [r]. *)
|
||||
|
||||
val note_resume : id -> unit
|
||||
(** [note_resume id] records that the system has resumed (used after {!note_hiatus}),
|
||||
and is now running [id]. *)
|
||||
|
||||
val note_fork : unit -> id
|
||||
(** [note_fork ()] records that a new thread has been forked and returns a fresh ID for it. *)
|
||||
|
||||
val note_resolved : id -> ex:exn option -> unit
|
||||
(** [note_resolved id ~ex] records that [id] is now resolved.
|
||||
If [ex = None] then [id] was successful, otherwise it failed with exception [ex]. *)
|
||||
|
||||
val note_signal : ?src:id -> id -> unit
|
||||
(** [note_signal ~src dst] records that [dst] was signalled.
|
||||
@param src The thread sending the signal (default is the current thread). *)
|
||||
|
||||
(** {2 Controlling tracing} *)
|
||||
|
||||
type log_buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
|
||||
|
||||
module Control : sig
|
||||
type t
|
||||
|
||||
val make : timestamper:(log_buffer -> int -> unit) -> log_buffer -> t
|
||||
(** [make ~timestamper b] is a trace buffer that record events in [b].
|
||||
In most cases, the {!Ctf_unix} module provides a simpler interface. *)
|
||||
|
||||
val start : t -> unit
|
||||
(** [start t] begins recording events in [t]. *)
|
||||
|
||||
val stop : t -> unit
|
||||
(** [stop t] stops recording to [t] (which must be the current trace buffer). *)
|
||||
end
|
||||
|
||||
(**/**)
|
||||
|
||||
module BS : sig
|
||||
val set_int8 : Cstruct.buffer -> int -> int -> unit
|
||||
val set_int64_le : Cstruct.buffer -> int -> int64 -> unit
|
||||
end
|
@ -8,6 +8,7 @@ let traceln_mutex = Mutex.create ()
|
||||
|
||||
let default_traceln ?__POS__:pos fmt =
|
||||
let k go =
|
||||
Trace.with_span "traceln" @@ fun () ->
|
||||
let b = Buffer.create 512 in
|
||||
let f = Format.formatter_of_buffer b in
|
||||
go f;
|
||||
@ -15,7 +16,7 @@ let default_traceln ?__POS__:pos fmt =
|
||||
Format.pp_close_box f ();
|
||||
Format.pp_print_flush f ();
|
||||
let msg = Buffer.contents b in
|
||||
Ctf.label msg;
|
||||
Trace.log msg;
|
||||
let lines = String.split_on_char '\n' msg in
|
||||
Mutex.lock traceln_mutex;
|
||||
Fun.protect ~finally:(fun () -> Mutex.unlock traceln_mutex) @@ fun () ->
|
||||
@ -24,13 +25,21 @@ let default_traceln ?__POS__:pos fmt =
|
||||
in
|
||||
Format.kdprintf k ("@[" ^^ fmt)
|
||||
|
||||
let traceln ?__POS__ fmt =
|
||||
let traceln =
|
||||
match Fiber.get traceln_key with
|
||||
| Some { traceln } -> traceln
|
||||
| None
|
||||
| exception (Effect.Unhandled _) -> default_traceln
|
||||
let get () =
|
||||
match Fiber.get traceln_key with
|
||||
| Some traceln -> traceln
|
||||
| None
|
||||
| exception (Effect.Unhandled _) -> { traceln = default_traceln }
|
||||
|
||||
let with_trace_prefix prefix fn =
|
||||
let { traceln } = get () in
|
||||
let traceln ?__POS__ fmt =
|
||||
traceln ?__POS__ ("%t" ^^ fmt) prefix
|
||||
in
|
||||
Fiber.with_binding traceln_key { traceln } fn
|
||||
|
||||
let traceln ?__POS__ fmt =
|
||||
let { traceln } = get () in
|
||||
traceln ?__POS__ fmt
|
||||
|
||||
type t = <
|
||||
|
@ -1,4 +1,4 @@
|
||||
(library
|
||||
(name eio__core)
|
||||
(public_name eio.core)
|
||||
(libraries cstruct hmap lwt-dllist fmt optint))
|
||||
(libraries hmap lwt-dllist fmt optint eio.runtime_events))
|
||||
|
@ -7,8 +7,8 @@ module Private = struct
|
||||
module Suspend = Suspend
|
||||
module Cells = Cells
|
||||
module Broadcast = Broadcast
|
||||
module Waiters = Waiters
|
||||
module Ctf = Ctf
|
||||
module Single_waiter = Single_waiter
|
||||
module Trace = Trace
|
||||
module Fiber_context = Cancel.Fiber_context
|
||||
module Debug = Debug
|
||||
|
||||
|
@ -34,16 +34,18 @@ module Switch : sig
|
||||
|
||||
(** {2 Switch creation} *)
|
||||
|
||||
val run : (t -> 'a) -> 'a
|
||||
val run : ?name:string -> (t -> 'a) -> 'a
|
||||
(** [run fn] runs [fn] with a fresh switch (initially on).
|
||||
|
||||
When [fn] finishes, [run] waits for all fibers registered with the switch to finish,
|
||||
and then releases all attached resources.
|
||||
|
||||
If {!fail} is called, [run] will re-raise the exception (after everything is cleaned up).
|
||||
If [fn] raises an exception, it is passed to {!fail}. *)
|
||||
If [fn] raises an exception, it is passed to {!fail}.
|
||||
|
||||
val run_protected : (t -> 'a) -> 'a
|
||||
@param name Used to name the switch when tracing. *)
|
||||
|
||||
val run_protected : ?name:string -> (t -> 'a) -> 'a
|
||||
(** [run_protected fn] is like [run] but ignores cancellation requests from the parent context. *)
|
||||
|
||||
(** {2 Cancellation and failure} *)
|
||||
@ -85,24 +87,41 @@ module Switch : sig
|
||||
Release handlers are run in LIFO order, in series.
|
||||
|
||||
Note that [fn] is called within a {!Cancel.protect}, since aborting clean-up actions is usually a bad idea
|
||||
and the switch may have been cancelled by the time it runs. *)
|
||||
and the switch may have been cancelled by the time it runs.
|
||||
You cannot attach new resources to a switch once the cancel hooks start to run.
|
||||
|
||||
This function is thread-safe (but not signal-safe).
|
||||
If the switch finishes before [fn] can be registered,
|
||||
it raises [Invalid_argument] and runs [fn] immediately instead. *)
|
||||
|
||||
type hook
|
||||
(** A handle for removing a clean-up callback. *)
|
||||
|
||||
val null_hook : hook
|
||||
(** A dummy hook. Removing it does nothing. *)
|
||||
(** A dummy hook. [try_remove_hook null_hook = false]. *)
|
||||
|
||||
val on_release_cancellable : t -> (unit -> unit) -> hook
|
||||
(** Like [on_release], but the handler can be removed later.
|
||||
|
||||
For example, opening a file will call [on_release_cancellable] to ensure the file is closed later.
|
||||
However, if the file is manually closed before that, it will use {!remove_hook} to remove the hook,
|
||||
which is no longer needed. *)
|
||||
which is no longer needed.
|
||||
|
||||
This function is thread-safe (but not signal-safe). *)
|
||||
|
||||
val try_remove_hook : hook -> bool
|
||||
(** [try_remove_hook h] removes a previously-added hook.
|
||||
Returns [true] if the hook was successfully removed, or [false] if another
|
||||
domain ran it or removed it first.
|
||||
|
||||
This function is thread-safe (but not signal-safe). *)
|
||||
|
||||
val remove_hook : hook -> unit
|
||||
(** [remove_hook h] removes a previously-added hook.
|
||||
If the hook has already been removed, this does nothing. *)
|
||||
(** [remove_hook h] is [ignore (try_remove_hook h)].
|
||||
|
||||
For multi-domain code, consider using {!try_remove_hook} instead
|
||||
so that you can handle the case of trying to close a resource
|
||||
just as another domain is closing it or finishing the switch. *)
|
||||
|
||||
(** {2 Debugging} *)
|
||||
|
||||
@ -148,6 +167,11 @@ module Promise : sig
|
||||
Any threads waiting for the result will be added to the run queue.
|
||||
@raise Invalid_argument if [u] is already resolved. *)
|
||||
|
||||
val try_resolve : 'a u -> 'a -> bool
|
||||
(** [try_resolve] is like {!resolve} but returns [false] instead of raising [Invalid_argument].
|
||||
|
||||
Returns [true] on success. *)
|
||||
|
||||
val peek : 'a t -> 'a option
|
||||
(** [peek t] is [Some v] if the promise has been resolved to [v], or [None] otherwise.
|
||||
If the result is [None] then it may change in future, otherwise it won't.
|
||||
@ -199,7 +223,7 @@ module Fiber : sig
|
||||
(** [all fs] is like [both], but for any number of fibers.
|
||||
[all []] returns immediately. *)
|
||||
|
||||
val first : (unit -> 'a) -> (unit -> 'a) -> 'a
|
||||
val first : ?combine:('a -> 'a -> 'a) -> (unit -> 'a) -> (unit -> 'a) -> 'a
|
||||
(** [first f g] runs [f ()] and [g ()] concurrently.
|
||||
|
||||
They run in a new cancellation sub-context, and when one finishes the other is cancelled.
|
||||
@ -209,15 +233,24 @@ module Fiber : sig
|
||||
|
||||
If both fibers fail, {!Exn.combine} is used to combine the exceptions.
|
||||
|
||||
Warning: it is always possible that {i both} operations will succeed (and one result will be thrown away).
|
||||
This is because there is a period of time after the first operation succeeds,
|
||||
but before its fiber finishes, during which the other operation may also succeed. *)
|
||||
Warning: it is always possible that {i both} operations will succeed.
|
||||
This is because there is a period of time after the first operation succeeds
|
||||
when it is waiting in the run-queue to resume
|
||||
during which the other operation may also succeed.
|
||||
|
||||
val any : (unit -> 'a) list -> 'a
|
||||
If both fibers succeed, [combine a b] is used to combine the results
|
||||
(where [a] is the result of the first fiber to return and [b] is the second result).
|
||||
The default is [fun a _ -> a], which discards the later result. *)
|
||||
|
||||
val any : ?combine:('a -> 'a -> 'a) -> (unit -> 'a) list -> 'a
|
||||
(** [any fs] is like [first], but for any number of fibers.
|
||||
|
||||
[any []] just waits forever (or until cancelled). *)
|
||||
|
||||
val n_any : (unit -> 'a) list -> 'a list
|
||||
(** [n_any fs] is like [any], expect that if multiple fibers return values
|
||||
then they are all returned, in the order in which the fibers finished. *)
|
||||
|
||||
val await_cancel : unit -> 'a
|
||||
(** [await_cancel ()] waits until cancelled.
|
||||
@raise Cancel.Cancelled *)
|
||||
@ -234,22 +267,42 @@ module Fiber : sig
|
||||
[fn] runs immediately, without switching to any other fiber first.
|
||||
The calling fiber is placed at the head of the run queue, ahead of any previous items. *)
|
||||
|
||||
val fork_sub : sw:Switch.t -> on_error:(exn -> unit) -> (Switch.t -> unit) -> unit
|
||||
(** [fork_sub ~sw ~on_error fn] is like [fork], but it creates a new sub-switch for the fiber.
|
||||
|
||||
This means that you can cancel the child switch without cancelling the parent.
|
||||
This is a convenience function for running {!Switch.run} inside a {!fork}.
|
||||
|
||||
@param on_error This is called if the fiber raises an exception.
|
||||
If it raises in turn, the parent switch is failed.
|
||||
It is not called if the parent [sw] itself is cancelled. *)
|
||||
|
||||
val fork_promise : sw:Switch.t -> (unit -> 'a) -> 'a Promise.or_exn
|
||||
(** [fork_promise ~sw fn] schedules [fn ()] to run in a new fiber and returns a promise for its result.
|
||||
|
||||
This is just a convenience wrapper around {!fork}.
|
||||
If [fn] raises an exception then the promise is resolved to the error, but [sw] is not failed. *)
|
||||
|
||||
val fork_seq : sw:Switch.t -> (('a -> unit) -> unit) -> 'a Seq.t
|
||||
(** [fork_seq ~sw fn] creates (but does not start) a new fiber to run [fn yield].
|
||||
|
||||
Requesting the next item from the returned sequence resumes the fiber until it
|
||||
calls [yield x], using [x] value as the next item in the sequence. If [fn]
|
||||
returns without producing a value then the result is {!Seq.Nil} (end-of-sequence).
|
||||
|
||||
The returned sequence can be consumed safely from another domain.
|
||||
[fn] itself always runs in the domain that called [fork_seq].
|
||||
|
||||
Example:
|
||||
{[
|
||||
Switch.run @@ fun sw ->
|
||||
let seq = Fiber.fork_seq ~sw (fun yield ->
|
||||
for i = 1 to 3 do
|
||||
traceln "Yielding %d" i;
|
||||
yield i
|
||||
done
|
||||
) in
|
||||
Seq.iter (traceln "Got: %d") seq
|
||||
]}
|
||||
|
||||
If [fn] raises an exception then the consumer receives it.
|
||||
If the consumer cancels while awaiting a value, the producer is cancelled when
|
||||
it next calls [yield].
|
||||
It is an error to request two items at once, or to request items out of sequence.
|
||||
|
||||
@param sw When the switch finishes, the fiber is cancelled (if still running).
|
||||
Attempting to read from the sequence after this raises an exception. *)
|
||||
|
||||
val fork_daemon : sw:Switch.t -> (unit -> [`Stop_daemon]) -> unit
|
||||
(** [fork_daemon] is like {!fork} except that instead of waiting for the fiber to finish,
|
||||
the switch will cancel it once all non-daemon fibers are done.
|
||||
@ -264,6 +317,9 @@ module Fiber : sig
|
||||
Many operations automatically check this before starting.
|
||||
@raise Cancel.Cancelled if the fiber's context has been cancelled. *)
|
||||
|
||||
val is_cancelled : unit -> bool
|
||||
(** [is_cancelled ()] is [true] iff {!check} would raise an exception. *)
|
||||
|
||||
val yield : unit -> unit
|
||||
(** [yield ()] asks the scheduler to switch to the next runnable task.
|
||||
The current task remains runnable, but goes to the back of the queue.
|
||||
@ -300,18 +356,6 @@ module Fiber : sig
|
||||
@param max_fibers Maximum number of fibers to run concurrently *)
|
||||
end
|
||||
|
||||
val filter : ?max_fibers:int -> ('a -> bool) -> 'a list -> 'a list
|
||||
[@@ocaml.deprecated "Use `Eio.Fiber.List.filter` instead."]
|
||||
|
||||
val map : ?max_fibers:int -> ('a -> 'b) -> 'a list -> 'b list
|
||||
[@@ocaml.deprecated "Use `Eio.Fiber.List.map instead."]
|
||||
|
||||
val filter_map : ?max_fibers:int -> ('a -> 'b option) -> 'a list -> 'b list
|
||||
[@@ocaml.deprecated "Use `Eio.Fiber.List.filter_map instead."]
|
||||
|
||||
val iter : ?max_fibers:int -> ('a -> unit) -> 'a list -> unit
|
||||
[@@ocaml.deprecated "Use `Eio.Fiber.List.iter instead."]
|
||||
|
||||
(** {2 Fiber-local variables}
|
||||
|
||||
Each fiber maintains a map of additional variables associated with it,
|
||||
@ -422,6 +466,12 @@ module Exn : sig
|
||||
This is similar to {!Fmt.exn}, but can do a better job on {!Io} exceptions
|
||||
because it can format them directly without having to convert to a string first. *)
|
||||
|
||||
val pp_err : err Fmt.t
|
||||
(** [pp_err] formats an error code. *)
|
||||
|
||||
val empty_backtrace : Printexc.raw_backtrace
|
||||
(** A backtrace with no frames. *)
|
||||
|
||||
(** Extensible backend-specific exceptions. *)
|
||||
module Backend : sig
|
||||
type t = ..
|
||||
@ -512,9 +562,6 @@ module Cancel : sig
|
||||
|
||||
The nested exception is only intended for debug-level logging and should generally be ignored. *)
|
||||
|
||||
exception Cancel_hook_failed of exn list
|
||||
(** Raised by {!cancel} if any of the cancellation hooks themselves fail. *)
|
||||
|
||||
val sub : (t -> 'a) -> 'a
|
||||
(** [sub fn] installs a new cancellation context [t], runs [fn t] inside it, and then restores the old context.
|
||||
|
||||
@ -547,9 +594,7 @@ module Cancel : sig
|
||||
If [t] is already cancelled then this does nothing.
|
||||
|
||||
Note that the caller of this function is still responsible for handling the error somehow
|
||||
(e.g. reporting it to the user); it does not become the responsibility of the cancelled thread(s).
|
||||
|
||||
@raise Cancel_hook_failed if one or more hooks fail. *)
|
||||
(e.g. reporting it to the user); it does not become the responsibility of the cancelled thread(s). *)
|
||||
|
||||
val dump : t Fmt.t
|
||||
(** Show the cancellation sub-tree rooted at [t], for debugging. *)
|
||||
@ -557,10 +602,11 @@ end
|
||||
|
||||
(** @canonical Eio.Private *)
|
||||
module Private : sig
|
||||
module Ctf = Ctf
|
||||
module Trace = Trace
|
||||
|
||||
module Cells = Cells
|
||||
module Broadcast = Broadcast
|
||||
module Single_waiter = Single_waiter
|
||||
|
||||
(** Every fiber has an associated context. *)
|
||||
module Fiber_context : sig
|
||||
@ -572,7 +618,7 @@ module Private : sig
|
||||
val destroy : t -> unit
|
||||
(** [destroy t] removes [t] from its cancellation context. *)
|
||||
|
||||
val tid : t -> Ctf.id
|
||||
val tid : t -> Trace.id
|
||||
|
||||
(** {2 Cancellation}
|
||||
|
||||
@ -684,71 +730,32 @@ module Private : sig
|
||||
|
||||
(** Suspend a fiber and enter the scheduler. *)
|
||||
module Suspend : sig
|
||||
val enter : (Fiber_context.t -> 'a Effects.enqueue -> unit) -> 'a
|
||||
(** [enter fn] suspends the calling fiber and calls [fn ctx enqueue] in the scheduler's context.
|
||||
val enter : string -> (Fiber_context.t -> 'a Effects.enqueue -> unit) -> 'a
|
||||
(** [enter op fn] suspends the calling fiber and calls [fn ctx enqueue] in the scheduler's context.
|
||||
|
||||
This should arrange for [enqueue] to be called when the fiber should be resumed.
|
||||
[enqueue] is thread-safe and so can be called from another domain or systhread.
|
||||
|
||||
[ctx] should be used to set a cancellation function. Otherwise, the operation is non-interruptable.
|
||||
If the caller's cancellation context is already cancelled, [enter] immediately aborts. *)
|
||||
If the caller's cancellation context is already cancelled, [enter] immediately aborts.
|
||||
|
||||
val enter_unchecked : (Fiber_context.t -> 'a Effects.enqueue -> unit) -> 'a
|
||||
[op] is used when tracing to label the operation. *)
|
||||
|
||||
val enter_unchecked : string -> (Fiber_context.t -> 'a Effects.enqueue -> unit) -> 'a
|
||||
(** [enter_unchecked] is like [enter] except that it does not perform the initial check
|
||||
that the fiber isn't cancelled (this is useful if you want to do the check yourself, e.g.
|
||||
because you need to unlock a mutex if cancelled). *)
|
||||
end
|
||||
|
||||
(** A queue of fibers waiting for an event. *)
|
||||
module Waiters : sig
|
||||
type 'a t
|
||||
(* A queue of fibers waiting for something.
|
||||
Note: an [_ t] is not thread-safe itself.
|
||||
To use share it between domains, the user is responsible for wrapping it in a mutex. *)
|
||||
|
||||
val create : unit -> 'a t
|
||||
|
||||
val wake_all : 'a t -> 'a -> unit
|
||||
(** [wake_all t] calls (and removes) all the functions waiting on [t].
|
||||
If [t] is shared between domains, the caller must hold the mutex while calling this. *)
|
||||
|
||||
val wake_one : 'a t -> 'a -> [`Ok | `Queue_empty]
|
||||
(** [wake_one t] is like {!wake_all}, but only calls (and removes) the first waiter in the queue.
|
||||
If [t] is shared between domains, the caller must hold the mutex while calling this. *)
|
||||
|
||||
val is_empty : 'a t -> bool
|
||||
(** [is_empty t] checks whether there are any functions waiting on [t].
|
||||
If [t] is shared between domains, the caller must hold the mutex while calling this,
|
||||
and the result is valid until the mutex is released. *)
|
||||
|
||||
val await :
|
||||
mutex:Mutex.t option ->
|
||||
'a t -> Ctf.id -> 'a
|
||||
(** [await ~mutex t id] suspends the current fiber and adds its continuation to [t].
|
||||
When the waiter is woken, the fiber is resumed and returns the result.
|
||||
If [t] can be used from multiple domains:
|
||||
- [mutex] must be set to the mutex to use to unlock it.
|
||||
- [mutex] must be already held when calling this function, which will unlock it before blocking.
|
||||
When [await] returns, [mutex] will have been unlocked.
|
||||
@raise Cancel.Cancelled if the fiber's context is cancelled *)
|
||||
|
||||
val await_internal :
|
||||
mutex:Mutex.t option ->
|
||||
'a t -> Ctf.id -> Fiber_context.t ->
|
||||
(('a, exn) result -> unit) -> unit
|
||||
(** [await_internal ~mutex t id ctx enqueue] is like [await], but the caller has to suspend the fiber.
|
||||
This also allows wrapping the [enqueue] function.
|
||||
Calls [enqueue (Error (Cancelled _))] if cancelled.
|
||||
Note: [enqueue] is called from the triggering domain,
|
||||
which is currently calling {!wake_one} or {!wake_all}
|
||||
and must therefore be holding [mutex]. *)
|
||||
end
|
||||
|
||||
module Debug : sig
|
||||
val traceln :
|
||||
?__POS__:string * int * int * int ->
|
||||
('a, Format.formatter, unit, unit) format4 -> 'a
|
||||
(** Writes trace logging using the current fiber's configured traceln function. *)
|
||||
|
||||
val with_trace_prefix : (Format.formatter -> unit) -> (unit -> 'a) -> 'a
|
||||
(** [with_trace_prefix fmt fn] runs [fn ()] with a traceln that outputs [fmt] before each message. *)
|
||||
|
||||
val traceln_mutex : Stdlib.Mutex.t
|
||||
(** The mutex used to prevent two domains writing to stderr at once.
|
||||
|
||||
@ -775,5 +782,4 @@ module Private : sig
|
||||
val v : t
|
||||
(** Backends should use this for {!Eio.Stdenv.debug}. *)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -16,10 +16,10 @@ type err += Multiple_io of (err * context * Printexc.raw_backtrace) list
|
||||
|
||||
exception Cancelled of exn
|
||||
|
||||
exception Cancel_hook_failed of exn list
|
||||
|
||||
let create err = Io (err, { steps = [] })
|
||||
|
||||
let empty_backtrace = Printexc.get_callstack 0
|
||||
|
||||
let add_context ex fmt =
|
||||
fmt |> Fmt.kstr @@ fun msg ->
|
||||
match ex with
|
||||
@ -90,7 +90,6 @@ let () =
|
||||
Printexc.register_printer @@ function
|
||||
| Io _ as ex -> Some (Fmt.str "@[<v>%a@]" pp ex)
|
||||
| Multiple exns -> Some (Fmt.str "%a" pp_multiple exns)
|
||||
| Cancel_hook_failed exns -> Some ("During cancellation:\n" ^ String.concat "\nand\n" (List.map Printexc.to_string exns))
|
||||
| Cancelled ex -> Some ("Cancelled: " ^ Printexc.to_string ex)
|
||||
| _ -> None
|
||||
|
||||
@ -99,9 +98,9 @@ let combine e1 e2 =
|
||||
else match e1, e2 with
|
||||
| (Cancelled _, _), e
|
||||
| e, (Cancelled _, _) -> e (* Don't need to report a cancelled exception if we have something better *)
|
||||
| (Io (c1, t1), bt1), (Io (c2, t2), bt2) -> create (Multiple_io [(c1, t1, bt1); (c2, t2, bt2)]), Printexc.get_callstack 0
|
||||
| (Io (c1, t1), bt1), (Io (c2, t2), bt2) -> create (Multiple_io [(c1, t1, bt1); (c2, t2, bt2)]), empty_backtrace
|
||||
| (Multiple exs, bt1), e2 -> Multiple (e2 :: exs), bt1
|
||||
| e1, e2 -> Multiple [e2; e1], Printexc.get_callstack 0
|
||||
| e1, e2 -> Multiple [e2; e1], empty_backtrace
|
||||
|
||||
module Backend = struct
|
||||
type t = ..
|
||||
|
@ -1,7 +1,9 @@
|
||||
[@@@alert "-unstable"]
|
||||
|
||||
type _ Effect.t += Fork : Cancel.fiber_context * (unit -> unit) -> unit Effect.t
|
||||
|
||||
let yield () =
|
||||
let fiber = Suspend.enter (fun fiber enqueue -> enqueue (Ok fiber)) in
|
||||
let fiber = Suspend.enter "" (fun fiber enqueue -> enqueue (Ok fiber)) in
|
||||
Cancel.check fiber.cancel_context
|
||||
|
||||
(* Note: [f] must not raise an exception, as that would terminate the whole scheduler. *)
|
||||
@ -15,12 +17,11 @@ let fork ~sw f =
|
||||
let new_fiber = Cancel.Fiber_context.make ~cc:sw.cancel ~vars in
|
||||
fork_raw new_fiber @@ fun () ->
|
||||
Switch.with_op sw @@ fun () ->
|
||||
match f () with
|
||||
| () ->
|
||||
Ctf.note_resolved (Cancel.Fiber_context.tid new_fiber) ~ex:None
|
||||
| exception ex ->
|
||||
Switch.fail sw ex; (* The [with_op] ensures this will succeed *)
|
||||
Ctf.note_resolved (Cancel.Fiber_context.tid new_fiber) ~ex:(Some ex)
|
||||
try
|
||||
f ()
|
||||
with ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
Switch.fail ~bt sw ex; (* The [with_op] ensures this will succeed *)
|
||||
) (* else the fiber should report the error to [sw], but [sw] is failed anyway *)
|
||||
|
||||
let fork_daemon ~sw f =
|
||||
@ -33,13 +34,13 @@ let fork_daemon ~sw f =
|
||||
match f () with
|
||||
| `Stop_daemon ->
|
||||
(* The daemon asked to stop. *)
|
||||
Ctf.note_resolved (Cancel.Fiber_context.tid new_fiber) ~ex:None
|
||||
()
|
||||
| exception Cancel.Cancelled Exit when not (Cancel.is_on sw.cancel) ->
|
||||
(* The daemon was cancelled because all non-daemon fibers are finished. *)
|
||||
Ctf.note_resolved (Cancel.Fiber_context.tid new_fiber) ~ex:None
|
||||
()
|
||||
| exception ex ->
|
||||
Switch.fail sw ex; (* The [with_daemon] ensures this will succeed *)
|
||||
Ctf.note_resolved (Cancel.Fiber_context.tid new_fiber) ~ex:(Some ex)
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
Switch.fail ~bt sw ex; (* The [with_daemon] ensures this will succeed *)
|
||||
) (* else the fiber should report the error to [sw], but [sw] is failed anyway *)
|
||||
|
||||
let fork_promise ~sw f =
|
||||
@ -65,54 +66,56 @@ let fork_promise_exn ~sw f =
|
||||
match Switch.with_op sw f with
|
||||
| x -> Promise.resolve r x
|
||||
| exception ex ->
|
||||
Switch.fail sw ex (* The [with_op] ensures this will succeed *)
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
Switch.fail ~bt sw ex (* The [with_op] ensures this will succeed *)
|
||||
);
|
||||
p
|
||||
|
||||
let all xs =
|
||||
Switch.run @@ fun sw ->
|
||||
List.iter (fork ~sw) xs
|
||||
(* Like [List.iter (fork ~sw)], but runs the last one in the current fiber
|
||||
for efficiency and less cluttered traces. *)
|
||||
let rec forks ~sw = function
|
||||
| [] -> ()
|
||||
| [x] -> Switch.check sw; x ()
|
||||
| x :: xs ->
|
||||
fork ~sw x;
|
||||
forks ~sw xs
|
||||
|
||||
let both f g = all [f; g]
|
||||
let all xs =
|
||||
Switch.run ~name:"all" @@ fun sw ->
|
||||
forks ~sw xs
|
||||
|
||||
let both f g =
|
||||
Switch.run ~name:"both" @@ fun sw ->
|
||||
forks ~sw [f; g]
|
||||
|
||||
let pair f g =
|
||||
Switch.run @@ fun sw ->
|
||||
Switch.run ~name:"pair" @@ fun sw ->
|
||||
let x = fork_promise ~sw f in
|
||||
let y = g () in
|
||||
(Promise.await_exn x, y)
|
||||
|
||||
let fork_sub ~sw ~on_error f =
|
||||
fork ~sw (fun () ->
|
||||
try Switch.run f
|
||||
with
|
||||
| ex when Cancel.is_on sw.cancel ->
|
||||
(* Typically the caller's context is within [sw], but it doesn't have to be.
|
||||
It's possible that the original context has finished by now,
|
||||
but [fork] is keeping [sw] alive so we can use that report the error. *)
|
||||
Switch.run_in sw @@ fun () ->
|
||||
try on_error ex
|
||||
with ex2 ->
|
||||
(* The [run_in] ensures [adopting_sw] isn't finished here *)
|
||||
Switch.fail sw ex;
|
||||
Switch.fail sw ex2
|
||||
)
|
||||
|
||||
exception Not_first
|
||||
|
||||
let await_cancel () =
|
||||
Suspend.enter @@ fun fiber enqueue ->
|
||||
Suspend.enter "await_cancel" @@ fun fiber enqueue ->
|
||||
Cancel.Fiber_context.set_cancel_fn fiber (fun ex -> enqueue (Error ex))
|
||||
|
||||
let any fs =
|
||||
let r = ref `None in
|
||||
type 'a any_status =
|
||||
| New
|
||||
| Ex of (exn * Printexc.raw_backtrace)
|
||||
| OK of 'a
|
||||
|
||||
let any_gen ~return ~combine fs =
|
||||
let r = ref New in
|
||||
let parent_c =
|
||||
Cancel.sub_unchecked (fun cc ->
|
||||
Cancel.sub_unchecked Any (fun cc ->
|
||||
let wrap h =
|
||||
match h () with
|
||||
| x ->
|
||||
begin match !r with
|
||||
| `None -> r := `Ok x; Cancel.cancel cc Not_first
|
||||
| `Ex _ | `Ok _ -> ()
|
||||
| New -> r := OK (return x); Cancel.cancel cc Not_first
|
||||
| OK prev -> r := OK (combine prev x)
|
||||
| Ex _ -> ()
|
||||
end
|
||||
| exception Cancel.Cancelled _ when not (Cancel.is_on cc) ->
|
||||
(* If this is in response to us asking the fiber to cancel then we can just ignore it.
|
||||
@ -121,11 +124,11 @@ let any fs =
|
||||
()
|
||||
| exception ex ->
|
||||
begin match !r with
|
||||
| `None -> r := `Ex (ex, Printexc.get_raw_backtrace ()); Cancel.cancel cc ex
|
||||
| `Ok _ -> r := `Ex (ex, Printexc.get_raw_backtrace ())
|
||||
| `Ex prev ->
|
||||
| New -> r := Ex (ex, Printexc.get_raw_backtrace ()); Cancel.cancel cc ex
|
||||
| OK _ -> r := Ex (ex, Printexc.get_raw_backtrace ())
|
||||
| Ex prev ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
r := `Ex (Exn.combine prev (ex, bt))
|
||||
r := Ex (Exn.combine prev (ex, bt))
|
||||
end
|
||||
in
|
||||
let vars = Cancel.Fiber_context.get_vars () in
|
||||
@ -137,7 +140,7 @@ let any fs =
|
||||
let p, r = Promise.create_with_id (Cancel.Fiber_context.tid new_fiber) in
|
||||
fork_raw new_fiber (fun () ->
|
||||
match wrap f with
|
||||
| x -> Promise.resolve_ok r x
|
||||
| () -> Promise.resolve_ok r ()
|
||||
| exception ex -> Promise.resolve_error r ex
|
||||
);
|
||||
p :: aux fs
|
||||
@ -147,16 +150,25 @@ let any fs =
|
||||
)
|
||||
in
|
||||
match !r, Cancel.get_error parent_c with
|
||||
| `Ok r, None -> r
|
||||
| (`Ok _ | `None), Some ex -> raise ex
|
||||
| `Ex (ex, bt), None -> Printexc.raise_with_backtrace ex bt
|
||||
| `Ex ex1, Some ex2 ->
|
||||
| OK r, None -> r
|
||||
| (OK _ | New), Some ex -> raise ex
|
||||
| Ex (ex, bt), None -> Printexc.raise_with_backtrace ex bt
|
||||
| Ex ex1, Some ex2 ->
|
||||
let bt2 = Printexc.get_raw_backtrace () in
|
||||
let ex, bt = Exn.combine ex1 (ex2, bt2) in
|
||||
Printexc.raise_with_backtrace ex bt
|
||||
| `None, None -> assert false
|
||||
| New, None -> assert false
|
||||
|
||||
let first f g = any [f; g]
|
||||
let n_any fs =
|
||||
List.rev (any_gen fs ~return:(fun x -> [x]) ~combine:(fun xs x -> x :: xs))
|
||||
|
||||
let any ?(combine=(fun x _ -> x)) fs = any_gen fs ~return:Fun.id ~combine
|
||||
|
||||
let first ?combine f g = any ?combine [f; g]
|
||||
|
||||
let is_cancelled () =
|
||||
let ctx = Effect.perform Cancel.Get_context in
|
||||
not (Cancel.is_on ctx.cancel_context)
|
||||
|
||||
let check () =
|
||||
let ctx = Effect.perform Cancel.Get_context in
|
||||
@ -208,7 +220,7 @@ module List = struct
|
||||
}
|
||||
|
||||
let await_free t =
|
||||
if t.free_fibers = 0 then Single_waiter.await t.cond t.sw.id;
|
||||
if t.free_fibers = 0 then Single_waiter.await t.cond "Limiter.await_free" t.sw.cancel.id;
|
||||
(* If we got woken up then there was a free fiber then. And since we're the
|
||||
only fiber that uses [t], and we were sleeping, it must still be free. *)
|
||||
assert (t.free_fibers > 0);
|
||||
@ -216,7 +228,7 @@ module List = struct
|
||||
|
||||
let release t =
|
||||
t.free_fibers <- t.free_fibers + 1;
|
||||
if t.free_fibers = 1 then Single_waiter.wake t.cond (Ok ())
|
||||
if t.free_fibers = 1 then Single_waiter.wake_if_sleeping t.cond
|
||||
|
||||
let use t fn x =
|
||||
await_free t;
|
||||
@ -237,7 +249,7 @@ module List = struct
|
||||
match items with
|
||||
| [] -> [] (* Avoid creating a switch in the simple case *)
|
||||
| items ->
|
||||
Switch.run @@ fun sw ->
|
||||
Switch.run ~name:"filter_map" @@ fun sw ->
|
||||
let limiter = Limiter.create ~sw max_fibers in
|
||||
let rec aux = function
|
||||
| [] -> []
|
||||
@ -256,7 +268,7 @@ module List = struct
|
||||
match items with
|
||||
| [] -> () (* Avoid creating a switch in the simple case *)
|
||||
| items ->
|
||||
Switch.run @@ fun sw ->
|
||||
Switch.run ~name:"iter" @@ fun sw ->
|
||||
let limiter = Limiter.create ~sw max_fibers in
|
||||
let rec aux = function
|
||||
| [] -> ()
|
||||
@ -269,8 +281,6 @@ module List = struct
|
||||
|
||||
end
|
||||
|
||||
include List
|
||||
|
||||
type 'a key = 'a Hmap.key
|
||||
|
||||
let create_key () = Hmap.Key.create ()
|
||||
@ -284,3 +294,108 @@ let with_binding var value fn =
|
||||
let without_binding var fn =
|
||||
let ctx = Effect.perform Cancel.Get_context in
|
||||
Cancel.Fiber_context.with_vars ctx (Hmap.rem var ctx.vars) fn
|
||||
|
||||
(* Coroutines.
|
||||
|
||||
[fork_coroutine ~sw fn] creates a new fiber for [fn]. [fn] immediately suspends, setting its state to
|
||||
[Ready enqueue]. A consumer can resume it by setting the state to [Running] and calling [enqueue],
|
||||
while suspending itself. The consumer passes in its own [enqueue] function. They run alternatively
|
||||
like this, switching between the [Ready] and [Running] states.
|
||||
|
||||
To finish, the coroutine fiber can set the state to [Finished] or [Failed],
|
||||
or the client can set the state to [Client_cancelled].
|
||||
*)
|
||||
|
||||
(* Note: we could easily generalise this to [('in, 'out) coroutine] if that was useful. *)
|
||||
type 'out coroutine =
|
||||
[ `Init
|
||||
| `Ready of [`Running of 'out Suspend.enqueue] Suspend.enqueue
|
||||
| `Running of 'out Suspend.enqueue
|
||||
| `Finished
|
||||
| `Client_cancelled of exn
|
||||
| `Failed of exn ]
|
||||
|
||||
(* The only good reason for the state to change while the coroutine is running is if the client
|
||||
cancels. Return the exception in that case. If the coroutine is buggy it might e.g. fork two
|
||||
fibers and yield twice for a single request - return Invalid_argument in that case. *)
|
||||
let unwrap_cancelled state =
|
||||
match Atomic.get state with
|
||||
| `Client_cancelled ex -> ex
|
||||
| `Finished | `Failed _ -> Invalid_argument "Coroutine has already stopped!"
|
||||
| `Ready _ -> Invalid_argument "Coroutine has already yielded!"
|
||||
| `Init | `Running _ -> Invalid_argument "Coroutine in unexpected state!"
|
||||
|
||||
let run_coroutine ~state fn =
|
||||
let await_request ~prev ~on_suspend =
|
||||
(* Suspend and wait for the consumer to resume us: *)
|
||||
Suspend.enter "await-consumer" (fun ctx enqueue ->
|
||||
let ready = `Ready enqueue in
|
||||
if Atomic.compare_and_set state prev ready then (
|
||||
Cancel.Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
if Atomic.compare_and_set state ready (`Failed ex) then
|
||||
enqueue (Error ex);
|
||||
(* else the client enqueued a resume for us; handle that instead *)
|
||||
);
|
||||
on_suspend ()
|
||||
) else (
|
||||
enqueue (Error (unwrap_cancelled state))
|
||||
)
|
||||
)
|
||||
in
|
||||
let current_state = ref (await_request ~prev:`Init ~on_suspend:ignore) in
|
||||
fn (fun v ->
|
||||
(* The coroutine wants to yield the value [v] and suspend. *)
|
||||
let `Running enqueue as prev = !current_state in
|
||||
current_state := await_request ~prev ~on_suspend:(fun () -> enqueue (Ok (Some v)))
|
||||
);
|
||||
(* [fn] has finished. End the stream. *)
|
||||
if Atomic.compare_and_set state (!current_state :> _ coroutine) `Finished then (
|
||||
let `Running enqueue = !current_state in
|
||||
enqueue (Ok None)
|
||||
) else (
|
||||
raise (unwrap_cancelled state)
|
||||
)
|
||||
|
||||
let fork_coroutine ~sw fn =
|
||||
let state = Atomic.make `Init in
|
||||
fork_daemon ~sw (fun () ->
|
||||
try
|
||||
run_coroutine ~state fn;
|
||||
`Stop_daemon
|
||||
with ex ->
|
||||
match ex, Atomic.exchange state (`Failed ex) with
|
||||
| _, `Running enqueue ->
|
||||
(* A client is waiting for us. Send the error there. Also do this if we were cancelled. *)
|
||||
enqueue (Error ex);
|
||||
`Stop_daemon
|
||||
| Cancel.Cancelled _, _ ->
|
||||
(* The client isn't waiting (probably it got cancelled, then we tried to yield to it and got cancelled too).
|
||||
If it tries to resume us later it will see the error. *)
|
||||
`Stop_daemon
|
||||
| _ ->
|
||||
(* Something unexpected happened. Re-raise. *)
|
||||
raise ex
|
||||
);
|
||||
fun () ->
|
||||
Suspend.enter "await-producer" (fun ctx enqueue ->
|
||||
let rec aux () =
|
||||
match Atomic.get state with
|
||||
| `Ready resume as prev ->
|
||||
let running = `Running enqueue in
|
||||
if Atomic.compare_and_set state prev running then (
|
||||
resume (Ok running);
|
||||
Cancel.Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
if Atomic.compare_and_set state running (`Client_cancelled ex) then
|
||||
enqueue (Error ex)
|
||||
)
|
||||
) else aux ()
|
||||
| `Finished -> enqueue (Error (Invalid_argument "Coroutine has already finished!"))
|
||||
| `Failed ex | `Client_cancelled ex -> enqueue (Error (Invalid_argument ("Coroutine has already failed: " ^ Printexc.to_string ex)))
|
||||
| `Running _ -> enqueue (Error (Invalid_argument "Coroutine is still running!"))
|
||||
| `Init -> assert false
|
||||
in
|
||||
aux ()
|
||||
)
|
||||
|
||||
let fork_seq ~sw fn =
|
||||
Seq.of_dispenser (fork_coroutine ~sw fn)
|
||||
|
@ -3,7 +3,7 @@ type 'a state =
|
||||
| Unresolved of Broadcast.t
|
||||
|
||||
type !'a promise = {
|
||||
id : Ctf.id;
|
||||
id : Trace.id;
|
||||
state : 'a state Atomic.t; (* Note: we always switch to Resolved before broadcasting *)
|
||||
}
|
||||
|
||||
@ -25,23 +25,23 @@ let create_with_id id =
|
||||
to_public_promise t, to_public_resolver t
|
||||
|
||||
let create ?label () =
|
||||
let id = Ctf.mint_id () in
|
||||
Ctf.note_created ?label id Ctf.Promise;
|
||||
let id = Trace.mint_id () in
|
||||
Trace.create_obj ?label id Promise;
|
||||
create_with_id id
|
||||
|
||||
let create_resolved x =
|
||||
let id = Ctf.mint_id () in
|
||||
Ctf.note_created id Ctf.Promise;
|
||||
let id = Trace.mint_id () in
|
||||
Trace.create_obj id Promise;
|
||||
to_public_promise { id; state = Atomic.make (Resolved x) }
|
||||
|
||||
let await t =
|
||||
let t = of_public_promise t in
|
||||
match Atomic.get t.state with
|
||||
| Resolved x ->
|
||||
Ctf.note_read t.id;
|
||||
Trace.get t.id;
|
||||
x
|
||||
| Unresolved b ->
|
||||
Suspend.enter (fun ctx enqueue ->
|
||||
Suspend.enter "Promise.await" (fun ctx enqueue ->
|
||||
match Broadcast.suspend b (fun () -> enqueue (Ok ())) with
|
||||
| None -> () (* We got resumed immediately *)
|
||||
| Some request ->
|
||||
@ -53,7 +53,7 @@ let await t =
|
||||
| Unresolved _ ->
|
||||
(* We observed the promise to be still unresolved after registering a waiter.
|
||||
Therefore any resolution must happen after we were registered and we will be notified. *)
|
||||
Ctf.note_try_read t.id;
|
||||
Trace.try_get t.id;
|
||||
Cancel.Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
if Broadcast.cancel request then enqueue (Error ex)
|
||||
(* else already resumed *)
|
||||
@ -61,7 +61,7 @@ let await t =
|
||||
);
|
||||
match Atomic.get t.state with
|
||||
| Resolved x ->
|
||||
Ctf.note_read t.id;
|
||||
Trace.get t.id;
|
||||
x
|
||||
| Unresolved _ -> assert false
|
||||
|
||||
@ -70,14 +70,15 @@ let await_exn t =
|
||||
| Ok x -> x
|
||||
| Error ex -> raise ex
|
||||
|
||||
let resolve t v =
|
||||
let try_resolve t v =
|
||||
let rec resolve' t v =
|
||||
match Atomic.get t.state with
|
||||
| Resolved _ -> invalid_arg "Can't resolve already-resolved promise"
|
||||
| Resolved _ -> false
|
||||
| Unresolved b as prev ->
|
||||
if Atomic.compare_and_set t.state prev (Resolved v) then (
|
||||
Ctf.note_resolved t.id ~ex:None;
|
||||
Broadcast.resume_all b
|
||||
Trace.put t.id;
|
||||
Broadcast.resume_all b;
|
||||
true
|
||||
) else (
|
||||
(* Otherwise, the promise was already resolved. Retry (to get the error). *)
|
||||
resolve' t v
|
||||
@ -85,6 +86,10 @@ let resolve t v =
|
||||
in
|
||||
resolve' (of_public_resolver t) v
|
||||
|
||||
let resolve u x =
|
||||
if not (try_resolve u x) then
|
||||
invalid_arg "Can't resolve already-resolved promise"
|
||||
|
||||
let resolve_ok u x = resolve u (Ok x)
|
||||
let resolve_error u x = resolve u (Error x)
|
||||
|
||||
|
@ -1,22 +1,42 @@
|
||||
(* A simplified version of [Waiters] that can only handle one waiter and is not thread-safe. *)
|
||||
type 'a state =
|
||||
| Running
|
||||
| Sleeping of (('a, exn) result -> unit)
|
||||
|
||||
type 'a t = {
|
||||
mutable wake : ('a, exn) result -> unit;
|
||||
}
|
||||
type 'a t = 'a state ref
|
||||
|
||||
let create () = { wake = ignore }
|
||||
let create () = ref Running
|
||||
|
||||
let wake t v = t.wake v
|
||||
let wake t v =
|
||||
match !t with
|
||||
| Running -> false
|
||||
| Sleeping fn ->
|
||||
t := Running;
|
||||
fn v;
|
||||
true
|
||||
|
||||
let await t id =
|
||||
Suspend.enter @@ fun ctx enqueue ->
|
||||
Cancel.Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
t.wake <- ignore;
|
||||
enqueue (Error ex)
|
||||
);
|
||||
t.wake <- (fun x ->
|
||||
Cancel.Fiber_context.clear_cancel_fn ctx;
|
||||
t.wake <- ignore;
|
||||
Ctf.note_read ~reader:id ctx.tid;
|
||||
enqueue x
|
||||
)
|
||||
let wake_if_sleeping t =
|
||||
ignore (wake t (Ok ()) : bool)
|
||||
|
||||
let await t op id =
|
||||
let x =
|
||||
Suspend.enter op @@ fun ctx enqueue ->
|
||||
Cancel.Fiber_context.set_cancel_fn ctx (fun ex ->
|
||||
t := Running;
|
||||
enqueue (Error ex)
|
||||
);
|
||||
t := Sleeping (fun x ->
|
||||
Cancel.Fiber_context.clear_cancel_fn ctx;
|
||||
t := Running;
|
||||
enqueue x
|
||||
)
|
||||
in
|
||||
Trace.get id;
|
||||
x
|
||||
|
||||
let await_protect t op id =
|
||||
let x =
|
||||
Suspend.enter_unchecked op @@ fun _ctx enqueue ->
|
||||
t := Sleeping (fun x -> t := Running; enqueue x)
|
||||
in
|
||||
Trace.get id;
|
||||
x
|
||||
|
25
lib_eio/core/single_waiter.mli
Normal file
25
lib_eio/core/single_waiter.mli
Normal file
@ -0,0 +1,25 @@
|
||||
(** Allows a single fiber to wait to be notified by another fiber in the same domain.
|
||||
If multiple fibers need to wait at once, or the notification comes from another domain,
|
||||
this can't be used. *)
|
||||
|
||||
type 'a t
|
||||
(** A handle representing a fiber that might be sleeping.
|
||||
It is either in the Running or Sleeping state. *)
|
||||
|
||||
val create : unit -> 'a t
|
||||
(** [create ()] is a new waiter, initially in the Running state. *)
|
||||
|
||||
val wake : 'a t -> ('a, exn) result -> bool
|
||||
(** [wake t v] resumes [t]'s fiber with value [v] and returns [true] if it was sleeping.
|
||||
If [t] is Running then this just returns [false]. *)
|
||||
|
||||
val wake_if_sleeping : unit t -> unit
|
||||
(** [wake_if_sleeping] is [ignore (wake t (Ok ()))]. *)
|
||||
|
||||
val await : 'a t -> string -> Trace.id -> 'a
|
||||
(** [await t op id] suspends the calling fiber, changing [t]'s state to Sleeping.
|
||||
If the fiber is cancelled, a cancel exception is raised.
|
||||
[op] and [id] are used for tracing. *)
|
||||
|
||||
val await_protect : 'a t -> string -> Trace.id -> 'a
|
||||
(** [await_protect] is like {!await}, but the sleep cannot be cancelled. *)
|
@ -1,10 +1,12 @@
|
||||
type 'a enqueue = ('a, exn) result -> unit
|
||||
type _ Effect.t += Suspend : (Cancel.fiber_context -> 'a enqueue -> unit) -> 'a Effect.t
|
||||
|
||||
let enter_unchecked fn = Effect.perform (Suspend fn)
|
||||
let enter_unchecked op fn =
|
||||
Trace.suspend_fiber op;
|
||||
Effect.perform (Suspend fn)
|
||||
|
||||
let enter fn =
|
||||
enter_unchecked @@ fun fiber enqueue ->
|
||||
let enter op fn =
|
||||
enter_unchecked op @@ fun fiber enqueue ->
|
||||
match Cancel.Fiber_context.get_error fiber with
|
||||
| None -> fn fiber enqueue
|
||||
| Some ex -> enqueue (Error ex)
|
||||
|
@ -1,28 +1,36 @@
|
||||
type t = {
|
||||
id : Ctf.id;
|
||||
mutable fibers : int; (* Total, including daemon_fibers and the main function *)
|
||||
mutable daemon_fibers : int;
|
||||
mutable exs : (exn * Printexc.raw_backtrace) option;
|
||||
on_release : (unit -> unit) Lwt_dllist.t;
|
||||
waiter : unit Waiters.t; (* The main [top]/[sub] function may wait here for fibers to finish. *)
|
||||
on_release_lock : Mutex.t;
|
||||
mutable on_release : (unit -> unit) Lwt_dllist.t option; (* [None] when closed. *)
|
||||
waiter : unit Single_waiter.t; (* The main [top]/[sub] function may wait here for fibers to finish. *)
|
||||
cancel : Cancel.t;
|
||||
}
|
||||
|
||||
type hook =
|
||||
| Null
|
||||
| Hook : Domain.id * 'a Lwt_dllist.node -> hook
|
||||
| Hook : Mutex.t * (unit -> unit) Lwt_dllist.node -> hook
|
||||
|
||||
let null_hook = Null
|
||||
|
||||
let remove_hook = function
|
||||
| Null -> ()
|
||||
| Hook (id, n) ->
|
||||
if Domain.self () <> id then invalid_arg "Switch hook removed from wrong domain!";
|
||||
Lwt_dllist.remove n
|
||||
let cancelled () = assert false
|
||||
|
||||
let try_remove_hook = function
|
||||
| Null -> false
|
||||
| Hook (on_release_lock, n) ->
|
||||
Mutex.lock on_release_lock;
|
||||
Lwt_dllist.remove n;
|
||||
let fn = Lwt_dllist.get n in
|
||||
Lwt_dllist.set n cancelled;
|
||||
Mutex.unlock on_release_lock;
|
||||
fn != cancelled
|
||||
|
||||
let remove_hook x = ignore (try_remove_hook x : bool)
|
||||
|
||||
let dump f t =
|
||||
Fmt.pf f "@[<v2>Switch %d (%d extra fibers):@,%a@]"
|
||||
(t.id :> int)
|
||||
(t.cancel.id :> int)
|
||||
t.fibers
|
||||
Cancel.dump t.cancel
|
||||
|
||||
@ -46,14 +54,12 @@ let combine_exn ex = function
|
||||
| Some ex1 -> Exn.combine ex1 ex
|
||||
|
||||
(* Note: raises if [t] is finished or called from wrong domain. *)
|
||||
let fail ?(bt=Printexc.get_raw_backtrace ()) t ex =
|
||||
let fail ?(bt=Exn.empty_backtrace) t ex =
|
||||
check_our_domain t;
|
||||
if t.exs = None then
|
||||
Ctf.note_resolved t.id ~ex:(Some ex);
|
||||
t.exs <- Some (combine_exn (ex, bt) t.exs);
|
||||
try
|
||||
Cancel.cancel t.cancel ex
|
||||
with Exn.Cancel_hook_failed _ as ex ->
|
||||
with ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
t.exs <- Some (combine_exn (ex, bt) t.exs)
|
||||
|
||||
@ -66,7 +72,7 @@ let dec_fibers t =
|
||||
if t.daemon_fibers > 0 && t.fibers = t.daemon_fibers then
|
||||
Cancel.cancel t.cancel Exit;
|
||||
if t.fibers = 0 then
|
||||
Waiters.wake_all t.waiter ()
|
||||
Single_waiter.wake_if_sleeping t.waiter
|
||||
|
||||
let with_op t fn =
|
||||
inc_fibers t;
|
||||
@ -89,26 +95,23 @@ let or_raise = function
|
||||
let rec await_idle t =
|
||||
(* Wait for fibers to finish: *)
|
||||
while t.fibers > 0 do
|
||||
Ctf.note_try_read t.id;
|
||||
Waiters.await ~mutex:None t.waiter t.id
|
||||
Trace.try_get t.cancel.id;
|
||||
Single_waiter.await_protect t.waiter "Switch.await_idle" t.cancel.id
|
||||
done;
|
||||
(* Call on_release handlers: *)
|
||||
let queue = Lwt_dllist.create () in
|
||||
Lwt_dllist.transfer_l t.on_release queue;
|
||||
let rec release () =
|
||||
match Lwt_dllist.take_opt_r queue with
|
||||
| None when t.fibers = 0 && Lwt_dllist.is_empty t.on_release -> ()
|
||||
| None -> await_idle t
|
||||
| Some fn ->
|
||||
begin
|
||||
try fn () with
|
||||
| ex -> fail t ex
|
||||
end;
|
||||
release ()
|
||||
(* Collect on_release handlers: *)
|
||||
let queue = ref [] in
|
||||
let enqueue n =
|
||||
let fn = Lwt_dllist.get n in
|
||||
Lwt_dllist.set n cancelled;
|
||||
queue := fn :: !queue
|
||||
in
|
||||
release ()
|
||||
|
||||
let await_idle t = Cancel.protect (fun _ -> await_idle t)
|
||||
Mutex.lock t.on_release_lock;
|
||||
Option.iter (Lwt_dllist.iter_node_l enqueue) t.on_release;
|
||||
t.on_release <- None;
|
||||
Mutex.unlock t.on_release_lock;
|
||||
(* Run on_release handlers *)
|
||||
!queue |> List.iter (fun fn -> try Cancel.protect fn with ex -> fail t ex);
|
||||
if t.fibers > 0 then await_idle t
|
||||
|
||||
let maybe_raise_exs t =
|
||||
match t.exs with
|
||||
@ -116,15 +119,13 @@ let maybe_raise_exs t =
|
||||
| Some (ex, bt) -> Printexc.raise_with_backtrace ex bt
|
||||
|
||||
let create cancel =
|
||||
let id = Ctf.mint_id () in
|
||||
Ctf.note_created id Ctf.Switch;
|
||||
{
|
||||
id;
|
||||
fibers = 1; (* The main function counts as a fiber *)
|
||||
daemon_fibers = 0;
|
||||
exs = None;
|
||||
waiter = Waiters.create ();
|
||||
on_release = Lwt_dllist.create ();
|
||||
waiter = Single_waiter.create ();
|
||||
on_release_lock = Mutex.create ();
|
||||
on_release = Some (Lwt_dllist.create ());
|
||||
cancel;
|
||||
}
|
||||
|
||||
@ -133,7 +134,7 @@ let run_internal t fn =
|
||||
| v ->
|
||||
dec_fibers t;
|
||||
await_idle t;
|
||||
Ctf.note_read t.id;
|
||||
Trace.get t.cancel.id;
|
||||
maybe_raise_exs t; (* Check for failure while finishing *)
|
||||
(* Success. *)
|
||||
v
|
||||
@ -144,15 +145,16 @@ let run_internal t fn =
|
||||
dec_fibers t;
|
||||
fail ~bt t ex;
|
||||
await_idle t;
|
||||
Ctf.note_read t.id;
|
||||
Trace.get t.cancel.id;
|
||||
maybe_raise_exs t;
|
||||
assert false
|
||||
|
||||
let run fn = Cancel.sub (fun cc -> run_internal (create cc) fn)
|
||||
let run ?name fn = Cancel.sub_checked ?name Switch (fun cc -> run_internal (create cc) fn)
|
||||
|
||||
let run_protected fn =
|
||||
let run_protected ?name fn =
|
||||
let ctx = Effect.perform Cancel.Get_context in
|
||||
Cancel.with_cc ~ctx ~parent:ctx.cancel_context ~protected:true @@ fun cancel ->
|
||||
Cancel.with_cc ~ctx ~parent:ctx.cancel_context ~protected:true Switch @@ fun cancel ->
|
||||
Option.iter (Trace.name cancel.id) name;
|
||||
run_internal (create cancel) fn
|
||||
|
||||
(* Run [fn ()] in [t]'s cancellation context.
|
||||
@ -176,25 +178,22 @@ let () =
|
||||
)
|
||||
|
||||
let on_release_full t fn =
|
||||
if Domain.self () = t.cancel.domain then (
|
||||
match t.cancel.state with
|
||||
| On | Cancelling _ -> Lwt_dllist.add_r fn t.on_release
|
||||
| Finished ->
|
||||
match Cancel.protect fn with
|
||||
| () -> invalid_arg "Switch finished!"
|
||||
| exception ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
Printexc.raise_with_backtrace (Release_error ("Switch finished!", ex)) bt
|
||||
) else (
|
||||
Mutex.lock t.on_release_lock;
|
||||
match t.on_release with
|
||||
| Some handlers ->
|
||||
let node = Lwt_dllist.add_r fn handlers in
|
||||
Mutex.unlock t.on_release_lock;
|
||||
node
|
||||
| None ->
|
||||
Mutex.unlock t.on_release_lock;
|
||||
match Cancel.protect fn with
|
||||
| () -> invalid_arg "Switch accessed from wrong domain!"
|
||||
| () -> invalid_arg "Switch finished!"
|
||||
| exception ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
Printexc.raise_with_backtrace (Release_error ("Switch accessed from wrong domain!", ex)) bt
|
||||
)
|
||||
Printexc.raise_with_backtrace (Release_error ("Switch finished!", ex)) bt
|
||||
|
||||
let on_release t fn =
|
||||
ignore (on_release_full t fn : _ Lwt_dllist.node)
|
||||
|
||||
let on_release_cancellable t fn =
|
||||
Hook (t.cancel.domain, on_release_full t fn)
|
||||
Hook (t.on_release_lock, on_release_full t fn)
|
||||
|
60
lib_eio/core/trace.ml
Normal file
60
lib_eio/core/trace.ml
Normal file
@ -0,0 +1,60 @@
|
||||
(* Copyright (C) 2014, Thomas Leonard *)
|
||||
|
||||
type id = int
|
||||
|
||||
let id_chunk_size = 1024
|
||||
|
||||
let next_id_chunk = Atomic.make 0
|
||||
|
||||
let next_id_key =
|
||||
Domain.DLS.new_key (fun () -> Atomic.fetch_and_add next_id_chunk id_chunk_size)
|
||||
|
||||
let mint_id () =
|
||||
let next_id_local = Domain.DLS.get next_id_key in
|
||||
let next_id_local_succ =
|
||||
if ((next_id_local + 1) mod id_chunk_size) = 0 then
|
||||
(* we're out of local IDs *)
|
||||
Atomic.fetch_and_add next_id_chunk id_chunk_size
|
||||
else
|
||||
next_id_local + 1
|
||||
in
|
||||
Domain.DLS.set next_id_key next_id_local_succ;
|
||||
next_id_local
|
||||
|
||||
module RE = Eio_runtime_events
|
||||
|
||||
let add_event = Runtime_events.User.write
|
||||
|
||||
let create_obj ?label id ty =
|
||||
add_event RE.create_obj (id, ty);
|
||||
Option.iter (fun l -> add_event RE.name (id, l)) label
|
||||
|
||||
let create_cc id ty =
|
||||
add_event RE.create_cc (id, ty)
|
||||
|
||||
let create_fiber ~cc id =
|
||||
add_event RE.create_fiber (id, cc)
|
||||
|
||||
let log = add_event RE.log
|
||||
let name id x = add_event RE.name (id, x)
|
||||
let enter_span = add_event RE.enter_span
|
||||
let exit_span = add_event RE.exit_span
|
||||
let fiber = add_event RE.fiber
|
||||
let suspend_domain = add_event RE.suspend_domain
|
||||
let try_get = add_event RE.try_get
|
||||
let get = add_event RE.get
|
||||
let put = add_event RE.put
|
||||
let exit_fiber = add_event RE.exit_fiber
|
||||
let exit_cc = add_event RE.exit_cc
|
||||
let error id ex = add_event RE.error (id, ex)
|
||||
let suspend_fiber op = add_event RE.suspend_fiber op
|
||||
let domain_spawn ~parent = add_event RE.domain_spawn parent
|
||||
|
||||
let with_span op fn =
|
||||
enter_span op;
|
||||
match fn () with
|
||||
| r -> exit_span (); r
|
||||
| exception ex ->
|
||||
let bt = Printexc.get_raw_backtrace () in
|
||||
exit_span ();
|
||||
Printexc.raise_with_backtrace ex bt
|
61
lib_eio/core/trace.mli
Normal file
61
lib_eio/core/trace.mli
Normal file
@ -0,0 +1,61 @@
|
||||
(** Trace Eio events using OCaml's runtime events system. *)
|
||||
|
||||
type id = private int
|
||||
(** Each thread/fiber/promise is identified by a unique ID. *)
|
||||
|
||||
val mint_id : unit -> id
|
||||
(** [mint_id ()] is a fresh unique [id]. *)
|
||||
|
||||
(** {2 Recording events}
|
||||
Libraries and applications can use these functions to make the traces more useful. *)
|
||||
|
||||
val log : string -> unit
|
||||
(** [log msg] attaches text [msg] to the current fiber. *)
|
||||
|
||||
val name : id -> string -> unit
|
||||
(** [name id label] sets [label] as the name for [id]. *)
|
||||
|
||||
val with_span : string -> (unit -> 'a) -> 'a
|
||||
(** [with_span op fn] runs [fn ()], labelling the timespan during which it runs with [op]. *)
|
||||
|
||||
val suspend_fiber : string -> unit
|
||||
(** [suspend_fiber op] records that the current fiber is now suspended waiting for [op]. *)
|
||||
|
||||
(** {2 Recording system events}
|
||||
These are normally only called by the scheduler. *)
|
||||
|
||||
val create_fiber : cc:id -> id -> unit
|
||||
(** [create_fiber ~cc id] records the creation of fiber [id] in context [cc]. *)
|
||||
|
||||
val create_cc : id -> Eio_runtime_events.cc_ty -> unit
|
||||
(** [create_cc id ty] records the creation of cancellation context [id]. *)
|
||||
|
||||
val create_obj : ?label:string -> id -> Eio_runtime_events.obj_ty -> unit
|
||||
(** [create_obj id ty] records the creation of [id]. *)
|
||||
|
||||
val get : id -> unit
|
||||
(** [get src] records reading a promise, taking from a stream, taking a lock, etc. *)
|
||||
|
||||
val try_get : id -> unit
|
||||
(** [try_get src] records that the current fiber wants to get from [src] (which is not currently ready). *)
|
||||
|
||||
val put : id -> unit
|
||||
(** [put dst] records resolving a promise, adding to a stream, releasing a lock, etc. *)
|
||||
|
||||
val fiber : id -> unit
|
||||
(** [fiber id] records that [id] is now the current fiber for this domain. *)
|
||||
|
||||
val suspend_domain : Runtime_events.Type.span -> unit
|
||||
(** [suspend_domain] records when the event loop is stopped waiting for events from the OS. *)
|
||||
|
||||
val domain_spawn : parent:id -> unit
|
||||
(** [domain_spawn ~parent] records that the current domain was spawned by fiber [parent]. *)
|
||||
|
||||
val exit_cc : unit -> unit
|
||||
(** [exit_cc ()] records that the current CC has finished. *)
|
||||
|
||||
val exit_fiber : id -> unit
|
||||
(** [exit_fiber id] records that fiber [id] has finished. *)
|
||||
|
||||
val error : id -> exn -> unit
|
||||
(** [error id exn] records that [id] received an error. *)
|
@ -1,20 +0,0 @@
|
||||
(* See [eio__core.mli] for details. *)
|
||||
|
||||
type 'a t
|
||||
|
||||
val create : unit -> 'a t
|
||||
|
||||
val wake_all : 'a t -> 'a -> unit
|
||||
|
||||
val wake_one : 'a t -> 'a -> [`Ok | `Queue_empty]
|
||||
|
||||
val is_empty : 'a t -> bool
|
||||
|
||||
val await :
|
||||
mutex:Mutex.t option ->
|
||||
'a t -> Ctf.id -> 'a
|
||||
|
||||
val await_internal :
|
||||
mutex:Mutex.t option ->
|
||||
'a t -> Ctf.id -> Cancel.fiber_context ->
|
||||
(('a, exn) result -> unit) -> unit
|
@ -1,12 +1,29 @@
|
||||
class virtual t = object
|
||||
method virtual run : 'a. (cancelled:exn Promise.t -> 'a) -> 'a
|
||||
method virtual run_raw : 'a. (unit -> 'a) -> 'a
|
||||
open Std
|
||||
|
||||
type ty = [`Domain_mgr]
|
||||
type 'a t = ([> ty] as 'a) r
|
||||
|
||||
module Pi = struct
|
||||
module type MGR = sig
|
||||
type t
|
||||
val run : t -> (cancelled:exn Promise.t -> 'a) -> 'a
|
||||
val run_raw : t -> (unit -> 'a) -> 'a
|
||||
end
|
||||
|
||||
type (_, _, _) Resource.pi +=
|
||||
| Mgr : ('t, (module MGR with type t = 't), [> ty]) Resource.pi
|
||||
|
||||
let mgr (type t) (module X : MGR with type t = t) =
|
||||
Resource.handler [H (Mgr, (module X))]
|
||||
end
|
||||
|
||||
let run_raw (t : #t) = t#run_raw
|
||||
let run_raw (Resource.T (t, ops)) fn =
|
||||
let module X = (val (Resource.get ops Pi.Mgr)) in
|
||||
X.run_raw t fn
|
||||
|
||||
let run (t : #t) fn =
|
||||
t#run @@ fun ~cancelled ->
|
||||
let run (Resource.T (t, ops)) fn =
|
||||
let module X = (val (Resource.get ops Pi.Mgr)) in
|
||||
X.run t @@ fun ~cancelled ->
|
||||
(* If the spawning fiber is cancelled, [cancelled] gets set to the exception. *)
|
||||
try
|
||||
Fiber.first
|
||||
|
37
lib_eio/domain_manager.mli
Normal file
37
lib_eio/domain_manager.mli
Normal file
@ -0,0 +1,37 @@
|
||||
type ty = [`Domain_mgr]
|
||||
type 'a t = ([> ty] as 'a) Resource.t
|
||||
|
||||
val run : _ t -> (unit -> 'a) -> 'a
|
||||
(** [run t f] runs [f ()] in a newly-created domain and returns the result.
|
||||
|
||||
Other fibers in the calling domain can run in parallel with the new domain.
|
||||
|
||||
Warning: [f] must only access thread-safe values from the calling domain,
|
||||
but this is not enforced by the type system.
|
||||
|
||||
If the calling fiber is cancelled, this is propagated to the spawned domain. *)
|
||||
|
||||
val run_raw : _ t -> (unit -> 'a) -> 'a
|
||||
(** [run_raw t f] is like {!run}, but does not run an event loop in the new domain,
|
||||
and so cannot perform IO, fork fibers, etc. *)
|
||||
|
||||
(** {2 Provider Interface} *)
|
||||
|
||||
module Pi : sig
|
||||
module type MGR = sig
|
||||
type t
|
||||
|
||||
val run : t -> (cancelled:exn Promise.t -> 'a) -> 'a
|
||||
(** [run t fn] runs [fn ~cancelled] in a new domain.
|
||||
|
||||
If the calling fiber is cancelled, [cancelled] becomes resolved to the {!Cancel.Cancelled} exception.
|
||||
[fn] should cancel itself in this case. *)
|
||||
|
||||
val run_raw : t -> (unit -> 'a) -> 'a
|
||||
end
|
||||
|
||||
type (_, _, _) Resource.pi +=
|
||||
| Mgr : ('t, (module MGR with type t = 't), [> ty]) Resource.pi
|
||||
|
||||
val mgr : (module MGR with type t = 't) -> ('t, ty) Resource.handler
|
||||
end
|
@ -1,28 +1,28 @@
|
||||
include Eio__core
|
||||
|
||||
module Fibre = Fiber
|
||||
|
||||
module Debug = Private.Debug
|
||||
let traceln = Debug.traceln
|
||||
|
||||
module Std = struct
|
||||
module Promise = Promise
|
||||
module Fiber = Fiber
|
||||
module Fibre = Fiber
|
||||
module Switch = Switch
|
||||
let traceln = Debug.traceln
|
||||
end
|
||||
|
||||
module Std = Std
|
||||
module Semaphore = Semaphore
|
||||
module Mutex = Eio_mutex
|
||||
module Condition = Condition
|
||||
module Stream = Stream
|
||||
module Lazy = Lazy
|
||||
module Pool = Pool
|
||||
module Executor_pool = Executor_pool
|
||||
module Exn = Exn
|
||||
module Generic = Generic
|
||||
module Flow = Flow
|
||||
module Resource = Resource
|
||||
module Buf_read = Buf_read
|
||||
module Flow = struct
|
||||
include Flow
|
||||
|
||||
let read_all flow =
|
||||
Buf_read.(parse_exn take_all) flow ~max_size:max_int
|
||||
end
|
||||
module Buf_write = Buf_write
|
||||
module Net = Net
|
||||
module Process = Process
|
||||
module Domain_manager = Domain_manager
|
||||
module Time = Time
|
||||
module File = File
|
||||
@ -30,31 +30,19 @@ module Fs = Fs
|
||||
module Path = Path
|
||||
|
||||
module Stdenv = struct
|
||||
type t = <
|
||||
stdin : Flow.source;
|
||||
stdout : Flow.sink;
|
||||
stderr : Flow.sink;
|
||||
net : Net.t;
|
||||
domain_mgr : Domain_manager.t;
|
||||
clock : Time.clock;
|
||||
mono_clock : Time.Mono.t;
|
||||
fs : Fs.dir Path.t;
|
||||
cwd : Fs.dir Path.t;
|
||||
secure_random : Flow.source;
|
||||
debug : Debug.t;
|
||||
>
|
||||
|
||||
let stdin (t : <stdin : #Flow.source; ..>) = t#stdin
|
||||
let stdout (t : <stdout : #Flow.sink; ..>) = t#stdout
|
||||
let stderr (t : <stderr : #Flow.sink; ..>) = t#stderr
|
||||
let net (t : <net : #Net.t; ..>) = t#net
|
||||
let domain_mgr (t : <domain_mgr : #Domain_manager.t; ..>) = t#domain_mgr
|
||||
let clock (t : <clock : #Time.clock; ..>) = t#clock
|
||||
let mono_clock (t : <mono_clock : #Time.Mono.t; ..>) = t#mono_clock
|
||||
let secure_random (t: <secure_random : #Flow.source; ..>) = t#secure_random
|
||||
let fs (t : <fs : #Fs.dir Path.t; ..>) = t#fs
|
||||
let cwd (t : <cwd : #Fs.dir Path.t; ..>) = t#cwd
|
||||
let stdin (t : <stdin : _ Flow.source; ..>) = t#stdin
|
||||
let stdout (t : <stdout : _ Flow.sink; ..>) = t#stdout
|
||||
let stderr (t : <stderr : _ Flow.sink; ..>) = t#stderr
|
||||
let net (t : <net : _ Net.t; ..>) = t#net
|
||||
let process_mgr (t : <process_mgr : _ Process.mgr; ..>) = t#process_mgr
|
||||
let domain_mgr (t : <domain_mgr : _ Domain_manager.t; ..>) = t#domain_mgr
|
||||
let clock (t : <clock : _ Time.clock; ..>) = t#clock
|
||||
let mono_clock (t : <mono_clock : _ Time.Mono.t; ..>) = t#mono_clock
|
||||
let secure_random (t: <secure_random : _ Flow.source; ..>) = t#secure_random
|
||||
let fs (t : <fs : _ Path.t; ..>) = t#fs
|
||||
let cwd (t : <cwd : _ Path.t; ..>) = t#cwd
|
||||
let debug (t : <debug : 'a; ..>) = t#debug
|
||||
let backend_id (t: <backend_id : string; ..>) = t#backend_id
|
||||
end
|
||||
|
||||
exception Io = Exn.Io
|
||||
|
257
lib_eio/eio.mli
257
lib_eio/eio.mli
@ -13,20 +13,24 @@
|
||||
|
||||
See {{:https://github.com/ocaml-multicore/eio}} for a tutorial. *)
|
||||
|
||||
(** {1 Concurrency primitives} *)
|
||||
(** Commonly used standard features. This module is intended to be [open]ed. *)
|
||||
module Std = Std
|
||||
|
||||
(** {1 Fibers} *)
|
||||
|
||||
(** Grouping fibers and other resources so they can be turned off together. *)
|
||||
module Switch = Eio__core.Switch
|
||||
|
||||
(** A promise is a placeholder for result that will arrive in the future. *)
|
||||
module Promise = Eio__core.Promise
|
||||
|
||||
(** A fiber is a light-weight thread. *)
|
||||
module Fiber = Eio__core.Fiber
|
||||
|
||||
(**/**)
|
||||
module Fibre = Fiber [@@deprecated "Now spelt Fiber"]
|
||||
(**/**)
|
||||
(** Cancelling fibers. *)
|
||||
module Cancel = Eio__core.Cancel
|
||||
|
||||
(** {1 Concurrency primitives} *)
|
||||
|
||||
(** A promise is a placeholder for result that will arrive in the future. *)
|
||||
module Promise = Eio__core.Promise
|
||||
|
||||
(** A counting semaphore. *)
|
||||
module Semaphore = Semaphore
|
||||
@ -37,91 +41,53 @@ module Mutex = Eio_mutex
|
||||
(** Waiting for a condition to become true. *)
|
||||
module Condition = Condition
|
||||
|
||||
(** Delayed evaluation. *)
|
||||
module Lazy = Lazy
|
||||
|
||||
(** {1 Collections} *)
|
||||
|
||||
(** A stream/queue. *)
|
||||
module Stream = Stream
|
||||
|
||||
(** Cancelling fibers. *)
|
||||
module Cancel = Eio__core.Cancel
|
||||
(** A pool of resources. *)
|
||||
module Pool = Pool
|
||||
|
||||
(** Commonly used standard features. This module is intended to be [open]ed. *)
|
||||
module Std : sig
|
||||
module Promise = Promise
|
||||
module Fiber = Fiber
|
||||
(**/**)
|
||||
module Fibre = Fiber [@@deprecated "Now spelt Fiber"]
|
||||
(**/**)
|
||||
module Switch = Switch
|
||||
|
||||
val traceln :
|
||||
?__POS__:string * int * int * int ->
|
||||
('a, Format.formatter, unit, unit) format4 -> 'a
|
||||
(** Same as {!Eio.traceln}. *)
|
||||
end
|
||||
|
||||
(** {1 Cross-platform OS API}
|
||||
|
||||
The general pattern here is that each type of resource has a set of functions for using it,
|
||||
plus an object type to allow defining your own implementations.
|
||||
To use the resources, it is recommended that you use the functions rather than calling
|
||||
methods directly. Using the functions results in better error messages from the compiler,
|
||||
and may provide extra features or sanity checks.
|
||||
|
||||
The system resources are available from the {!Stdenv.t} provided by your event loop
|
||||
(e.g. {!Eio_main.run}). *)
|
||||
|
||||
(** A base class for objects that can be queried at runtime for extra features. *)
|
||||
module Generic = Generic
|
||||
|
||||
(** Byte streams. *)
|
||||
module Flow = Flow
|
||||
|
||||
(** Buffered input and parsing *)
|
||||
module Buf_read = Buf_read
|
||||
|
||||
(** Buffered output *)
|
||||
module Buf_write = Buf_write
|
||||
|
||||
(** Networking. *)
|
||||
module Net = Net
|
||||
(** {1 Multiple domains} *)
|
||||
|
||||
(** Parallel computation across multiple CPU cores. *)
|
||||
module Domain_manager : sig
|
||||
class virtual t : object
|
||||
method virtual run_raw : 'a. (unit -> 'a) -> 'a
|
||||
module Domain_manager = Domain_manager
|
||||
|
||||
method virtual run : 'a. (cancelled:exn Promise.t -> 'a) -> 'a
|
||||
(** [t#run fn] runs [fn ~cancelled] in a new domain.
|
||||
(** A pool of domains for executing jobs. *)
|
||||
module Executor_pool = Executor_pool
|
||||
|
||||
If the calling fiber is cancelled, [cancelled] becomes resolved to the {!Cancel.Cancelled} exception.
|
||||
[fn] should cancel itself in this case. *)
|
||||
end
|
||||
(** {1 Errors and debugging} *)
|
||||
|
||||
val run : #t -> (unit -> 'a) -> 'a
|
||||
(** [run t f] runs [f ()] in a newly-created domain and returns the result.
|
||||
val traceln :
|
||||
?__POS__:string * int * int * int ->
|
||||
('a, Format.formatter, unit, unit) format4 -> 'a
|
||||
(** [traceln fmt] outputs a debug message (typically to stderr).
|
||||
|
||||
Other fibers in the calling domain can run in parallel with the new domain.
|
||||
Trace messages are printed by default and do not require logging to be configured first.
|
||||
The message is printed with a newline, and is flushed automatically.
|
||||
[traceln] is intended for quick debugging rather than for production code.
|
||||
|
||||
Warning: [f] must only access thread-safe values from the calling domain,
|
||||
but this is not enforced by the type system.
|
||||
Unlike most Eio operations, [traceln] will never switch to another fiber;
|
||||
if the OS is not ready to accept the message then the whole domain waits.
|
||||
|
||||
If the calling fiber is cancelled, this is propagated to the spawned domain. *)
|
||||
It is safe to call [traceln] from multiple domains at the same time.
|
||||
Each line will be written atomically.
|
||||
|
||||
val run_raw : #t -> (unit -> 'a) -> 'a
|
||||
(** [run_raw t f] is like {!run}, but does not run an event loop in the new domain,
|
||||
and so cannot perform IO, fork fibers, etc. *)
|
||||
end
|
||||
Examples:
|
||||
{[
|
||||
traceln "x = %d" x;
|
||||
traceln "x = %d" x ~__POS__; (* With location information *)
|
||||
]}
|
||||
@param __POS__ Display [__POS__] as the location of the [traceln] call. *)
|
||||
|
||||
(** Clocks, time, sleeping and timeouts. *)
|
||||
module Time = Time
|
||||
(** Eio exceptions. *)
|
||||
module Exn = Eio__core.Exn
|
||||
|
||||
(** Operations on open files. *)
|
||||
module File = File
|
||||
|
||||
(** File-system types. *)
|
||||
module Fs = Fs
|
||||
|
||||
(** Accessing paths on a file-system. *)
|
||||
module Path = Path
|
||||
exception Io of Exn.err * Exn.context
|
||||
|
||||
(** Control over debugging. *)
|
||||
module Debug : sig
|
||||
@ -154,16 +120,78 @@ module Debug : sig
|
||||
If the system is not ready to receive the trace output,
|
||||
the whole domain must block until it is. *)
|
||||
|
||||
val with_trace_prefix : (Format.formatter -> unit) -> (unit -> 'a) -> 'a
|
||||
(** [with_trace_prefix fmt fn] runs [fn ()] with a traceln that outputs [fmt] before each message. *)
|
||||
|
||||
type t = <
|
||||
traceln : traceln Fiber.key;
|
||||
>
|
||||
(** Fiber keys used to control debugging. Use {!Stdenv.debug} to get this. *)
|
||||
end
|
||||
|
||||
(** {1 Cross-platform OS API}
|
||||
|
||||
The general pattern here is that each type of resource has a set of functions for using it,
|
||||
plus a provider ([Pi]) module to allow defining your own implementations.
|
||||
|
||||
The system resources are available from the environment argument provided by your event loop
|
||||
(e.g. {!Eio_main.run}). *)
|
||||
|
||||
(** Defines the base resource type. *)
|
||||
module Resource = Resource
|
||||
|
||||
(** {2 Byte streams} *)
|
||||
|
||||
(** A flow can be used to read or write bytes. *)
|
||||
module Flow : sig
|
||||
include module type of Flow (** @inline *)
|
||||
|
||||
(** {2 Convenience wrappers} *)
|
||||
|
||||
val read_all : _ source -> string
|
||||
(** [read_all src] is a convenience wrapper to read an entire flow.
|
||||
|
||||
It is the same as [Buf_read.(parse_exn take_all) src ~max_size:max_int] *)
|
||||
end
|
||||
|
||||
(** Buffered input and parsing. *)
|
||||
module Buf_read = Buf_read
|
||||
|
||||
(** Buffered output and formatting. *)
|
||||
module Buf_write = Buf_write
|
||||
|
||||
(** {2 Networking} *)
|
||||
|
||||
(** Network sockets and addresses. *)
|
||||
module Net = Net
|
||||
|
||||
(** {2 File-systems} *)
|
||||
|
||||
(** Accessing paths on a file-system. *)
|
||||
module Path = Path
|
||||
|
||||
(** Operations on open files. *)
|
||||
module File = File
|
||||
|
||||
(** File-system types. *)
|
||||
module Fs = Fs
|
||||
|
||||
(** {2 Processes} *)
|
||||
|
||||
(** Managing child processes. *)
|
||||
module Process = Process
|
||||
|
||||
(** {2 Time} *)
|
||||
|
||||
(** Clocks, time, sleeping and timeouts. *)
|
||||
module Time = Time
|
||||
|
||||
(** {2 Main env} *)
|
||||
|
||||
(** The standard environment of a process. *)
|
||||
module Stdenv : sig
|
||||
(** All access to the outside world comes from running the event loop,
|
||||
which provides a {!t}.
|
||||
which provides an environment (e.g. an {!Eio_unix.Stdenv.base}).
|
||||
|
||||
Example:
|
||||
{[
|
||||
@ -175,27 +203,13 @@ module Stdenv : sig
|
||||
]}
|
||||
*)
|
||||
|
||||
type t = <
|
||||
stdin : Flow.source;
|
||||
stdout : Flow.sink;
|
||||
stderr : Flow.sink;
|
||||
net : Net.t;
|
||||
domain_mgr : Domain_manager.t;
|
||||
clock : Time.clock;
|
||||
mono_clock : Time.Mono.t;
|
||||
fs : Fs.dir Path.t;
|
||||
cwd : Fs.dir Path.t;
|
||||
secure_random : Flow.source;
|
||||
debug : Debug.t;
|
||||
>
|
||||
|
||||
(** {1 Standard streams}
|
||||
|
||||
To use these, see {!Flow}. *)
|
||||
|
||||
val stdin : <stdin : #Flow.source as 'a; ..> -> 'a
|
||||
val stdout : <stdout : #Flow.sink as 'a; ..> -> 'a
|
||||
val stderr : <stderr : #Flow.sink as 'a; ..> -> 'a
|
||||
val stdin : <stdin : _ Flow.source as 'a; ..> -> 'a
|
||||
val stdout : <stdout : _ Flow.sink as 'a; ..> -> 'a
|
||||
val stderr : <stderr : _ Flow.sink as 'a; ..> -> 'a
|
||||
|
||||
(** {1 File-system access}
|
||||
|
||||
@ -219,15 +233,23 @@ module Stdenv : sig
|
||||
To use this, see {!Net}.
|
||||
*)
|
||||
|
||||
val net : <net : #Net.t as 'a; ..> -> 'a
|
||||
val net : <net : _ Net.t as 'a; ..> -> 'a
|
||||
(** [net t] gives access to the process's network namespace. *)
|
||||
|
||||
(** {1 Processes }
|
||||
|
||||
To use this, see {!Process}.
|
||||
*)
|
||||
|
||||
val process_mgr : <process_mgr : _ Process.mgr as 'a; ..> -> 'a
|
||||
(** [process_mgr t] allows you to manage child processes. *)
|
||||
|
||||
(** {1 Domains (using multiple CPU cores)}
|
||||
|
||||
To use this, see {!Domain_manager}.
|
||||
*)
|
||||
|
||||
val domain_mgr : <domain_mgr : #Domain_manager.t as 'a; ..> -> 'a
|
||||
val domain_mgr : <domain_mgr : _ Domain_manager.t as 'a; ..> -> 'a
|
||||
(** [domain_mgr t] allows running code on other cores. *)
|
||||
|
||||
(** {1 Time}
|
||||
@ -235,52 +257,29 @@ module Stdenv : sig
|
||||
To use this, see {!Time}.
|
||||
*)
|
||||
|
||||
val clock : <clock : #Time.clock as 'a; ..> -> 'a
|
||||
val clock : <clock : _ Time.clock as 'a; ..> -> 'a
|
||||
(** [clock t] is the system clock (used to get the current time and date). *)
|
||||
|
||||
val mono_clock : <mono_clock : #Time.Mono.t as 'a; ..> -> 'a
|
||||
val mono_clock : <mono_clock : _ Time.Mono.t as 'a; ..> -> 'a
|
||||
(** [mono_clock t] is a monotonic clock (used for measuring intervals). *)
|
||||
|
||||
(** {1 Randomness} *)
|
||||
|
||||
val secure_random : <secure_random : #Flow.source as 'a; ..> -> 'a
|
||||
val secure_random : <secure_random : _ Flow.source as 'a; ..> -> 'a
|
||||
(** [secure_random t] is an infinite source of random bytes suitable for cryptographic purposes. *)
|
||||
|
||||
(** {1 Debugging} *)
|
||||
|
||||
val debug : <debug : <Debug.t; ..> as 'a; ..> -> 'a
|
||||
(** [debug t] provides privileged controls for debugging. *)
|
||||
|
||||
val backend_id : <backend_id:string; ..> -> string
|
||||
(** [backend_id t] provides the name of the backend being used.
|
||||
|
||||
The possible values are the same as the possible values of the "EIO_BACKEND"
|
||||
environment variable used by {!Eio_main.run}. *)
|
||||
end
|
||||
|
||||
(** {1 Errors and Debugging} *)
|
||||
|
||||
exception Io of Exn.err * Exn.context
|
||||
|
||||
val traceln :
|
||||
?__POS__:string * int * int * int ->
|
||||
('a, Format.formatter, unit, unit) format4 -> 'a
|
||||
(** [traceln fmt] outputs a debug message (typically to stderr).
|
||||
|
||||
Trace messages are printed by default and do not require logging to be configured first.
|
||||
The message is printed with a newline, and is flushed automatically.
|
||||
[traceln] is intended for quick debugging rather than for production code.
|
||||
|
||||
Unlike most Eio operations, [traceln] will never switch to another fiber;
|
||||
if the OS is not ready to accept the message then the whole domain waits.
|
||||
|
||||
It is safe to call [traceln] from multiple domains at the same time.
|
||||
Each line will be written atomically.
|
||||
|
||||
Examples:
|
||||
{[
|
||||
traceln "x = %d" x;
|
||||
traceln "x = %d" x ~__POS__; (* With location information *)
|
||||
]}
|
||||
@param __POS__ Display [__POS__] as the location of the [traceln] call. *)
|
||||
|
||||
(** Eio exceptions. *)
|
||||
module Exn = Eio__core.Exn
|
||||
|
||||
(** {1 Provider API for OS schedulers} *)
|
||||
|
||||
(** API for use by the scheduler implementation. *)
|
||||
|
@ -6,7 +6,7 @@ type state =
|
||||
exception Poisoned of exn
|
||||
|
||||
type t = {
|
||||
id : Ctf.id;
|
||||
id : Trace.id;
|
||||
mutex : Mutex.t;
|
||||
mutable state : state; (* Owned by [t.mutex] *)
|
||||
waiters : [`Take | `Error of exn] Waiters.t; (* Owned by [t.mutex] *)
|
||||
@ -19,8 +19,8 @@ type t = {
|
||||
|
||||
(* {R} t = create () {mutex t R} *)
|
||||
let create () =
|
||||
let id = Ctf.mint_id () in
|
||||
Ctf.note_created id Ctf.Mutex;
|
||||
let id = Trace.mint_id () in
|
||||
Trace.create_obj id Mutex;
|
||||
{
|
||||
id;
|
||||
mutex = Mutex.create ();
|
||||
@ -33,7 +33,7 @@ let create () =
|
||||
let unlock t =
|
||||
Mutex.lock t.mutex;
|
||||
(* We now have ownership of [t.state] and [t.waiters]. *)
|
||||
Ctf.note_signal t.id;
|
||||
Trace.put t.id;
|
||||
match t.state with
|
||||
| Unlocked ->
|
||||
Mutex.unlock t.mutex;
|
||||
@ -55,16 +55,18 @@ let lock t =
|
||||
Mutex.lock t.mutex;
|
||||
match t.state with
|
||||
| Locked ->
|
||||
Ctf.note_try_read t.id;
|
||||
begin match Waiters.await ~mutex:(Some t.mutex) t.waiters t.id with
|
||||
| `Error ex -> raise ex (* Poisoned; stop waiting *)
|
||||
Trace.try_get t.id;
|
||||
begin match Waiters.await ~mutex:(Some t.mutex) "Mutex.lock" t.waiters with
|
||||
| `Error ex ->
|
||||
Trace.get t.id;
|
||||
raise ex (* Poisoned; stop waiting *)
|
||||
| `Take ->
|
||||
(* The unlocker didn't change the state, so it's still Locked, as required.
|
||||
{locked t * R} *)
|
||||
()
|
||||
Trace.get t.id
|
||||
end
|
||||
| Unlocked ->
|
||||
Ctf.note_read t.id;
|
||||
Trace.get t.id;
|
||||
t.state <- Locked; (* We transfer R from the state to our caller. *)
|
||||
(* {locked t * R} *)
|
||||
Mutex.unlock t.mutex
|
||||
@ -77,11 +79,11 @@ let try_lock t =
|
||||
Mutex.lock t.mutex;
|
||||
match t.state with
|
||||
| Locked ->
|
||||
Ctf.note_try_read t.id;
|
||||
Trace.try_get t.id;
|
||||
Mutex.unlock t.mutex;
|
||||
false
|
||||
| Unlocked ->
|
||||
Ctf.note_read t.id;
|
||||
Trace.get t.id;
|
||||
t.state <- Locked; (* We transfer R from the state to our caller. *)
|
||||
Mutex.unlock t.mutex;
|
||||
(* {locked t * R} *)
|
||||
|
74
lib_eio/executor_pool.ml
Normal file
74
lib_eio/executor_pool.ml
Normal file
@ -0,0 +1,74 @@
|
||||
type job = Pack : {
|
||||
fn : unit -> 'a;
|
||||
w : ('a, exn) Result.t Promise.u;
|
||||
weight : int;
|
||||
} -> job
|
||||
|
||||
type t = {
|
||||
queue : job Sync.t;
|
||||
}
|
||||
|
||||
let max_capacity = 1_000_000
|
||||
|
||||
let max_capacity_f = float max_capacity
|
||||
|
||||
(* This function is the core of executor_pool.ml.
|
||||
Each worker runs in its own domain,
|
||||
taking jobs from [queue] whenever it has spare capacity. *)
|
||||
let run_worker { queue } =
|
||||
Switch.run ~name:"run_worker" @@ fun sw ->
|
||||
let capacity = ref 0 in
|
||||
let condition = Condition.create () in
|
||||
(* The main worker loop. *)
|
||||
let rec loop () =
|
||||
while !capacity >= max_capacity do Condition.await_no_mutex condition done;
|
||||
match Sync.take queue with
|
||||
| Error `Closed -> `Stop_daemon
|
||||
| Ok (Pack { fn; w; weight }) ->
|
||||
capacity := !capacity + weight;
|
||||
Option.iter (Promise.resolve_error w) (Switch.get_error sw);
|
||||
Fiber.fork ~sw (fun () ->
|
||||
Promise.resolve w (try Ok (fn ()) with ex -> Error ex);
|
||||
capacity := !capacity - weight;
|
||||
Condition.broadcast condition
|
||||
);
|
||||
(* Give a chance to other domains to start waiting on [queue]
|
||||
before the current thread blocks on [Sync.take] again. *)
|
||||
Fiber.yield ();
|
||||
(loop [@tailcall]) ()
|
||||
in
|
||||
loop ()
|
||||
|
||||
let create ~sw ~domain_count domain_mgr =
|
||||
let queue = Sync.create () in
|
||||
let t = { queue } in
|
||||
Switch.on_release sw (fun () -> Sync.close queue);
|
||||
for _ = 1 to domain_count do
|
||||
(* Workers run as daemons to not hold the user's switch from completing.
|
||||
It's up to the user to hold the switch open (and thus, the executor pool)
|
||||
by blocking on the jobs issued to the pool. *)
|
||||
Fiber.fork_daemon ~sw (fun () ->
|
||||
Domain_manager.run domain_mgr (fun () ->
|
||||
run_worker t))
|
||||
done;
|
||||
t
|
||||
|
||||
let enqueue { queue } ~weight fn =
|
||||
if not (weight >= 0. && weight <= 1.) (* Handles NaN *)
|
||||
then Fmt.invalid_arg "Executor_pool: weight %g not >= 0.0 && <= 1.0" weight
|
||||
else (
|
||||
let weight = Float.to_int (weight *. max_capacity_f) in
|
||||
let p, w = Promise.create () in
|
||||
Sync.put queue (Pack { fn; w; weight });
|
||||
p
|
||||
)
|
||||
|
||||
let submit t ~weight fn =
|
||||
enqueue t ~weight fn |> Promise.await
|
||||
|
||||
let submit_exn t ~weight fn =
|
||||
enqueue t ~weight fn |> Promise.await_exn
|
||||
|
||||
let submit_fork ~sw t ~weight fn =
|
||||
(* [enqueue] blocks until the job is accepted, so we have to fork here. *)
|
||||
Fiber.fork_promise ~sw (fun () -> submit_exn t ~weight fn)
|
59
lib_eio/executor_pool.mli
Normal file
59
lib_eio/executor_pool.mli
Normal file
@ -0,0 +1,59 @@
|
||||
(** An executor pool distributes jobs (functions to execute) among a pool of domain workers (threads).
|
||||
|
||||
Domains are reused and can execute multiple jobs concurrently.
|
||||
Jobs are queued up if they cannot be started immediately due to all workers being busy.
|
||||
|
||||
[Eio.Executor_pool] is the recommended way of leveraging OCaml 5's multicore capabilities.
|
||||
It is built on top of the low level [Eio.Domain_manager].
|
||||
|
||||
Usually you will only want one pool for an entire application,
|
||||
so the pool is typically created when the application starts:
|
||||
|
||||
{[
|
||||
let () =
|
||||
Eio_main.run @@ fun env ->
|
||||
Switch.run @@ fun sw ->
|
||||
let pool =
|
||||
Eio.Executor_pool.create
|
||||
~sw (Eio.Stdenv.domain_mgr env)
|
||||
~domain_count:4
|
||||
in
|
||||
main ~pool
|
||||
]}
|
||||
|
||||
The pool starts its domain workers (threads) immediately upon creation.
|
||||
*)
|
||||
|
||||
type t
|
||||
(** An executor pool. *)
|
||||
|
||||
val create :
|
||||
sw:Switch.t ->
|
||||
domain_count:int ->
|
||||
_ Domain_manager.t ->
|
||||
t
|
||||
(** [create ~sw ~domain_count dm] creates a new executor pool.
|
||||
|
||||
The executor pool will not block switch [sw] from completing;
|
||||
when the switch finishes, all domain workers and running jobs are cancelled.
|
||||
|
||||
@param domain_count The number of domain workers to create.
|
||||
The total number of domains should not exceed {!Domain.recommended_domain_count} or the number of cores on your system.
|
||||
Additionally, consider reducing this number by 1 if your original domain will be performing CPU intensive work at the same time as the Executor_pool.
|
||||
*)
|
||||
|
||||
val submit : t -> weight:float -> (unit -> 'a) -> ('a, exn) result
|
||||
(** [submit t ~weight fn] runs [fn ()] using this executor pool.
|
||||
|
||||
The job is added to the back of the queue.
|
||||
|
||||
@param weight This value represents the anticipated proportion of a CPU core used by the job.
|
||||
This value must be >= 0.0 and <= 1.0; Example: given an IO-bound job that averages 2% of a CPU core, pass [~weight:0.02].
|
||||
Each domain worker starts new jobs until the total [~weight] of its running jobs reaches 1.0
|
||||
*)
|
||||
|
||||
val submit_exn : t -> weight:float -> (unit -> 'a) -> 'a
|
||||
(** Same as {!submit} but raises if the job fails. *)
|
||||
|
||||
val submit_fork : sw:Switch.t -> t -> weight:float -> (unit -> 'a) -> 'a Promise.or_exn
|
||||
(** Same as {!submit} but returns immediately, without blocking. *)
|
166
lib_eio/file.ml
166
lib_eio/file.ml
@ -1,13 +1,10 @@
|
||||
(** Tranditional Unix permissions. *)
|
||||
open Std
|
||||
|
||||
module Unix_perm = struct
|
||||
type t = int
|
||||
(** This is the same as {!Unix.file_perm}, but avoids a dependency on [Unix]. *)
|
||||
end
|
||||
|
||||
(** Portable file stats. *)
|
||||
module Stat = struct
|
||||
|
||||
(** Kind of file from st_mode. **)
|
||||
type kind = [
|
||||
| `Unknown
|
||||
| `Fifo
|
||||
@ -19,7 +16,16 @@ module Stat = struct
|
||||
| `Socket
|
||||
]
|
||||
|
||||
(** Like stat(2). *)
|
||||
let pp_kind ppf = function
|
||||
| `Unknown -> Fmt.string ppf "unknown"
|
||||
| `Fifo -> Fmt.string ppf "fifo"
|
||||
| `Character_special -> Fmt.string ppf "character special file"
|
||||
| `Directory -> Fmt.string ppf "directory"
|
||||
| `Block_device -> Fmt.string ppf "block device"
|
||||
| `Regular_file -> Fmt.string ppf "regular file"
|
||||
| `Symbolic_link -> Fmt.string ppf "symbolic link"
|
||||
| `Socket -> Fmt.string ppf "socket"
|
||||
|
||||
type t = {
|
||||
dev : Int64.t;
|
||||
ino : Int64.t;
|
||||
@ -34,64 +40,118 @@ module Stat = struct
|
||||
mtime : float;
|
||||
ctime : float;
|
||||
}
|
||||
|
||||
let pp ppf t =
|
||||
Fmt.record [
|
||||
Fmt.field "dev" (fun t -> t.dev) Fmt.int64;
|
||||
Fmt.field "ino" (fun t -> t.ino) Fmt.int64;
|
||||
Fmt.field "kind" (fun t -> t.kind) pp_kind;
|
||||
Fmt.field "perm" (fun t -> t.perm) (fun ppf i -> Fmt.pf ppf "0o%o" i);
|
||||
Fmt.field "nlink" (fun t -> t.nlink) Fmt.int64;
|
||||
Fmt.field "uid" (fun t -> t.uid) Fmt.int64;
|
||||
Fmt.field "gid" (fun t -> t.gid) Fmt.int64;
|
||||
Fmt.field "rdev" (fun t -> t.rdev) Fmt.int64;
|
||||
Fmt.field "size" (fun t -> t.size) Optint.Int63.pp;
|
||||
Fmt.field "atime" (fun t -> t.atime) Fmt.float;
|
||||
Fmt.field "mtime" (fun t -> t.mtime) Fmt.float;
|
||||
Fmt.field "ctime" (fun t -> t.ctime) Fmt.float;
|
||||
] ppf t
|
||||
end
|
||||
|
||||
(** A file opened for reading. *)
|
||||
class virtual ro = object (_ : <Generic.t; Flow.source; ..>)
|
||||
method probe _ = None
|
||||
method read_methods = []
|
||||
method virtual pread : file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
method virtual stat : Stat.t
|
||||
type ro_ty = [`File | Flow.source_ty | Resource.close_ty]
|
||||
|
||||
type 'a ro = ([> ro_ty] as 'a) r
|
||||
|
||||
type rw_ty = [ro_ty | Flow.sink_ty]
|
||||
|
||||
type 'a rw = ([> rw_ty] as 'a) r
|
||||
|
||||
module Pi = struct
|
||||
module type READ = sig
|
||||
include Flow.Pi.SOURCE
|
||||
|
||||
val pread : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
val stat : t -> Stat.t
|
||||
val seek : t -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
|
||||
val close : t -> unit
|
||||
end
|
||||
|
||||
module type WRITE = sig
|
||||
include Flow.Pi.SINK
|
||||
include READ with type t := t
|
||||
|
||||
val pwrite : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
val sync : t -> unit
|
||||
val truncate : t -> Optint.Int63.t -> unit
|
||||
end
|
||||
|
||||
type (_, _, _) Resource.pi +=
|
||||
| Read : ('t, (module READ with type t = 't), [> ro_ty]) Resource.pi
|
||||
| Write : ('t, (module WRITE with type t = 't), [> rw_ty]) Resource.pi
|
||||
|
||||
let ro (type t) (module X : READ with type t = t) =
|
||||
Resource.handler [
|
||||
H (Flow.Pi.Source, (module X));
|
||||
H (Read, (module X));
|
||||
H (Resource.Close, X.close);
|
||||
]
|
||||
|
||||
let rw (type t) (module X : WRITE with type t = t) =
|
||||
Resource.handler (
|
||||
H (Flow.Pi.Sink, (module X)) ::
|
||||
H (Write, (module X)) ::
|
||||
Resource.bindings (ro (module X))
|
||||
)
|
||||
end
|
||||
|
||||
(** A file opened for reading and writing. *)
|
||||
class virtual rw = object (_ : <Generic.t; Flow.source; Flow.sink; ..>)
|
||||
inherit ro
|
||||
method virtual pwrite : file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
end
|
||||
let stat (Resource.T (t, ops)) =
|
||||
let module X = (val (Resource.get ops Pi.Read)) in
|
||||
X.stat t
|
||||
|
||||
(** [stat t] returns the {!Stat.t} record associated with [t]. *)
|
||||
let stat (t : #ro) = t#stat
|
||||
|
||||
(** [size t] returns the size of [t]. *)
|
||||
let size t = (stat t).size
|
||||
|
||||
(** [pread t ~file_offset bufs] performs a single read of [t] at [file_offset] into [bufs].
|
||||
|
||||
It returns the number of bytes read, which may be less than the space in [bufs],
|
||||
even if more bytes are available. Use {!pread_exact} instead if you require
|
||||
the buffer to be filled.
|
||||
|
||||
To read at the current offset, use {!Flow.single_read} instead. *)
|
||||
let pread (t : #ro) ~file_offset bufs =
|
||||
let got = t#pread ~file_offset bufs in
|
||||
let pread (Resource.T (t, ops)) ~file_offset bufs =
|
||||
let module X = (val (Resource.get ops Pi.Read)) in
|
||||
let got = X.pread t ~file_offset bufs in
|
||||
assert (got > 0 && got <= Cstruct.lenv bufs);
|
||||
got
|
||||
|
||||
(** [pread_exact t ~file_offset bufs] reads from [t] into [bufs] until [bufs] is full.
|
||||
let pread_exact (Resource.T (t, ops)) ~file_offset bufs =
|
||||
let module X = (val (Resource.get ops Pi.Read)) in
|
||||
let rec aux ~file_offset bufs =
|
||||
if Cstruct.lenv bufs > 0 then (
|
||||
let got = X.pread t ~file_offset bufs in
|
||||
let file_offset = Optint.Int63.add file_offset (Optint.Int63.of_int got) in
|
||||
aux ~file_offset (Cstruct.shiftv bufs got)
|
||||
)
|
||||
in
|
||||
aux ~file_offset bufs
|
||||
|
||||
@raise End_of_file if the buffer could not be filled. *)
|
||||
let rec pread_exact (t : #ro) ~file_offset bufs =
|
||||
if Cstruct.lenv bufs > 0 then (
|
||||
let got = t#pread ~file_offset bufs in
|
||||
let file_offset = Optint.Int63.add file_offset (Optint.Int63.of_int got) in
|
||||
pread_exact t ~file_offset (Cstruct.shiftv bufs got)
|
||||
)
|
||||
|
||||
(** [pwrite_single t ~file_offset bufs] performs a single write operation, writing
|
||||
data from [bufs] to location [file_offset] in [t].
|
||||
|
||||
It returns the number of bytes written, which may be less than the length of [bufs].
|
||||
In most cases, you will want to use {!pwrite_all} instead. *)
|
||||
let pwrite_single (t : #rw) ~file_offset bufs =
|
||||
let got = t#pwrite ~file_offset bufs in
|
||||
let pwrite_single (Resource.T (t, ops)) ~file_offset bufs =
|
||||
let module X = (val (Resource.get ops Pi.Write)) in
|
||||
let got = X.pwrite t ~file_offset bufs in
|
||||
assert (got > 0 && got <= Cstruct.lenv bufs);
|
||||
got
|
||||
|
||||
(** [pwrite_all t ~file_offset bufs] writes all the data in [bufs] to location [file_offset] in [t]. *)
|
||||
let rec pwrite_all (t : #rw) ~file_offset bufs =
|
||||
if Cstruct.lenv bufs > 0 then (
|
||||
let got = t#pwrite ~file_offset bufs in
|
||||
let file_offset = Optint.Int63.add file_offset (Optint.Int63.of_int got) in
|
||||
pwrite_all t ~file_offset (Cstruct.shiftv bufs got)
|
||||
)
|
||||
let pwrite_all (Resource.T (t, ops)) ~file_offset bufs =
|
||||
let module X = (val (Resource.get ops Pi.Write)) in
|
||||
let rec aux ~file_offset bufs =
|
||||
if Cstruct.lenv bufs > 0 then (
|
||||
let got = X.pwrite t ~file_offset bufs in
|
||||
let file_offset = Optint.Int63.add file_offset (Optint.Int63.of_int got) in
|
||||
aux ~file_offset (Cstruct.shiftv bufs got)
|
||||
)
|
||||
in
|
||||
aux ~file_offset bufs
|
||||
|
||||
let seek (Resource.T (t, ops)) off cmd =
|
||||
let module X = (val (Resource.get ops Pi.Read)) in
|
||||
X.seek t off cmd
|
||||
|
||||
let sync (Resource.T (t, ops)) =
|
||||
let module X = (val (Resource.get ops Pi.Write)) in
|
||||
X.sync t
|
||||
|
||||
let truncate (Resource.T (t, ops)) len =
|
||||
let module X = (val (Resource.get ops Pi.Write)) in
|
||||
X.truncate t len
|
||||
|
141
lib_eio/file.mli
Normal file
141
lib_eio/file.mli
Normal file
@ -0,0 +1,141 @@
|
||||
(** Files implement the {!Flow} APIs, which can be used for reading and writing data.
|
||||
This module provides additonal file-specific operations, such as seeking within a file.
|
||||
|
||||
To get an open file, use the functions in the {!Path} module. *)
|
||||
|
||||
open Std
|
||||
|
||||
(** {2 Types} *)
|
||||
|
||||
(** Traditional Unix permissions. *)
|
||||
module Unix_perm : sig
|
||||
type t = int
|
||||
(** This is the same as {!Unix.file_perm}, but avoids a dependency on [Unix]. *)
|
||||
end
|
||||
|
||||
(** Portable file stats. *)
|
||||
module Stat : sig
|
||||
|
||||
type kind = [
|
||||
| `Unknown
|
||||
| `Fifo
|
||||
| `Character_special
|
||||
| `Directory
|
||||
| `Block_device
|
||||
| `Regular_file
|
||||
| `Symbolic_link
|
||||
| `Socket
|
||||
]
|
||||
(** Kind of file from st_mode. **)
|
||||
|
||||
val pp_kind : kind Fmt.t
|
||||
(** Pretty printer for {! kind}. *)
|
||||
|
||||
type t = {
|
||||
dev : Int64.t; (** Device containing the filesystem where the file resides. *)
|
||||
ino : Int64.t; (** Inode number. *)
|
||||
kind : kind; (** File type. *)
|
||||
perm : Unix_perm.t; (** Permissions (mode). *)
|
||||
nlink : Int64.t; (** Number of hard links. *)
|
||||
uid : Int64.t; (** User ID of owner. *)
|
||||
gid : Int64.t; (** Group ID of owner. *)
|
||||
rdev : Int64.t; (** Device's ID (if this is a device). *)
|
||||
size : Optint.Int63.t; (** Total size in bytes. *)
|
||||
atime : float; (** Last access time. *)
|
||||
mtime : float; (** Last modification time. *)
|
||||
ctime : float; (** Creation time. *)
|
||||
}
|
||||
(** Like stat(2). *)
|
||||
|
||||
val pp : t Fmt.t
|
||||
(** Pretty printer for {! t}. *)
|
||||
end
|
||||
|
||||
type ro_ty = [`File | Flow.source_ty | Resource.close_ty]
|
||||
|
||||
type 'a ro = ([> ro_ty] as 'a) r
|
||||
(** A file opened for reading. *)
|
||||
|
||||
type rw_ty = [ro_ty | Flow.sink_ty]
|
||||
|
||||
type 'a rw = ([> rw_ty] as 'a) r
|
||||
(** A file opened for reading and writing. *)
|
||||
|
||||
(** {2 Metadata} *)
|
||||
|
||||
val stat : _ ro -> Stat.t
|
||||
(** [stat t] returns the {!Stat.t} record associated with [t]. *)
|
||||
|
||||
val size : _ ro -> Optint.Int63.t
|
||||
(** [size t] returns the size of [t]. *)
|
||||
|
||||
(** {2 Reading and writing} *)
|
||||
|
||||
val pread : _ ro -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
(** [pread t ~file_offset bufs] performs a single read of [t] at [file_offset] into [bufs].
|
||||
|
||||
It returns the number of bytes read, which may be less than the space in [bufs],
|
||||
even if more bytes are available. Use {!pread_exact} instead if you require
|
||||
the buffer to be filled.
|
||||
|
||||
To read at the current offset, use {!Flow.single_read} instead. *)
|
||||
|
||||
val pread_exact : _ ro -> file_offset:Optint.Int63.t -> Cstruct.t list -> unit
|
||||
(** [pread_exact t ~file_offset bufs] reads from [t] into [bufs] until [bufs] is full.
|
||||
|
||||
@raise End_of_file if the buffer could not be filled. *)
|
||||
|
||||
val pwrite_single : _ rw -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
(** [pwrite_single t ~file_offset bufs] performs a single write operation, writing
|
||||
data from [bufs] to location [file_offset] in [t].
|
||||
|
||||
It returns the number of bytes written, which may be less than the length of [bufs].
|
||||
In most cases, you will want to use {!pwrite_all} instead. *)
|
||||
|
||||
val pwrite_all : _ rw -> file_offset:Optint.Int63.t -> Cstruct.t list -> unit
|
||||
(** [pwrite_all t ~file_offset bufs] writes all the data in [bufs] to location [file_offset] in [t]. *)
|
||||
|
||||
val seek : _ ro -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
|
||||
(** Set and/or get the current file position.
|
||||
|
||||
Like {!Unix.lseek}. *)
|
||||
|
||||
val sync : _ rw -> unit
|
||||
(** Flush file buffers to disk.
|
||||
|
||||
Like {!Unix.fsync}. *)
|
||||
|
||||
val truncate : _ rw -> Optint.Int63.t -> unit
|
||||
(** Set the length of a file.
|
||||
|
||||
Like {!Unix.ftruncate}. *)
|
||||
|
||||
(** {2 Provider Interface} *)
|
||||
|
||||
module Pi : sig
|
||||
module type READ = sig
|
||||
include Flow.Pi.SOURCE
|
||||
|
||||
val pread : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
val stat : t -> Stat.t
|
||||
val seek : t -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
|
||||
val close : t -> unit
|
||||
end
|
||||
|
||||
module type WRITE = sig
|
||||
include Flow.Pi.SINK
|
||||
include READ with type t := t
|
||||
|
||||
val pwrite : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
|
||||
val sync : t -> unit
|
||||
val truncate : t -> Optint.Int63.t -> unit
|
||||
end
|
||||
|
||||
type (_, _, _) Resource.pi +=
|
||||
| Read : ('t, (module READ with type t = 't), [> ro_ty]) Resource.pi
|
||||
| Write : ('t, (module WRITE with type t = 't), [> rw_ty]) Resource.pi
|
||||
|
||||
val ro : (module READ with type t = 't) -> ('t, ro_ty) Resource.handler
|
||||
|
||||
val rw : (module WRITE with type t = 't) -> ('t, rw_ty) Resource.handler
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user