aboutsummaryrefslogtreecommitdiffstats
path: root/core/module-list.h
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-30 02:25:43 +0100
committereunhhu <[email protected]>2026-09-30 02:25:43 +0100
commitd1e8f38f100571d55aaa98527ae2873e6d247f80 (patch)
tree216998a90e39d3dd90141e0e1b78267f9ed4c02f /core/module-list.h
parentc72284953bb6938ff480ae9be11d5d0c3c4154f6 (diff)
downloadpure-d1e8f38f100571d55aaa98527ae2873e6d247f80.tar.gz
pure-d1e8f38f100571d55aaa98527ae2873e6d247f80.zip
Let a held snapshot keep the states of its time, not all that came after
An app's snapshots formed a chain, each holding the next, and what the app's lists let go while a snapshot was the newest went with it. So one snapshot held for long held every later one and every node and text let go since: a surface holding the snapshot of 20,000 items while their notes were set again grew the node from 6.5 MB to 696 MB in 30 s, 3.4 KB an update, without end. A snapshot reads only what was made before it. Snapshots are now numbered (their epoch, given to the lists' copies and so to each node and text made after), and the ones held are linked under a register they share. What the app lets go while a snapshot is its newest goes with it, as before; when that one goes, what the newest older one still held may read (made before its epoch) goes to it, and the rest back to the system at once. The links move under a spin the register keeps; what is freed is freed outside it. The same held snapshot now costs its states once: 6.6 MB to 10.6 MB, flat after the notes diverge. test-module's snapshot_held holds a snapshot through 40,000 events and snapshots: none of the second 20,000's allocations stays (0 B; with the chain's keeping, it fails). The kept-snapshots tests read eight held in random order, and the module tests pass under AddressSanitizer too.
Diffstat (limited to 'core/module-list.h')
-rw-r--r--core/module-list.h14
1 files changed, 12 insertions, 2 deletions
diff --git a/core/module-list.h b/core/module-list.h
index a4e760a..abe19cb 100644
--- a/core/module-list.h
+++ b/core/module-list.h
@@ -59,8 +59,18 @@ size_t pure_list_count(const PureList *);
* freed, since the copy may still read them. The copy is freed with
* pure_list_free, on any thread, when its last reference goes
* (pure_list_hold takes one more). Only between events (no change waits to
- * be committed or undone). */
-PureList *pure_list_share(PureList *, PureRetired *retired);
+ * be committed or undone). epoch numbers the copy (as a snapshot of an app
+ * numbers its lists' copies, one number for all of them): a node or text
+ * the list makes after it has the epoch, and a copy of epoch e reads only
+ * what was made before e. */
+PureList *pure_list_share(PureList *, PureRetired *retired, uint64_t epoch);
+/* A copy made before and still current (the list unchanged since) is read
+ * as of epoch too: what the list lets go from now on is retired. */
+void pure_list_mark(PureList *, uint64_t epoch);
+/* Of what was retired, what a copy of epoch may still read (made before
+ * it) goes to kept (none when kept is NULL), and the rest to gone, for
+ * pure_retired_free (later, and where it pleases): from is left empty. */
+void pure_retired_pass(PureRetired *from, uint64_t epoch, PureRetired *kept, PureRetired *gone);
void pure_list_hold(PureList *copy);
/* Whether copy shares list's items as they are now. */
bool pure_list_current(const PureList *copy, const PureList *list);