@nevion No. H5CPP is thread safe when used with a thread safe HDF5 Library.
No, H5CPP doesn’t introduce any new global state. but does rely on the CAPI internal states for object reference counting, etc…
From the code base HDF5 CAPI relies in skip lists to associate hid_t handles with internal objects, and also features datastructures for metadata, indexing chunks, etc… all these may be modelled with a single global variable per property list, object reference, […] that H5CPP methods access when invoked. Since H5CPP hid_t types are binary compatible with the CAPI any changes to the CAPI delegates to H5CPP – no rewrite is necessary.
Replacing the CAPI calls with thread safe and reentrant code H5CPP guarantees both. Think of H5CPP as a set of context sensitive templates that do the right thing respect to the object being serialized + persisted (or the inverse). They are basically generate expert level sequence of CAPI calls respect to context.
TLDR:
Reentrant vs Threadsafe
The action when a code block is interrupted at any given point, then invoked again is called reentry. This reentry doesn’t necessary have to be parallel in time, although the possibility is not excluded. If this code block has a global mutable state which is modified then the consecutive reentry will leave the state undefined. The code block is said to be reentrant if the state is well defined regardless of interruption and consecutive reentries. Think of software/hardware interrupts, recursive calls being equivalent of reentry and the state as a global variable see: singleton pattern in GoF, static variable, memory reference/pointer . However automatic storage of standard layout types within a method/function are reentrant since each function call has it’s own copy on the current stack.
Thread safety is concerned whether a state of a code block remains well defined when executed from different threads of the OS. This is disjoint from reentry as allows datastructures stored in thread local place, making it safe when ran concurrently but unsafe for reentry as that happens from the same thread.
Lifted from wikipedia here is the cross product of reentry and thread safety explained with examples:
not thread-safe, not reentrant
int tmp;
// shared/global datastructure: think of HDF5 skiplists,
// B-link-tree (balanced sibling linked N-ary Tree) [...]
void swap(int* x, int* y) { // mutatating operator such as awrite, write, create, acreate,
// increment/decrement reference counting, basically any HDF5 CAPI call that changes the HDF5 internal state
tmp = *x;
*x = *y;
/* Hardware interrupt might invoke isr() here. */
*y = tmp;
}
// inerrupt service routine ISR used throughout the examples
void isr() {
int x = 1, y = 2;
swap(&x, &y);
}
thread-safe, not reentrant
thread_local int tmp; // dedicate storage per thread
void swap(int* x, int* y) {
tmp = *x;
*x = *y;
*y = tmp; //Hardware interrupt might invoke isr() here.
}
not thread-safe, reentrant
thread_local int tmp;
void swap(int* x, int* y) {
int s = tmp; // Save global variable, must be atomic op
tmp = *x;
*x = *y;
*y = tmp; // Hardware interrupt might invoke isr() here.
tmp = s; // Restore global variable, must be atomic op
}
thread-safe, reentrant
void swap(int* x, int* y){
int tmp; // allocated on stack, different for each function fall
tmp = *x;
*x = *y;
*y = tmp; // Hardware interrupt might invoke isr() here.
}
When H5CPP is used with a rentrant and thread safe HDF5 library both property will delegate, making H5CPP threadsafe and reentrant.
hope it helps:
steve