summaryrefslogtreecommitdiff
path: root/indra/llcommon/lockstatic.h
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2019-12-04 15:44:32 -0500
committerNat Goodspeed <nat@lindenlab.com>2020-03-25 15:28:17 -0400
commitba8fe9b483aaa59e724cdbfa183c69ee5998dc1f (patch)
tree03b2b86e6cd02944704ca11ba5784cadb7bbb243 /indra/llcommon/lockstatic.h
parent2dfaba6e32ef027036378e499d9cb28aa2e6220f (diff)
DRTVWR-494: Move explanatory comments from LLSingleton to LockStatic.
Diffstat (limited to 'indra/llcommon/lockstatic.h')
-rw-r--r--indra/llcommon/lockstatic.h17
1 files changed, 17 insertions, 0 deletions
diff --git a/indra/llcommon/lockstatic.h b/indra/llcommon/lockstatic.h
index 5f08742cae..96c53c6473 100644
--- a/indra/llcommon/lockstatic.h
+++ b/indra/llcommon/lockstatic.h
@@ -46,6 +46,23 @@ protected:
private:
Static* getStatic()
{
+ // Static::mMutex must be function-local static rather than class-
+ // static. Some of our consumers must function properly (therefore
+ // lock properly) even when the containing module's static variables
+ // have not yet been runtime-initialized. A mutex requires
+ // construction. A static class member might not yet have been
+ // constructed.
+ //
+ // We could store a dumb mutex_t*, notice when it's NULL and allocate a
+ // heap mutex -- but that's vulnerable to race conditions. And we can't
+ // defend the dumb pointer with another mutex.
+ //
+ // We could store a std::atomic<mutex_t*> -- but a default-constructed
+ // std::atomic<T> does not contain a valid T, even a default-constructed
+ // T! Which means std::atomic, too, requires runtime initialization.
+ //
+ // But a function-local static is guaranteed to be initialized exactly
+ // once: the first time control reaches that declaration.
static Static sData;
return &sData;
}