Template Singleton Base Class in Shared Object

C++ template singleton base class for deep level inheritance

You will have to make Base a template and pass that to Singleton, then inherit from Base<A> if you wish to achieve this. Or, if you want Base to be a Singleton and A/B to be a Singleton, then they will have to inherit from Singleton<A>, Singleton<B> in addition to Base.

But dear lord, man, Singletons are a curse on you and your children for a hundred generations. Why would you do that to yourself?

C++ Singleton template class inheritance

Problem is that you do not use the virtual function as you intend to use. i,e there no polymorphism in action now. Why? because you call init() on the direct derived object. The use of init() function being virtual is when you invoke init() either on the base-class reference or on base class pointer as given below. Then the invocation happens from the base-class scope and since instance() method is a base class method, calling a protected method from that is perfectly fine.

    static T& instance()
{
static T myInstance;
Singleton<T>& t = myInstance; // Just define a dummy reference here.
t.init();
return myInstance;
}

C++ singleton template class

The correctness of the concurrency related code here is difficult to evaluate. The implementation is trying to be a little too clever, in my opinion.

OTOH, all the concurrency related code basically has stubs behind it that do nothing. If this is used in a non-threaded environment, I think it should be fine.

But, I also think your worry is well founded. Those external definitions of static members seem like they would violate the one definition rule.

Personally, I think this template should be re-written to have the concurrency stuff as a policy argument to the template itself, and to require derived classes to declare their own versions of pInstance in an appropriate .cpp file.

Somebody else has suggested relying on compiler specific behavior with regards to the initialization of static local variables. I don't think that's a horrible suggestion, but it might be nice to have an option when you can't rely on the compiler to do the right thing.

Multiple instances of singleton across shared libraries on Linux

First, you should generally use -fPIC flag when building shared libraries.

Not using it "works" on 32-bit Linux, but would fail on 64-bit one with an error similar to:

/usr/bin/ld: /tmp/ccUUrz9c.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC

Second, your program will work as you expect after you add -rdynamic to the link line for the main executable:

singleton.num in main : 100
singleton.num in hello.so : 100
singleton.num in hello.so after ++ : 101
singleton.num in main : 101

In order to understand why -rdynamic is required, you need to know about the way dynamic linker resolves symbols, and about the dynamic symbol table.

First, let's look at the dynamic symbol table for hello.so:

$ nm -C -D hello.so | grep singleton
0000000000000b8c W singleton::instance()
0000000000201068 B singleton::pInstance
0000000000000b78 W singleton::singleton()

This tells us that there are two weak function definitions, and one global variable singleton::pInstance that are visible to the dynamic linker.

Now let's look at the static and dynamic symbol table for the original example1 (linked without -rdynamic):

$ nm -C  example1 | grep singleton
0000000000400d0f t global constructors keyed to singleton::pInstance
0000000000400d38 W singleton::instance()
00000000006022e0 B singleton::pInstance
0000000000400d24 W singleton::singleton()

$ nm -C -D example1 | grep singleton
$

That's right: even though the singleton::pInstance is present in the executable as a global variable, that symbol is not present in the dynamic symbol table, and therefore "invisible" to the dynamic linker.

Because the dynamic linker "doesn't know" that example1 already contains a definition of singleton::pInstance, it doesn't bind that variable inside hello.so to the existing definition (which is what you really want).

When we add -rdynamic to the link line:

$ nm -C  example1-rdynamic | grep singleton
0000000000400fdf t global constructors keyed to singleton::pInstance
0000000000401008 W singleton::instance()
00000000006022e0 B singleton::pInstance
0000000000400ff4 W singleton::singleton()

$ nm -C -D example1-rdynamic | grep singleton
0000000000401008 W singleton::instance()
00000000006022e0 B singleton::pInstance
0000000000400ff4 W singleton::singleton()

Now the definition of singleton::pInstance inside the main executable is visible to the dynamic linker, and so it will "reuse" that definition when loading hello.so:

LD_DEBUG=bindings ./example1-rdynamic |& grep pInstance
31972: binding file ./hello.so [0] to ./example1-rdynamic [0]: normal symbol `_ZN9singleton9pInstanceE'

In C++, can two other different shared objects access a Singleton from a third shared object?


A dynamic library (shared object), which includes a singleton class with a thread-safe Queue.

Singleton are used when you want to constraint a class to be instantiated only once. That's not what you want: you want all your plugins to work on a particular instance of a class. There is no "only one can live" requirement here.

A thread-safe singleton in C++11 using Meyer's pattern may looks like this:

class Singleton
{
private:
Singleton();

public:
Singleton(const &Singleton) = delete;
Singleton& operator=(const &Singleton) = delete;

static Singleton& get_instance()
{
static Singleton s;
return s;
}
};

Default constructor is declared private, and copy/assignment operations are deleted to avoid multiple instances.

You need something more simple: a function always returning the same instance. Something like this:

class Manager
{
public:
static Resource& get_resource()
{
static Resource r;
return r;
}
};

No need to prevent multiple instantiation: if you want the same instance, just ask for the same instance.

You can also extend the design with a resource pool returning a same instance given some id:

enum class ResourceId
{
ID_FOR_A_FAMILY_OF_PLUGIN,
ID_FOR_AN_OTHER_FAMILY_OF_PLUGIN
};

class Pool
{
public:
static Resource& get_resource(ResourceId id)
{
static std::map<ResourceId, Resource> p;
return p[id];
}
};

Note that in this example p[id] is created on the fly with Resource's default constructor. You may want to pass parameters during construction:

class Resource
{
public:
Resource():ready(false){}

void init(some parameters)
{
// do some intialization
ready = true;
}

bool is_ready() const { return ready; }

private:
bool ready;
};

class Pool
{
public:
static Resource& get_resource(ResourceId id)
{
static std::map<ResourceId, Resource> p;
auto& r = p[id];
if(!r.is_ready())
{
r.init(some parameters);
}
return r;
}
};

Or, using pointers to allow polymorphism:

class Pool
{
public:
static std::unique_ptr<Resource>& get_resource(ResourceId id)
{
static std::map<ResourceId, std::unique_ptr<Resource>> p;
auto& r = p[id];
if(!r)
{
r = std::make_unique<SomeResourceTypeForId>(some parameters);
}
return r;
}
};

Note that the last two implementations need a mutex around the non-static code to be thread-safe.

Generalized Singleton base class in Java

I have yet to see a satisfactory solution for this in Java. There are many examples using templates in C++ or generics in .NET, but Java's generics implementation has some limitations with static members that make this difficult.

The best option I've seen is to use a static HashMap, and a factory class. This allows you to make a single factory that can serve multiple Singletons of any class.

For an implementation, see this post.



Related Topics



Leave a reply



Submit