views:

459

answers:

3

I'm pretty sure this problem isn't new, and pretty sure it's hard to solve. Hopefully I'm wrong about the latter.

I'm trying to use the Loki::Singleton from Modern C++ Design in a program of mine.

However, I can't seem to get it to work across DLLs. I think I know why this is happening: the templated code gets instantiated in every source module, so instead of there being one global variable, each module has its own.

Obviously, this makes the Singleton very much non-single.

Is there any way to get around this behavior?

A: 

You are probably correct that each DLL has its own instance of the singleton. I'm not that familiar with the Loki implementation and the source code isn't a lot of fun to figure out.

Possible solutions are:

  • Not using singletons. This is actually my usual preference because you can avoid whole classes of issues by changing your design to not need them. For a long rant on why Singletons may be harmful see this Yegge post. I'm not THAT vehemently against them but 95% of the time Singletons cause many more problems than they solve (if they actually solve any)
  • Copying static members across DLL boundaries. I've also done this as a hack, where the DLL gets a pointer from an application or another DLL, and resets its own copy of the static class member to the pointer passed from outside. It's evil, it's dirty, you can't clean up after it, but it does work.
MadKeithV
If you downvote, please comment as well on why.
MadKeithV
+1  A: 

Note this is not going to address the question. An explicitly instantiated and exported singleton should do the trick...

-Rick

Check out #pragma data_seg here basically, you need to declare an instance of the singleton in a shared section of your code. By default statics are scoped to the dll.

It may get tricky with templates, but this is the path to success here that doesn't involve passing / copying static data around.

Rick
I've learned something new today. Thanks!
Kaz Dragon
That doesn't seem to do what I want. Using the #pragma data_seg allows me to share data between PROGRAMS. The problem I am having is to share between DLLs.In fact, the restrictions on the page you pointed to explicitly state "Each process gets its own address space. It is very important that pointers are never stored in a variable contained in a shared data segment. A pointer might be perfectly valid in one application but not in another." And the Singleton uses pointers internally.
Eric H.
you are correct, sorry. Todd's answer below is correct.
Rick
+2  A: 

I see in the Loki source directory that they have a specific SingletonDLL directory under test, looks like they use an exported, explicitly instantiated template (which would work). Hopefully that contains the code you want.

Todd Gardner
Thanks, Todd!. That seemed to work, and I found this [KB article](http://support.microsoft.com/kb/168958) which explains in depth what the sample code from SingletonDll (in Loki) is doing. It's a pain to get working correctly (with all the declspecs and such), and it still leaves me with code like m_tick_file = Tick_File_Factory::Instance ().CreateObject ("OHLC_File")); in my apps. I think I might end up adding static member functions to Tick_File, which internally use the Loki stuff, then I know the templates only get inst'd once, in the .cpp for Tick_File
Eric H.