Expand description
One writer at a time on a file that two parts of Sioul change: the window
marks a dose in the doses’ record while the sharing writes in it what your
other devices marked. One writing an older copy over the other would lose a
dose taken, and the sharing would then take it out on every device. An
advisory lock on a hidden file beside it (.<name>.lock, which the
sharing never carries), held while the file is read, changed and written.
Structs§
- File
Stamp - A file as it was when it was read, to know before replacing it that it still is (its device and number, its size and time; size and time only where a file has no number: Windows).
- Placed
- A replacement made: what is left once the lock is let go. No reader that
takes that lock holds the old file then (it reads within its own hold,
by the file’s name, which names the new file), and a reader that does not
reads through
read_whole, which never returns what follows. - Prepared
- New bytes for a file, written beside it under a hidden name (which the sharing and the watcher pass over), yours alone, and on the disk, waiting to take its place; taken out if they never do. The slow part of a replacement, done before any lock is taken.
- Read
- A TOML file as it was read, kept beside the state read from it (a field
that serde skips): saved, only what changed since it was read is written
over what the file holds then (
save_merged), so that a change your other devices brought in meanwhile (the sharing writes under the same lock) stays. Equal to any other, so that it changes no comparison of the state.
Constants§
- HELD 🔒
- The locks this thread holds: one taken again inside (a writer calling another of the same file) is already held, never waited for.
- READ_
AGAIN 🔒 - How many times a file replaced while it was read is read again before that is said (“Interrupted”).
Statics§
- EMPTY 🔒
Functions§
- copy_
whole fromcopied totoas one of its versions held it whole, withread_whole’s check: through its descriptor, then again, a few times, when the file copied lost its name meanwhile orfromnames another one.tois made yours alone (on Unix). Returns the bytes copied.- has_
lock - Whether a writer of
pathtakes its lock here (its hidden lock file is there): for files the sharing writes without it otherwise (a note, which most writers do not lock), so that a file one of Sioul’s own writers changes under its lock (the letters’ list) is written under it too. - lock_
path 🔒 - merge 🔒
- What changed from
basetonew, set overcurrent. A list or a table on one side only stands against an empty one on the other: emptied, it takes out what it held, never what another writer added since; filled from nothing, it adds to what another writer put there. - overwrite 🔒
- A file without a name left, its bytes overwritten with zeros, on the disk.
- read_
through 🔒 read_whole_with, each file opened byopen(a test replaces the file between its opening and its reading).- read_
whole - A file’s bytes as one of its versions held them whole, never the zeros
Placed::finishwrites over the file it replaced: read through its descriptor, then checked that the file read still has a name and thatpathnames it (still_named); else read again, a few times. A file replaced while it was read has no name, and its bytes may be zeros by then; one replaced after it was read is an older version: both are read again. Where a file has no number to tell (Windows), read once: there nothing is overwritten. - read_
whole_ with read_whole, with what the descriptor said of the file read, after the read: its size and time are those of the bytes returned.- rename_
over 🔒 fromrenamed overto. On Windows a file another thread or program has open for a moment (a reader of the same state) refuses to be replaced: tried again a few times, for a tenth of a second at most (CI’s Windows job of 22 October 2026: a calendar’s kinds lost so).- replace
- Bytes written beside
pathunder a hidden name of their own, then renamed over it: a reader never finds the file empty or half written (the sharing reads without the lock), and a full disk leaves the file as it was rather than empty (review of 5 October 2026, F10). - replace_
wiping bytesin place ofpath’s content, what it held overwritten where the filesystem lets it be (docs/client.md, “What a disk keeps”):Prepared,Prepared::placeandPlaced::finishat once, for a file no other part of Sioul reads meanwhile but throughread_whole. A file that readers take a lock for is replaced in those three steps, the place alone under that lock (draftcopies: the sharing’s exchange lock).- save_
merged statewritten intopath, under its lock, the file read again first: what changed fromread(the file as it was read) tostateis set over what the file holds now, field by field (a list as a set: what was added added, what was taken out taken out; a list or table missing on one side is an empty one, as a state skips an empty field); the rest stays as the file holds it. A file missing when it was read is read as empty. Nothing read before that could be merged (a file that did not read):statewhole. Written beside, then moved.- save_
merged_ by - The same,
settlethen given the merged table and the file as it was just before (none when missing): for what a field-by-field merge cannot say (a mark that must never go backwards). - still_
named 🔒 - Whether the file read through a descriptor (
held: what it says after the read) still has a name, andpathis it. - with_
lock f, with the lock onpathheld: other threads and programs wait for it. Where no lock can be taken (a folder not writable),fruns all the same: writing it fails there anyway. Taken again by the thread holding it, it is held already.