template<
class CLASS>
class bio::SafelyAccessShared< CLASS >
RAII reader-side companion to SafelyAccess<T>. Acquires the shared (reader) side of the underlying ThreadSafe object's mutex on construction; releases on destruction. Multiple SafelyAccessShared holders may proceed in parallel; an in-flight SafelyAccess<T> (exclusive) blocks all SafelyAccessShared acquisitions and vice-versa.
Use case: read-mostly hot paths on Perspective / IdPerspective / TypedPerspective and other ThreadSafe derivatives where the existing exclusive lock serialises uncontested lookups. The classic shape:
{
SafelyAccessShared<Perspective<X>> shared(Pointer<Perspective<X> >(&perspective));
DIMENSION existing = shared->GetIdWithoutCreation(name);
if (existing) return existing;
}
{
// Miss: drop shared, take exclusive, recheck (another thread
// may have inserted between our shared release and exclusive
// acquire), then insert.
SafelyAccess<Perspective<X>> exclusive(Pointer<Perspective<X> >(&perspective));
DIMENSION existing = exclusive->GetIdWithoutCreation(name);
if (existing) return existing;
return exclusive->GetIdFromName(name);
}
Caveats:
- std::shared_mutex does NOT allow shared->exclusive promotion (would deadlock). Always release the shared lock before taking exclusive.
- Reentrant shared acquisition on the same thread is undefined per the C++ standard. Don't rely on it.
- On BIO_CPP_VERSION < 11 (cpp98), this falls through to exclusive since std::shared_mutex isn't available. Correct, but no concurrency win on cpp98.
- Methods called via operator-> must be const-qualified or mutable-aware — calling a non-const method under shared lock is undefined behavior. We hand back const CLASS* to make this a compile error.
- Template Parameters
-