aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--org/out_src_abstraction_ocda_peg_ssp.org46
-rw-r--r--src/sisudoc/ocda/abstraction/ssp.d46
2 files changed, 66 insertions, 26 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;
diff --git a/src/sisudoc/ocda/abstraction/ssp.d b/src/sisudoc/ocda/abstraction/ssp.d
index 2501add..05931b1 100644
--- a/src/sisudoc/ocda/abstraction/ssp.d
+++ b/src/sisudoc/ocda/abstraction/ssp.d
@@ -406,6 +406,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;
@@ -579,21 +585,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;