diff options
| author | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-09 16:12:37 -0400 |
|---|---|---|
| committer | Ralph Amissah <ralph.amissah@gmail.com> | 2026-09-09 20:26:33 -0400 |
| commit | a87c7dbef6968f496168f6d2cfe249bb150e0e27 (patch) | |
| tree | 360fce31917c1ed89e6c4ffd129b9e48d9cf9f0a /org | |
| parent | sqlite: schema version, & fail run on writes fail (diff) | |
ssp: abstraction directory cleared once
abstraction directory cleared once, by whichever language is first
The .ssp writer clears stale files out of
pod/<doc>/media/abstraction/, and that one directory is shared by
every language of a document. The clearing is now done once per
directory per run, by whichever language reaches it first, with
the lock held across it. A language that finds the directory
already prepared has passed through that same lock before writing,
so the clearing it skipped had completed before its own write
began: no .ssp produced on a given run can be removed during it.
(removes possibility of a race condition on parallelisation)
(assisted by Claude-Code)
Diffstat (limited to 'org')
| -rw-r--r-- | org/out_src_abstraction_ocda_peg_ssp.org | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/org/out_src_abstraction_ocda_peg_ssp.org b/org/out_src_abstraction_ocda_peg_ssp.org index 0edad7d..c1b1930 100644 --- a/org/out_src_abstraction_ocda_peg_ssp.org +++ b/org/out_src_abstraction_ocda_peg_ssp.org @@ -388,6 +388,12 @@ template sspObjectRecord() { } } +/+ ↓ abstraction directories whose stale .ssp have been cleared this run, one + entry per document. __gshared, and read and written only inside the + synchronized block in the writer below: a document's languages share one + abstraction directory and may be written in parallel ++/ +private __gshared bool[string] _abstraction_dir_prepared; template spineAbstractionTxt() { import std.conv : to; import std.digest : toHexString; @@ -561,21 +567,35 @@ template spineAbstractionTxt() { auto pths_pod = spinePathsPods!()(doc_matters); string base_pth = pths_pod.abstraction_root(doc_matters.src.filename).filesystem_open_zpod.to!string; - try { - if (!exists(base_pth)) { - base_pth.mkdirRecurse; - } else if (doc_matters.src.language - == doc_matters.pod.manifest_list_of_languages[0] - ) { - /+ ↓ this directory is the one part of the pod written before the pod - is built, so the pod builder leaves it alone. It therefore clears - itself here, on the first language of a run, or a .ssp for a - language the document no longer has would linger and be bundled +/ - foreach (string _f; dirEntries(base_pth, "*.ssp", SpanMode.shallow)) { - _f.remove; + /+ ↓ this directory is the one part of the pod written before the pod is + built, so the pod builder leaves it alone. It therefore clears itself + here, or a .ssp for a language the document no longer has would linger + and be bundled. + . + Every language of a document writes into this one directory, and the + languages may be running at once, so the clearing is done once per + directory per run, by whichever language reaches it first, with the + lock held across it. A language that finds the directory already + prepared passed through this lock before writing, so the clearing it + skipped had already finished, and no .ssp written by this run can be + removed by it. Keying the clearing on the manifest's first language + instead makes it wait for a thread that may be scheduled last, and + take the .ssp already written by the other languages with it. + +/ + synchronized { + if (base_pth !in _abstraction_dir_prepared) { + _abstraction_dir_prepared[base_pth] = true; + try { + if (!exists(base_pth)) { + base_pth.mkdirRecurse; + } else { + foreach (string _f; dirEntries(base_pth, "*.ssp", SpanMode.shallow)) { + _f.remove; + } + } + } catch (Exception ex) { } } - } catch (Exception ex) { } string out_file = ((base_pth.chainPath( doc_matters.src.doc_uid_out ~ ".ssp")).asNormalizedPath).array; |
