Thread-safe "singleton" that destroys object when not used anymore I'm working on some legacy code which uses the singleton pattern. The problem I have with the traditional singleton is that the instance lives until the program terminates. This is messing up the order in which things need to get destroyed and makes it difficult to write independent unit tests. Unfortunately, I can't get rid of the singleton by constructing a single instance and passing it around since this would break APIs.

I wrote the following wrapper around a class T that hands out shared pointers to a single instance of T. When the last shared pointer goes out of scope the object gets destroyed.

#include &lt;memory&gt;
#include &lt;type_traits&gt;
#include &lt;mutex&gt;

template &lt;class T&gt;
class refCountedSingleton
{
  static_assert(!std::is_default_constructible&lt;T&gt;::value, "T must have a private/protected constructor to ensure it can only be constructed by refCountedSingleton");
  static_assert(!std::is_copy_constructible&lt;T&gt;::value, "T must have a private/protected copy constructor to ensure instances handed out by refCountedSingleton cannot be copied");
  static_assert(!std::is_copy_assignable&lt;T&gt;::value, "T must have a private/protected copy assignment operator to ensure instances handed out by refCountedSingleton cannot be copied");
  static std::weak_ptr&lt;T&gt; p;
  static std::mutex mu;
public:
  static std::shared_ptr&lt;T&gt; getShared();
};

template &lt;class T&gt;
std::weak_ptr&lt;T&gt; refCountedSingleton&lt;T&gt;::p;
template &lt;class T&gt;
std::mutex refCountedSingleton&lt;T&gt;::mu;

template &lt;class T&gt;
std::shared_ptr&lt;T&gt; refCountedSingleton&lt;T&gt;::getShared()
{
    std::lock_guard&lt;std::mutex&gt; lock(mu);
    std::shared_ptr&lt;T&gt; temp = p.lock();
    if (!temp) {
      temp.reset(new T());
      p = temp;
    }
  return temp;
}


The following class could be used as T:

class obj {
  friend class refCountedSingleton&lt;obj&gt;;
private:
  obj() {}
  obj(obj const&amp;);
  obj&amp; operator=(obj const&amp;);
};


Example use case:

{
  std::shared_ptr&lt;obj&gt; pm1 = refCountedSingleton&lt;obj&gt;::getShared();
  {
    // calling getShared() multiple times yields pointers to the same object
    std::shared_ptr&lt;obj&gt; pm2 = refCountedSingleton&lt;obj&gt;::getShared();
  }
} // instance of obj gets destroyed here
{
   // a new instance of obj gets greated
   std::shared_ptr&lt;obj&gt; pm3 = refCountedSingleton&lt;obj&gt;::getShared();
}


My singleton needs to be thread safe which is why I'm locking the mutex in getShared(). With the traditional singleton pattern performance can be improved by avoiding the expensive locking most of the time by leveraging double-checked locking. I'm wondering if something similar could be done here as well.
The problem with the above code is that it doing two things with one piece of code.

1: Singleton Creation.
2: Singelton LifeSpan.

I would separate these out into two separate classes.

The creation is done via an abstract factory (MySingletonFactory) but lifespan is controlled via explicit factory classes that are defined for the situation (so your code does not define the life span of the singleton).

The other issue of the above code is that I have seen this not working because of the way global variables are created in libraries. When these libraries are linked together it is not required to remove duplicate variables (as all variables were already resolved as much as possible during compilation). The linking phase will only try and resolve unresolved dependencies not all linkers will try and remove duplicated global variables (though I suppose this will depend on how sophisticated the linker is).

Here is how I would resolve the problem (by removing globals (using static storage function scope variables)).

Interfaces

#include &lt;memory&gt;
#include &lt;iostream&gt;
#include &lt;cstdlib&gt;

class MySingleInterface
{
    public:
        virtual ~MySingleInterface() {}

        virtual int doWork() = 0;
};
class MySingleFactoryInterface
{
    public:
        virtual ~MySingleFactoryInterface() {}
        virtual std::shared_ptr&lt;MySingleInterface&gt;  createTheObject() = 0;
};


Abstract Factory (I think?)

class MySingletonFactory
{
    private:
        friend class MySingleInterface;
        static MySingleFactoryInterface&amp; getCurrentFactory(MySingleFactoryInterface* replace)
        {
            // Do not strictly need a default factory.
            // But it is nice to have one for standard (default)
            // operations. Then you only specify one in non standard
            // situations like testing. 
            static MyDefaultSingeltonFactory           defaultFactory;

            // The current factory we are using.
            static MySingleFactoryInterface*           currentFactory = &amp;defaultFactory;
            if (replace)
            {
                std::swap(replace, currentFactory);
            }
            else
            {
                replace = currentFactory;
            }
            return *replace;
        }
    public:
        static std::shared_ptr&lt;MySingleInterface&gt; getInstance()
        {
            return getCurrentFactory(nullptr).createTheObject();
        }
        static MySingleFactoryInterface&amp; setFactory(MySingleFactoryInterface&amp; alternativeFactory)
        {
             return getCurrentFactory(&amp;alternativeFactory);
        }
};


Example Default Singleton

class MyDefaultSingeltonFactory;
class MyDefaultSingleton: public MySingleInterface
{
    private:
        friend class MyDefaultSingeltonFactory;
        MyDefaultSingleton(){}
    public:
        virtual int doWork() override {static int value; return value++;}   // Normal operation.
};
class MyDefaultSingeltonFactory: public MySingleFactoryInterface
{
    // A Normal Singleton factory.
    // The singelton lives from creation until the end of the program.
    // Note: This is the behavior of this factory does not need to
    //       to be universal behavior.
    public:
        std::shared_ptr&lt;MySingleInterface&gt;  createTheObject() override
        {
            std::shared_ptr&lt;MySingleInterface&gt;  instance = std::shared_ptr&lt;MySingleInterface&gt;(new MyDefaultSingleton());
            return instance;
        }
};


Example Test Singelton

class MyTestSingleton: public MySingleInterface
{
    int value;
    public:
    MyTestSingleton()
        : value(rand())
    {}
    public:
        virtual int doWork() override {return value;}        // Operation for testing.
};

class MyTestSingletonFactory: public MySingleFactoryInterface
{
    // This factory creates a new instance each time.
    // Can be useful for some types of test.
    public:
        std::shared_ptr&lt;MySingleInterface&gt;  createTheObject() override
        {
            return std::make_shared&lt;MyTestSingleton&gt;();
        }
};

class MyTestPersistantSingletonFactory: public MySingleFactoryInterface
{
    // As long as the code holds a shared pointer it will be re-used.
    // Useful if you want to create the singleton during "setUp()" and
    // destroy it during "tearDown()" you get a brand new singleton for
    // each individual test.
    public:
        std::shared_ptr&lt;MySingleInterface&gt;  createTheObject() override
        {
            // I leave the exercise of locking to you.
            static std::weak_ptr&lt;MySingleInterface&gt;     persist;
            auto result = persist.lock();
            if (!result)
            {
                result = std::make_shared&lt;MyTestSingleton&gt;();
                persist = result;
            }
            return result;
        }
};


Test Harness

int main()
{
    srand(0);

    // Incrementing results.
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";

    // Each result indapendant.
    MyTestSingletonFactory  testFactory;
    MySingletonFactory::setFactory(testFactory);
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    std::cout &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";


    MyTestPersistantSingletonFactory    persistantFactory;
    MySingletonFactory::setFactory(persistantFactory);
    {
        // As long as we hold a reference then
        // we should get the same result.
        std::shared_ptr&lt;MySingleInterface&gt; local = MySingletonFactory::getInstance();
        std::cout &lt;&lt; "L: " &lt;&lt; local-&gt;doWork() &lt;&lt; "\n";
        std::cout &lt;&lt; "L: " &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
        std::cout &lt;&lt; "L: " &lt;&lt; local-&gt;doWork() &lt;&lt; "\n";
        std::cout &lt;&lt; "L: " &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
    }
    // No local reference so we will create a new value.
    std::cout &lt;&lt; "N: " &lt;&lt; MySingletonFactory::getInstance()-&gt;doWork() &lt;&lt; "\n";
}


Output

&gt; ./a.out
0
1
2
3
4
5
6
7
8
520932930
28925691
822784415
890459872
L: 145532761
L: 145532761
L: 145532761
L: 145532761
N: 2132723841