Skip to content
Snippets Groups Projects
Commit 7e9c5dd0 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

DRTVWR-494: LLParamSingleton::initParamSingleton() on main thread.

When calling LLParamSingleton::initParamSingleton() on a secondary thread, use
LLMainThreadTask::dispatch() to construct the instance on the main thread --
as with LLSingleton::getInstance().
parent 68505edf
No related branches found
No related tags found
No related merge requests found
......@@ -59,6 +59,7 @@ class LLSingletonBase: private boost::noncopyable
typedef enum e_init_state
{
UNINITIALIZED = 0, // must be default-initialized state
QUEUED, // construction queued, not yet executing
CONSTRUCTING, // within DERIVED_TYPE constructor
INITIALIZING, // within DERIVED_TYPE::initSingleton()
INITIALIZED, // normal case
......@@ -552,6 +553,11 @@ class LLSingleton : public LLSingletonBase
" -- creating new instance");
// fall through
case UNINITIALIZED:
case QUEUED:
// QUEUED means some secondary thread has already requested an
// instance, but for present purposes that's semantically
// identical to UNINITIALIZED: either way, we must ourselves
// request an instance.
break;
}
......@@ -564,10 +570,13 @@ class LLSingleton : public LLSingletonBase
capture_dependency(lk->mInstance);
return lk->mInstance;
}
// Here we need to construct a new instance, but we're on a secondary
// thread.
lk->mInitState = QUEUED;
} // unlock 'lk'
// Here we need to construct a new instance, but we're on a secondary
// thread. Per the comment block above, dispatch to the main thread.
// Per the comment block above, dispatch to the main thread.
loginfos(classname<DERIVED_TYPE>().c_str(),
"::getInstance() dispatching to main thread");
auto instance = LLMainThreadTask::dispatch(
......@@ -588,7 +597,7 @@ class LLSingleton : public LLSingletonBase
// suppresses dep tracking when dispatched to the main thread)
capture_dependency(instance);
loginfos(classname<DERIVED_TYPE>().c_str(),
"::getInstance() returning on invoking thread");
"::getInstance() returning on requesting thread");
return instance;
}
......@@ -672,11 +681,40 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
" twice!");
return nullptr;
}
else
else if (on_main_thread())
{
// on the main thread, simply construct instance while holding lock
super::constructSingleton(lk, std::forward<Args>(args)...);
return lk->mInstance;
}
else
{
// on secondary thread, dispatch to main thread --
// set state so we catch any other calls before the main thread
// picks up the task
lk->mInitState = super::QUEUED;
// very important to unlock here so main thread can actually process
lk.unlock();
super::loginfos(super::template classname<DERIVED_TYPE>().c_str(),
"::initParamSingleton() dispatching to main thread");
// Normally it would be the height of folly to reference-bind
// 'args' into a lambda to be executed on some other thread! By
// the time that thread executed the lambda, the references would
// all be dangling, and Bad Things would result. But
// LLMainThreadTask::dispatch() promises to block until the passed
// task has completed. So in this case we know the references will
// remain valid until the lambda has run, so we dare to bind
// references.
auto instance = LLMainThreadTask::dispatch(
[&](){
super::loginfos(super::template classname<DERIVED_TYPE>().c_str(),
"::initParamSingleton() on main thread");
return initParamSingleton(std::forward<Args>(args)...);
});
super::loginfos(super::template classname<DERIVED_TYPE>().c_str(),
"::initParamSingleton() returning on requesting thread");
return instance;
}
}
static DERIVED_TYPE* getInstance()
......@@ -688,6 +726,7 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
switch (lk->mInitState)
{
case super::UNINITIALIZED:
case super::QUEUED:
super::logerrs("Uninitialized param singleton ",
super::template classname<DERIVED_TYPE>().c_str());
break;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment