SSteven
SSteven

Reputation: 753

How to use call_once() correctly in a constructor?

The following program tries to use call_once() in a constructor. It is a modification of an example provided by Stroustrup in "CPL", 4.

class X
{
private:
   static int data;
   static once_flag initdata_flg;

   static void init();

public:
   X()
   {
      call_once(initdata_flg, init);

      cout << "** diagnostic: X::data initialized"
           << endl; 
   }

   int getdata() const
   {
      return data;
   }
};


/** class X static members ...
    (static members must be defined 
    outside the class **/
int X::data;
once_flag X::initdata_flg;

void X::init()
{
   data = 915;
}


/// declarations ...
void construct();

/// implementation ...

int main()
{
   thread t1 {construct};
   thread t2 {construct};

   t1.join();
   t2.join();
}

void construct()
{
    X x;
}


The output is as follows:

** diagnostic: X::data initialized
** diagnostic: X::data initialized

The diagnostic appears twice, rather than once. Clearly, this is not how to use call_once() correctly in a constructor.

For this to work, I would need to use call_once() in the construct() function. That's not what I want to do. I want to use call_once() in the constructor.

What is the right way to do so?

Upvotes: 0

Views: 185

Answers (1)

You're issuing the diagnostic in the consturctor, not in init. Of course the constructor will run twice; it will always run once for each object you create. However, only one of the calls to call_once will actually call init, which you can verify by moving the diagnostic output there.

[Live example]

Upvotes: 4

Related Questions