You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
h5::threads{N} installs the worker pool via H5Pinsert2 on the user FAPL, but every read/write dispatch re-derives the FAPL with H5Fget_access_plist, which reconstructs a FAPL from the file's library-known access properties and drops user-inserted custom properties. resolve_worker_pool returns null and pool_pipeline_t never engages — high_throughput + threads{N} silently falls back to synchronous basic_pipeline_t.
Confirmed behavior (probes, HDF5 1.12.3 AND 1.14.6 — version-independent)
✘ FAPL custom property: PRESENT on the original FAPL, ABSENT after H5Fget_access_plist (H5Pequal=0). By design per the HDF5 VFL docs — the driver fapl_get callback reconstructs only driver-specific properties, and "user-defined properties cannot currently be encoded."
✔ DAPL/DCPL custom property SURVIVES H5Dget_access_plist on the same open handle (this is why high_throughput works today) — but NOT across close/reopen.
✔ H5Fget_fileno is stable per physical file and shared across multiple opens (two opens → one fileno) → correct per-file key.
Chosen fix — fileno-keyed singleton registry (candidate #2 from the original analysis)
Carry the per-file worker pool in a process-global singleton keyed by H5Fget_fileno, not in the FAPL:
io_registry_t : h5::impl::singleton_t<io_registry_t> (MIT, vendored), lazy init via std::call_once.
attach at H5Fcreate/H5Fopen while the original FAPL is live (reads threads{N} before any stripping); refcount by open.
resolve at dispatch via H5Fget_fileno(H5Iget_file_id(ds)); optional DAPL pointer-cache for the hot path.
detach + drain at ~fd_t (before H5Fclose); refs→0 tears down.
Per-process scope (correct: HDF5 thread-safety + SWMR/MPI are per-process); one pool per physical file (multi-open shares).
Rejected alternatives: DAPL stash (per-dataset, cannot be the per-file singleton); re-architect via #266 (couples to the larger async rework).
Single per-file IO collector model, descriptor thinning (async exec, pt_t), and the h5::sync + h5::async + threaded filter chain build on top of this mechanism.
Acceptance
✔ pool_pipeline_t executes with threads{N} + high_throughput (non-zero H5Zpipeline_pool.hpp coverage; probe asserts resolve_* returns non-null at the dispatch site)
✔ a regression test asserts the pool engages (not just that data round-trips)
✔ FAPL/DAPL/fileno behavior probes committed under test/
Supersedes the original report; the FAPL-stripping root cause and the fileno→pool registry candidate are preserved above. Behavior confirmed on HDF5 1.12.3 and 1.14.6.
Summary
h5::threads{N}installs the worker pool viaH5Pinsert2on the user FAPL, but every read/write dispatch re-derives the FAPL withH5Fget_access_plist, which reconstructs a FAPL from the file's library-known access properties and drops user-inserted custom properties.resolve_worker_poolreturns null andpool_pipeline_tnever engages —high_throughput+threads{N}silently falls back to synchronousbasic_pipeline_t.Confirmed behavior (probes, HDF5 1.12.3 AND 1.14.6 — version-independent)
H5Fget_access_plist(H5Pequal=0). By design per the HDF5 VFL docs — the driverfapl_getcallback reconstructs only driver-specific properties, and "user-defined properties cannot currently be encoded."H5Dget_access_pliston the same open handle (this is whyhigh_throughputworks today) — but NOT across close/reopen.H5Fget_filenois stable per physical file and shared across multiple opens (two opens → one fileno) → correct per-file key.Chosen fix — fileno-keyed singleton registry (candidate #2 from the original analysis)
Carry the per-file worker pool in a process-global singleton keyed by
H5Fget_fileno, not in the FAPL:io_registry_t : h5::impl::singleton_t<io_registry_t>(MIT, vendored), lazy init viastd::call_once.H5Fcreate/H5Fopenwhile the original FAPL is live (readsthreads{N}before any stripping); refcount by open.H5Fget_fileno(H5Iget_file_id(ds)); optional DAPL pointer-cache for the hot path.~fd_t(beforeH5Fclose);refs→0tears down.Rejected alternatives: DAPL stash (per-dataset, cannot be the per-file singleton); re-architect via #266 (couples to the larger async rework).
Scope (this issue)
singleton_t+call_once+~fd_tdrainpool_pipeline_tbecomes reachable through the public APIcall_oncefirst-open race, multi-open→one pool, leaked-fd_tteardown orderingH5Zpipeline_pool.hppOut of scope (follow-on issue)
Single per-file IO collector model, descriptor thinning (async
exec,pt_t), and theh5::sync+h5::async+ threaded filter chain build on top of this mechanism.Acceptance
pool_pipeline_texecutes withthreads{N}+high_throughput(non-zeroH5Zpipeline_pool.hppcoverage; probe assertsresolve_*returns non-null at the dispatch site)H5Zpipeline_pool.hppis removedtest/Supersedes the original report; the FAPL-stripping root cause and the
fileno→pool registrycandidate are preserved above. Behavior confirmed on HDF5 1.12.3 and 1.14.6.