diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index 812fd3171959fc768d3bb028902752ff18dbe33d..bf594f122c3be33f7210377ba4bd4ed85da744d4 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -302,7 +302,7 @@ void LLSingletonBase::MasterList::LockedInitializing::log(const char* verb, cons
     }
 }
 
-void LLSingletonBase::capture_dependency(EInitState initState)
+void LLSingletonBase::capture_dependency()
 {
     MasterList::LockedInitializing locked_list;
     list_t& initializing(locked_list.get());
@@ -334,21 +334,8 @@ void LLSingletonBase::capture_dependency(EInitState initState)
                 LLSingletonBase* foundp(*found);
                 out << classname(foundp) << " -> ";
             }
-            // We promise to capture dependencies from both the constructor
-            // and the initSingleton() method, so an LLSingleton's instance
-            // pointer is on the initializing list during both. Now that we've
-            // detected circularity, though, we must distinguish the two. If
-            // the recursive call is from the constructor, we CAN'T honor it:
-            // otherwise we'd be returning a pointer to a partially-
-            // constructed object! But from initSingleton() is okay: that
-            // method exists specifically to support circularity.
             // Decide which log helper to call.
-            if (initState == CONSTRUCTING)
-            {
-                logerrs("LLSingleton circularity in Constructor: ", out.str().c_str(),
-                    classname(this).c_str(), "");
-            }
-            else if (it_next == initializing.end())
+            if (it_next == initializing.end())
             {
                 // Points to self after construction, but during initialization.
                 // Singletons can initialize other classes that depend onto them,
@@ -457,6 +444,19 @@ void LLSingletonBase::cleanupAll()
     }
 }
 
+void LLSingletonBase::cleanup_()
+{
+    logdebugs("calling ", classname(this).c_str(), "::cleanupSingleton()");
+    try
+    {
+        cleanupSingleton();
+    }
+    catch (...)
+    {
+        LOG_UNHANDLED_EXCEPTION(classname(this) + "::cleanupSingleton()");
+    }
+}
+
 //static
 void LLSingletonBase::deleteAll()
 {
@@ -536,6 +536,12 @@ void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, c
     log(LLError::LEVEL_WARN, p1, p2, p3, p4);
 }
 
+//static
+void LLSingletonBase::loginfos(const char* p1, const char* p2, const char* p3, const char* p4)
+{
+    log(LLError::LEVEL_INFO, p1, p2, p3, p4);
+}
+
 //static
 void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4)
 {
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index ebae6010293d3b2762fa8681fe554b500f856afa..4f3b8ceb38a365c14bd10474156046ee76e71d8f 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -31,6 +31,9 @@
 #include <vector>
 #include <typeinfo>
 #include "mutex.h"
+#include "lockstatic.h"
+#include "llthread.h"               // on_main_thread()
+#include "llmainthreadtask.h"
 
 class LLSingletonBase: private boost::noncopyable
 {
@@ -105,7 +108,7 @@ class LLSingletonBase: private boost::noncopyable
 protected:
     // If a given call to B::getInstance() happens during either A::A() or
     // A::initSingleton(), record that A directly depends on B.
-    void capture_dependency(EInitState);
+    void capture_dependency();
 
     // delegate LL_ERRS() logging to llsingleton.cpp
     static void logerrs(const char* p1, const char* p2="",
@@ -113,6 +116,9 @@ class LLSingletonBase: private boost::noncopyable
     // delegate LL_WARNS() logging to llsingleton.cpp
     static void logwarns(const char* p1, const char* p2="",
                          const char* p3="", const char* p4="");
+    // delegate LL_INFOS() logging to llsingleton.cpp
+    static void loginfos(const char* p1, const char* p2="",
+                         const char* p3="", const char* p4="");
     static std::string demangle(const char* mangled);
     template <typename T>
     static std::string classname()       { return demangle(typeid(T).name()); }
@@ -123,6 +129,9 @@ class LLSingletonBase: private boost::noncopyable
     virtual void initSingleton() {}
     virtual void cleanupSingleton() {}
 
+    // internal wrapper around calls to cleanupSingleton()
+    void cleanup_();
+
     // deleteSingleton() isn't -- and shouldn't be -- a virtual method. It's a
     // class static. However, given only Foo*, deleteAll() does need to be
     // able to reach Foo::deleteSingleton(). Make LLSingleton (which declares
@@ -193,9 +202,9 @@ struct LLSingleton_manage_master
     {
         return LLSingletonBase::get_initializing_size();
     }
-    void capture_dependency(LLSingletonBase* sb, LLSingletonBase::EInitState state)
+    void capture_dependency(LLSingletonBase* sb)
     {
-        sb->capture_dependency(state);
+        sb->capture_dependency();
     }
 };
 
@@ -210,14 +219,14 @@ struct LLSingleton_manage_master<LLSingletonBase::MasterList>
     // since we never pushed, no need to clean up
     void reset_initializing(LLSingletonBase::list_t::size_type size) {}
     LLSingletonBase::list_t::size_type get_initializing_size() { return 0; }
-    void capture_dependency(LLSingletonBase*, LLSingletonBase::EInitState) {}
+    void capture_dependency(LLSingletonBase*) {}
 };
 
 // Now we can implement LLSingletonBase's template constructor.
 template <typename DERIVED_TYPE>
 LLSingletonBase::LLSingletonBase(tag<DERIVED_TYPE>):
     mCleaned(false),
-    mDeleteSingleton(NULL)
+    mDeleteSingleton(nullptr)
 {
     // This is the earliest possible point at which we can push this new
     // instance onto the init stack. LLSingleton::constructSingleton() can't
@@ -295,65 +304,40 @@ template <typename DERIVED_TYPE>
 class LLSingleton : public LLSingletonBase
 {
 private:
-    // Allow LLParamSingleton subclass -- but NOT DERIVED_TYPE itself -- to
-    // access our private members.
-    friend class LLParamSingleton<DERIVED_TYPE>;
-
-    // Scoped lock on the mutex associated with this LLSingleton<T>
-    class Locker
+    // LLSingleton<DERIVED_TYPE> must have a distinct instance of
+    // SingletonData for every distinct DERIVED_TYPE. It's tempting to
+    // consider hoisting SingletonData up into LLSingletonBase. Don't do it.
+    struct SingletonData
     {
-    public:
-        Locker(): mLock(getMutex()) {}
-
-    private:
         // Use a recursive_mutex in case of constructor circularity. With a
         // non-recursive mutex, that would result in deadlock.
         typedef std::recursive_mutex mutex_t;
+        mutex_t mMutex;             // LockStatic looks for mMutex
 
-        // LLSingleton<T> must have a distinct instance of sMutex for every
-        // distinct T. It's tempting to consider hoisting Locker up into
-        // LLSingletonBase. Don't do it.
-        //
-        // sMutex must be a function-local static rather than a static member. One
-        // of the essential features of LLSingleton and friends is that they must
-        // support getInstance() 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 mutex_t& getMutex()
-        {
-            static mutex_t sMutex;
-            return sMutex;
-        }
-
-        std::unique_lock<mutex_t> mLock;
+        EInitState      mInitState{UNINITIALIZED};
+        DERIVED_TYPE*   mInstance{nullptr};
     };
+    typedef llthread::LockStatic<SingletonData> LockStatic;
+
+    // Allow LLParamSingleton subclass -- but NOT DERIVED_TYPE itself -- to
+    // access our private members.
+    friend class LLParamSingleton<DERIVED_TYPE>;
 
     // LLSingleton only supports a nullary constructor. However, the specific
     // purpose for its subclass LLParamSingleton is to support Singletons
     // requiring constructor arguments. constructSingleton() supports both use
     // cases.
+    // Accepting LockStatic& requires that the caller has already locked our
+    // static data before calling.
     template <typename... Args>
-    static void constructSingleton(Args&&... args)
+    static void constructSingleton(LockStatic& lk, Args&&... args)
     {
         auto prev_size = LLSingleton_manage_master<DERIVED_TYPE>().get_initializing_size();
-        // getInstance() calls are from within constructor
-        sData.mInitState = CONSTRUCTING;
+        // Any getInstance() calls after this point are from within constructor
+        lk->mInitState = CONSTRUCTING;
         try
         {
-            sData.mInstance = new DERIVED_TYPE(std::forward<Args>(args)...);
-            // we have called constructor, have not yet called initSingleton()
+            lk->mInstance = new DERIVED_TYPE(std::forward<Args>(args)...);
         }
         catch (const std::exception& err)
         {
@@ -367,55 +351,56 @@ class LLSingleton : public LLSingletonBase
             // There isn't a separate EInitState value meaning "we attempted
             // to construct this LLSingleton subclass but could not," so use
             // DELETED. That seems slightly more appropriate than UNINITIALIZED.
-            sData.mInitState = DELETED;
+            lk->mInitState = DELETED;
             // propagate the exception
             throw;
         }
 
-        // getInstance() calls are from within initSingleton()
-        sData.mInitState = INITIALIZING;
+        // Any getInstance() calls after this point are from within initSingleton()
+        lk->mInitState = INITIALIZING;
         try
         {
             // initialize singleton after constructing it so that it can
             // reference other singletons which in turn depend on it, thus
             // breaking cyclic dependencies
-            sData.mInstance->initSingleton();
-            sData.mInitState = INITIALIZED;
+            lk->mInstance->initSingleton();
+            lk->mInitState = INITIALIZED;
 
             // pop this off stack of initializing singletons
-            pop_initializing();
+            pop_initializing(lk->mInstance);
         }
         catch (const std::exception& err)
         {
             // pop this off stack of initializing singletons here, too --
             // BEFORE logging, so log-machinery LLSingletons don't record a
             // dependency on DERIVED_TYPE!
-            pop_initializing();
+            pop_initializing(lk->mInstance);
             logwarns("Error in ", classname<DERIVED_TYPE>().c_str(),
                      "::initSingleton(): ", err.what());
-            // and get rid of the instance entirely
+            // Get rid of the instance entirely. This call depends on our
+            // recursive_mutex. We could have a deleteSingleton(LockStatic&)
+            // overload and pass lk, but we don't strictly need it.
             deleteSingleton();
             // propagate the exception
             throw;
         }
     }
 
-    static void pop_initializing()
+    static void pop_initializing(LLSingletonBase* sb)
     {
         // route through LLSingleton_manage_master so we Do The Right Thing
         // (namely, nothing) for MasterList
-        LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance);
+        LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sb);
     }
 
-    static void capture_dependency()
+    static void capture_dependency(LLSingletonBase* sb)
     {
         // By this point, if DERIVED_TYPE was pushed onto the initializing
         // stack, it has been popped off. So the top of that stack, if any, is
         // an LLSingleton that directly depends on DERIVED_TYPE. If
         // getInstance() was called by another LLSingleton, rather than from
         // vanilla application code, record the dependency.
-        LLSingleton_manage_master<DERIVED_TYPE>().capture_dependency(
-            sData.mInstance, sData.mInitState);
+        LLSingleton_manage_master<DERIVED_TYPE>().capture_dependency(sb);
     }
 
     // We know of no way to instruct the compiler that every subclass
@@ -442,19 +427,6 @@ class LLSingleton : public LLSingletonBase
         LLSingleton_manage_master<DERIVED_TYPE>().add(this);
     }
 
-protected:
-    virtual ~LLSingleton()
-    {
-        // In case racing threads call getInstance() at the same moment as
-        // this destructor, serialize the calls.
-        Locker lk;
-
-        // remove this instance from the master list
-        LLSingleton_manage_master<DERIVED_TYPE>().remove(this);
-        sData.mInstance = NULL;
-        sData.mInitState = DELETED;
-    }
-
 public:
     /**
      * @brief Immediately delete the singleton.
@@ -479,54 +451,149 @@ class LLSingleton : public LLSingletonBase
      */
     static void deleteSingleton()
     {
-        delete sData.mInstance;
-        // SingletonData state handled by destructor, above
+        DERIVED_TYPE* lameduck;
+        {
+            LockStatic lk;
+            // Capture the instance and clear SingletonData. This sequence
+            // guards against the chance that the destructor throws, somebody
+            // catches it and there's a subsequent call to getInstance().
+            lameduck = lk->mInstance;
+            lk->mInstance = nullptr;
+            lk->mInitState = DELETED;
+            // At this point we can safely unlock SingletonData during the
+            // remaining cleanup. If another thread calls deleteSingleton() (or
+            // getInstance(), or whatever) it won't find our instance, now
+            // referenced only as 'lameduck'.
+        }
+        // of course, only cleanup and delete if there's something there
+        if (lameduck)
+        {
+            // remove this instance from the master list BEFORE attempting
+            // cleanup so possible destructor exception won't leave the master
+            // list confused
+            LLSingleton_manage_master<DERIVED_TYPE>().remove(lameduck);
+            lameduck->cleanup_();
+            delete lameduck;
+        }
     }
 
     static DERIVED_TYPE* getInstance()
     {
-        // In case racing threads call getInstance() at the same moment,
-        // serialize the calls.
-        Locker lk;
-
-        switch (sData.mInitState)
-        {
-        case CONSTRUCTING:
-            // here if DERIVED_TYPE's constructor (directly or indirectly)
-            // calls DERIVED_TYPE::getInstance()
-            logerrs("Tried to access singleton ",
-                    classname<DERIVED_TYPE>().c_str(),
-                    " from singleton constructor!");
-            return NULL;
-
-        case UNINITIALIZED:
-            constructSingleton();
-            break;
-
-        case INITIALIZING:
-            // here if DERIVED_TYPE::initSingleton() (directly or indirectly)
-            // calls DERIVED_TYPE::getInstance(): go ahead and allow it
-        case INITIALIZED:
-            // normal subsequent calls
-            break;
-
-        case DELETED:
-            // called after deleteSingleton()
-            logwarns("Trying to access deleted singleton ",
-                     classname<DERIVED_TYPE>().c_str(),
-                     " -- creating new instance");
-            constructSingleton();
-            break;
-        }
-
-        // record the dependency, if any: check if we got here from another
-        // LLSingleton's constructor or initSingleton() method
-        capture_dependency();
-        return sData.mInstance;
+        // We know the viewer has LLSingleton dependency circularities. If you
+        // feel strongly motivated to eliminate them, cheers and good luck.
+        // (At that point we could consider a much simpler locking mechanism.)
+
+        // If A and B depend on each other, and thread T1 requests A at the
+        // same moment thread T2 requests B, you could get a sequence like this:
+        // - T1 locks A
+        // - T2 locks B
+        // - T1, having constructed A, calls A::initSingleton(), which calls
+        //   B::getInstance() and blocks on B's lock
+        // - T2, having constructed B, calls B::initSingleton(), which calls
+        //   A::getInstance() and blocks on A's lock
+        // In other words, classic deadlock.
+
+        // Avoid that by constructing and initializing every LLSingleton on
+        // the main thread. In that scenario:
+        // - T1 locks A
+        // - T2 locks B
+        // - T1 discovers A is UNINITIALIZED, so it queues a task for the main
+        //   thread, unlocks A and blocks on the std::future.
+        // - T2 discovers B is UNINITIALIZED, so it queues a task for the main
+        //   thread, unlocks B and blocks on the std::future.
+        // - The main thread executes T1's request for A. It locks A and
+        //   starts to construct it.
+        // - A::initSingleton() calls B::getInstance(). Fine: nobody's holding
+        //   B's lock.
+        // - The main thread locks B, constructs B, calls B::initSingleton(),
+        //   which calls A::getInstance(), which returns A.
+        // - B::getInstance() returns B to A::initSingleton(), unlocking B.
+        // - A::getInstance() returns A to the task wrapper, unlocking A.
+        // - The task wrapper passes A to T1 via the future. T1 resumes.
+        // - The main thread executes T2's request for B. Oh look, B already
+        //   exists. The task wrapper passes B to T2 via the future. T2
+        //   resumes.
+        // This still works even if one of T1 or T2 *is* the main thread.
+        // This still works even if thread T3 requests B at the same moment as
+        // T2. Finding B still UNINITIALIZED, T3 also queues a task for the
+        // main thread, unlocks B and blocks on a (distinct) std::future. By
+        // the time the main thread executes T3's request for B, B already
+        // exists, and is simply delivered via the future.
+
+        { // nested scope for 'lk'
+            // In case racing threads call getInstance() at the same moment,
+            // serialize the calls.
+            LockStatic lk;
+
+            switch (lk->mInitState)
+            {
+            case CONSTRUCTING:
+                // here if DERIVED_TYPE's constructor (directly or indirectly)
+                // calls DERIVED_TYPE::getInstance()
+                logerrs("Tried to access singleton ",
+                        classname<DERIVED_TYPE>().c_str(),
+                        " from singleton constructor!");
+                return nullptr;
+
+            case INITIALIZING:
+                // here if DERIVED_TYPE::initSingleton() (directly or indirectly)
+                // calls DERIVED_TYPE::getInstance(): go ahead and allow it
+            case INITIALIZED:
+                // normal subsequent calls
+                // record the dependency, if any: check if we got here from another
+                // LLSingleton's constructor or initSingleton() method
+                capture_dependency(lk->mInstance);
+                return lk->mInstance;
+
+            case DELETED:
+                // called after deleteSingleton()
+                logwarns("Trying to access deleted singleton ",
+                         classname<DERIVED_TYPE>().c_str(),
+                         " -- creating new instance");
+                // fall through
+            case UNINITIALIZED:
+                break;
+            }
+
+            // Here we need to construct a new instance.
+            if (on_main_thread())
+            {
+                // On the main thread, directly construct the instance while
+                // holding the lock.
+                constructSingleton(lk);
+                capture_dependency(lk->mInstance);
+                return lk->mInstance;
+            }
+        } // 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.
+        loginfos(classname<DERIVED_TYPE>().c_str(),
+                 "::getInstance() dispatching to main thread");
+        auto instance = LLMainThreadTask::dispatch(
+            [](){
+                // VERY IMPORTANT to call getInstance() on the main thread,
+                // rather than going straight to constructSingleton()!
+                // During the time window before mInitState is INITIALIZED,
+                // multiple requests might be queued. It's essential that, as
+                // the main thread processes them, only the FIRST such request
+                // actually constructs the instance -- every subsequent one
+                // simply returns the existing instance.
+                loginfos(classname<DERIVED_TYPE>().c_str(),
+                         "::getInstance() on main thread");
+                return getInstance();
+            });
+        // record the dependency chain tracked on THIS thread, not the main
+        // thread (consider a getInstance() overload with a tag param that
+        // suppresses dep tracking when dispatched to the main thread)
+        capture_dependency(instance);
+        loginfos(classname<DERIVED_TYPE>().c_str(),
+                 "::getInstance() returning on invoking thread");
+        return instance;
     }
 
     // Reference version of getInstance()
-    // Preferred over getInstance() as it disallows checking for NULL
+    // Preferred over getInstance() as it disallows checking for nullptr
     static DERIVED_TYPE& instance()
     {
         return *getInstance();
@@ -537,8 +604,8 @@ class LLSingleton : public LLSingletonBase
     static bool instanceExists()
     {
         // defend any access to sData from racing threads
-        Locker lk;
-        return sData.mInitState == INITIALIZED;
+        LockStatic lk;
+        return lk->mInitState == INITIALIZED;
     }
 
     // Has this singleton been deleted? This can be useful during shutdown
@@ -547,24 +614,11 @@ class LLSingleton : public LLSingletonBase
     static bool wasDeleted()
     {
         // defend any access to sData from racing threads
-        Locker lk;
-        return sData.mInitState == DELETED;
+        LockStatic lk;
+        return lk->mInitState == DELETED;
     }
-
-private:
-    struct SingletonData
-    {
-        // explicitly has a default constructor so that member variables are zero initialized in BSS
-        // and only changed by singleton logic, not constructor running during startup
-        EInitState      mInitState;
-        DERIVED_TYPE*   mInstance;
-    };
-    static SingletonData sData;
 };
 
-template<typename T>
-typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
-
 
 /**
  * LLParamSingleton<T> is like LLSingleton<T>, except in the following ways:
@@ -589,7 +643,7 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
 {
 private:
     typedef LLSingleton<DERIVED_TYPE> super;
-    using typename super::Locker;
+    using typename super::LockStatic;
 
 public:
     using super::deleteSingleton;
@@ -603,9 +657,9 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
         // In case racing threads both call initParamSingleton() at the same
         // time, serialize them. One should initialize; the other should see
         // mInitState already set.
-        Locker lk;
+        LockStatic lk;
         // For organizational purposes this function shouldn't be called twice
-        if (super::sData.mInitState != super::UNINITIALIZED)
+        if (lk->mInitState != super::UNINITIALIZED)
         {
             super::logerrs("Tried to initialize singleton ",
                            super::template classname<DERIVED_TYPE>().c_str(),
@@ -613,7 +667,7 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
         }
         else
         {
-            super::constructSingleton(std::forward<Args>(args)...);
+            super::constructSingleton(lk, std::forward<Args>(args)...);
         }
     }
 
@@ -621,9 +675,9 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
     {
         // In case racing threads call getInstance() at the same moment as
         // initParamSingleton(), serialize the calls.
-        Locker lk;
+        LockStatic lk;
 
-        switch (super::sData.mInitState)
+        switch (lk->mInitState)
         {
         case super::UNINITIALIZED:
             super::logerrs("Uninitialized param singleton ",
@@ -641,8 +695,8 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
             // within initSingleton()
         case super::INITIALIZED:
             // for any valid call, capture dependencies
-            super::capture_dependency();
-            return super::sData.mInstance;
+            super::capture_dependency(lk->mInstance);
+            return lk->mInstance;
 
         case super::DELETED:
             super::logerrs("Trying to access deleted param singleton ",
diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp
index 75ddff9d7daa427472f3408b70f170331b5c2ddb..15ffe68e67251ec7001fe29185787433cbf8bd00 100644
--- a/indra/llcommon/tests/llsingleton_test.cpp
+++ b/indra/llcommon/tests/llsingleton_test.cpp
@@ -143,8 +143,6 @@ namespace tut
                                                                         \
         (void)CLS::instance();                                          \
         ensure_equals(sLog, #CLS "i" #CLS);                             \
-        LLSingletonBase::cleanupAll();                                  \
-        ensure_equals(sLog, #CLS "i" #CLS "x" #CLS);                    \
         LLSingletonBase::deleteAll();                                   \
         ensure_equals(sLog, #CLS "i" #CLS "x" #CLS "~" #CLS);           \
     }                                                                   \
@@ -159,10 +157,8 @@ namespace tut
                                                                         \
         (void)CLS::instance();                                          \
         ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS);           \
-        LLSingletonBase::cleanupAll();                                  \
-        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER); \
         LLSingletonBase::deleteAll();                                   \
-        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \
+        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "~" #CLS "x" #OTHER "~" #OTHER); \
     }                                                                   \
                                                                         \
     template<> template<>                                               \
@@ -175,10 +171,8 @@ namespace tut
                                                                         \
         (void)CLS::instance();                                          \
         ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER);           \
-        LLSingletonBase::cleanupAll();                                  \
-        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \
         LLSingletonBase::deleteAll();                                   \
-        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \
+        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "~" #CLS "x" #OTHER "~" #OTHER); \
     }                                                                   \
                                                                         \
     template<> template<>                                               \
@@ -191,10 +185,8 @@ namespace tut
                                                                         \
         (void)CLS::instance();                                          \
         ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER);           \
-        LLSingletonBase::cleanupAll();                                  \
-        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \
         LLSingletonBase::deleteAll();                                   \
-        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \
+        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "~" #CLS "x" #OTHER "~" #OTHER); \
     }
 
     TESTS(A, B, 4, 5, 6, 7)