diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2016-09-06 21:25:57 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2016-09-06 21:25:57 -0400 |
commit | 1cadeb40df15c1eaef3410064f9a2b8e4489082d (patch) | |
tree | c37d1d8a8d4941ae35eefed7dcbfc8e54f5c866b /indra/llcommon/llsingleton.cpp | |
parent | 90f424980a3aba06ac85cc23373795bc53a3fd87 (diff) |
MAINT-5232: Prevent runaway LLSingletonBase::MasterList growth.
Until we reimplement LLCoros on Boost.Fiber, we must hand-implement
coroutine-local data. That presently takes the form of a map keyed on
llcoro::id, whose values are the stacks of currently-initializing LLSingleton
instances.
But since the viewer launches an open-ended number of coroutines, we could end
up with an open-ended number of map entries unless we intentionally prune the
map. So every time we pop the stack to empty, remove that map entry.
This could result in thrashing, a given coroutine's 'initializing' stack being
created and deleted for almost every LLSingleton instantiated by that
coroutine -- but the number of different LLSingletons is necessarily static,
and the lifespan of each is the entire rest of the process. Even a couple
dozen LLSingletons won't thrash that badly.
Diffstat (limited to 'indra/llcommon/llsingleton.cpp')
-rw-r--r-- | indra/llcommon/llsingleton.cpp | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 3f65820f2e..24ccc8ddb4 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -94,6 +94,15 @@ public: // here. It returns a reference to the selected mapped_type instance. return mInitializing[llcoro::get_id()]; } + + void cleanup_initializing_() + { + InitializingMap::iterator found = mInitializing.find(llcoro::get_id()); + if (found != mInitializing.end()) + { + mInitializing.erase(found); + } + } }; //static @@ -129,7 +138,7 @@ LLSingletonBase::list_t& LLSingletonBase::get_initializing() //static LLSingletonBase::list_t& LLSingletonBase::get_initializing_from(MasterList* master) { - return master->get_initializing_();; + return master->get_initializing_(); } LLSingletonBase::~LLSingletonBase() {} @@ -156,6 +165,17 @@ void LLSingletonBase::pop_initializing() // and pop it list.pop_back(); + // The viewer launches an open-ended number of coroutines. While we don't + // expect most of them to initialize LLSingleton instances, our present + // get_initializing() logic could lead to an open-ended number of map + // entries. So every time we pop the stack back to empty, delete the entry + // entirely. + if (list.empty()) + { + MasterList::instance().cleanup_initializing_(); + } + + // Now validate the newly-popped LLSingleton. if (back != this) { logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ", |