2

I am trying to execute some code(c++) on windows and cygwin(linux) and found there is a difference in execution of singleton class. Since my code has dependency with other singleton class, it functionally operates correctly with linux and not with windows, sometimes viceversa.

See the sequence below:

Posix:

 Singleton : UniqueIdService
 Singleton : MonitorServer
MonitorServer : Waiting for Monitor Client connection....
 Singleton : ManagerServer
ManagerServer : Waiting for Tester Client connection....
 Singleton : EventAggregator
 Singleton : DataAggregator
 Singleton : CounterService
 Singleton : AppletManager
 Singleton : SubService
 Singleton : PubService
 main

Windows:

 Singleton : AppletManager
 Singleton : PubService
 Singleton : SubService
 Singleton : CounterService
 Singleton : DataAggregator
 Singleton : EventAggregator
 Singleton : ManagerServer
ManagerServer : Waiting for Tester Client connection....
 Singleton : MonitorServer
MonitorServer : Waiting for Monitor Client connection....
 Singleton : UniqueIdService
 main

Is there a way or mechanism to sequence these execution across platform?

Code example. AppletManger.cpp:

AppletManager *AppletManager::instance = new AppletManager();
AppletManager::AppletManager(void)
{
    printf("\n Singleton : AppletManager");
}

AppletManager.h

class AppletManager
{
public:
    static AppletManager *getInstance(){
        assert(instance != NULL);
        return instance;
    }
    ~AppletManager();

private:
    AppletManager();
    static  AppletManager *instance;
};

UniqueIdService.cpp:

UniqueIdService *UniqueIdService::instance = new UniqueIdService();

UniqueIdService::UniqueIdService()
{
    printf("\n Singleton : UniqueIdService");
    uniqueId = 0;
    appletId = 0;
    funcblocId = 0;
    eventId = 0;
}

UniqueIdService.h:

class UniqueIdService
{
public:
    static UniqueIdService *getInstance(){
        assert(instance != NULL);
        return instance;
    }
    ~UniqueIdService();
private:
    UniqueIdService();
    static  UniqueIdService *instance;
};
kar
  • 495
  • 1
  • 8
  • 19
  • 2
    Show how you have you singletons defined and how they are used. Show, for example, two of them - no need to show them all. – Anon Mail Dec 15 '15 at 21:30
  • OK, how many of these singletons are subsystems with their own asynchronous initiaization/execution? – Martin James Dec 15 '15 at 21:32
  • 3
    Smells like relying on order of initialization of globals. Short answer - not gonna happen. – Rostislav Dec 15 '15 at 21:46
  • Martin James: I have 7 singletons – kar Dec 15 '15 at 21:57
  • 3
    You can guarantee the order of initialization of global data objects by defining them all in the same translation unit. If you need to guarantee dependency for initialization of global across translation units your best bet is to guard the global data by functions returning a reference to a static function-local object which will be created upon call. Usual recommendation applies, though: avoid using the anti-pattern Singleton if at all possible. – Dietmar Kühl Dec 15 '15 at 22:18
  • Static initialization described [here](http://stackoverflow.com/a/1421780/3042070) with excerpt from standard. – stj Dec 17 '15 at 20:54

2 Answers2

0

The best way to do a singleton in C++ is this:

A& getInstanceA() {
    static A a;
    return a;
}

This is thread safe and does not have order of initialization problem.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • 1
    This is thread-safe starting with C++11. When using Visual Studio, you'll need at least Visual Studio 2015 (see [Support For C++11/14/17 Features](https://msdn.microsoft.com/en-us/library/hh567368.aspx)). – IInspectable Dec 15 '15 at 23:06
  • Confirmed this is not thread-safe in Visual Studio 2013 and before. You'll get nice races and to find/reproduce partly-initialized variables when calling the function concurrently there. g++ produces code that prevents this from happening, but VS 2013 definitely doesn't. – stj Dec 17 '15 at 20:50
  • Then it's a bug. Because five years ago the standard said it was tread safe. msvc is so damn late... – Guillaume Racicot Dec 17 '15 at 20:53
  • At least the 2015 seems less crappy, but still lack some features. – Guillaume Racicot Dec 17 '15 at 20:54
0

You can create a partial ordering of initialization simply by referencing one singleton A in the constructor of another B. The referenced singleton A will have to be constructed before the constructor of the referencing singleton B completes, thus ensuring an ordering relationship that A is constructed before B.

The dependency graph must be acyclic, or else you get singletons all the way down. Don't do that; at best you'll get a stack overflow.

eh9
  • 7,340
  • 20
  • 43