Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Static member functions in template classes and inlining

1 view
Skip to first unread message

tchernobog

unread,
Jun 22, 2006, 11:41:45 AM6/22/06
to
First of all, hi to everybody! This is my first post here.

I'm encountering a nasty problem in developing an application of mine.
I've got a main executable and some dynamic modules that can be loaded
by it. Both the executable and modules do link to a shared library
called "libbackend.so".

Into libbackend.so, I've put some objects that follow the Singleton
pattern. So I've created a template like this (it uses a Glib::Mutex
object you can easily ignore for thread-safeness):

-------- # code -------

template<typename Instantiated_class>
class Singleton
{
public:
static Instantiated_class& get_instance();

private:
static Instantiated_class* _instance;
static Glib::StaticMutex _mutex;
}; //~ class Singleton

template<typename Instantiated_class>
Instantiated_class*
sgpem::Singleton<Instantiated_class>::_instance = NULL;

template<typename Instantiated_class>
Glib::StaticMutex
sgpem::Singleton<Instantiated_class>::_mutex =
GLIBMM_STATIC_MUTEX_INIT;

template<typename Instantiated_class>
Instantiated_class&
sgpem::Singleton<Instantiated_class>::get_instance()
{
Glib::Mutex::Lock lock(_mutex);
if(_instance == NULL)
_instance = new Instantiated_class();
return *_instance;
}

---- # end code ----

This means that each Singleton I want to have into libbackend.so has
just to do:

-------- # code -------

class SomeClass : public Singleton<SomeClass>
{
friend class Singleton<SomeClass>;
public:
// ...
private:
SomeClass();
SomeClass(const SomeClass&);
}; //~ SomeClass

---- # end code ----

Now, the problem I noticed is that what should be a unique instance of
SomeClass (the one that dwells into libbackend.so) is instantiated
multiple times when the program begins, instead of really the first
time that SomeClass::get_instance() is called.

After investigating this for a little, I discovered that:

$ nm -C .libs/libbackend.so | grep get_instance

0000cd90 W sgpem::Singleton<sgpem::SomeClass>::get_instance()
00010b00 W sgpem::Singleton<sgpem::SomeOtherClass>::get_instance()

$ nm -C .libs/mainexecutable | grep get_instance

08051460 W sgpem::Singleton<sgpem::SomeClass>::get_instance()
08056e70 W sgpem::Singleton<sgpem::SomeOtherClass>::get_instance()

$ nm -C .libs/loadablemodule | grep get_instance

00004cd0 W sgpem::Singleton<sgpem::SomeClass>::get_instance()
00005010 W sgpem::Singleton<sgpem::SomeOtherClass>::get_instance()

So, my guess is that get_instance() of the Singleton template is
inlined and included into both the main executable and each module.
This is why calling SomeClass::get_instance() from one place returns a
SomeClass object, from another place it returns another unrelated
SomeClass object.

I'm not sure how to solve this. Of course, I can drop the template
completely and use the "standard way" to make every class I need a
Singleton, but I rather liked the idea of this approach. :-)
Maybe there's a GCC attribute to prevent inlining for a function,
although I'd prefer to not to use compiler-dependent flags for this.

So, how can i get the symbols for Singleton<SomeClass> to be marked "T"
(global exported symbols into the text section) in libbackend.so and
"U" (undefined) in the main executable and modules?

Thanks for any answer,
Matteo

PS: if I got it wrong, apologies in advance. I'm a student after all,
of course I behave stupidly! :-)

Paul Pluzhnikov

unread,
Jun 22, 2006, 6:25:08 PM6/22/06
to
"tchernobog" <msett...@gmail.com> writes:

> So, how can i get the symbols for Singleton<SomeClass> to be marked "T"
> (global exported symbols into the text section) in libbackend.so and
> "U" (undefined) in the main executable and modules?

Remove the definition of Singleton<T>::get_instance() from the
body of the class in Singleton.h header, and put it into a separate
Singleton.tc file.

Then '#include "Singleton.tc"' only into the compilation units
where you want the Singleton<SomeClass>::get_instance() to be
defined.

After that, you'll get a 'W' in libbackend.so, and a 'U' everywhere
else, which should be good enough.

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.

0 new messages