summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2016-09-06 21:25:57 -0400
committerNat Goodspeed <nat@lindenlab.com>2016-09-06 21:25:57 -0400
commit1cadeb40df15c1eaef3410064f9a2b8e4489082d (patch)
treec37d1d8a8d4941ae35eefed7dcbfc8e54f5c866b /indra/llcommon
parent90f424980a3aba06ac85cc23373795bc53a3fd87 (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')
-rw-r--r--indra/llcommon/llsingleton.cpp22
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: ",