Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how do I initialise an atomic_flag variable if it is a member of a class?

I'm trying to implement a spin lock using an atomic_flag. I know that with C++11 I have to initialise the atomic_flag variable, but I can't get it to compile. My code looks like this:

class SpinLock 
{
 public:
  SpinLock()
   :m_flag(ATOMIC_FLAG_INIT)  /// syntax error : missing ')' before '{'
  {
  }

  void lock()
  {
    while (m_flag.test_and_set() == true){}
  }

  void unlock()
  {
    m_flag.clear();
  }

 private:
  SpinLock &operator=(const SpinLock &);

 private:
  std::atomic_flag    m_flag;
};

When I compile the code I get 'syntax error : missing ')' before '{''. I also see that ATOMIC_FLAG_INIT is defined as {0}, but what is the correct way to write this then?

The following compiles, but is it still threads safe?

  SpinLock()
  {
         m_flag.clear();
  }
like image 205
Arno Duvenhage Avatar asked Oct 29 '13 11:10

Arno Duvenhage


2 Answers

Visual Studio 2012 does not support c++11 initializer lists (see the c++11 support page)

It is however supported in Visual Studio 2013, (see the "initializer_list Constructors" section in the Uniform Initialization docs)

Meanwhile in your case the constructor can just use an assignment m_flag = ATOMIC_FLAG_INIT;

Update: It seems it did not test the above assignment, but using m_flag.clear(); achieves the same result

like image 124
Mihai Stan Avatar answered Oct 23 '22 18:10

Mihai Stan


It really looks like a bug ( visual 2013 rtm ). ATOMIC_FLAG_INIT is implementation specific and solve as a macro to {0}. It means that Microsoft uses aggregate rules to do the job.

Quote from cppreference about them : Until C++11, aggregate initialization could not be used in a constructor initializer list due to syntax restrictions.. I conclude that Microsoft do not yet change this behavior.

Here an exemple working fine on clang and failing on VS2013 RTM with a simpler case :

struct Pod {
  int m_val;
};

Pod g_1{ 0 }; // aggregate initialization
Pod g_2{ { 0 } }; // just like ATOMIC_FLAG_INIT

struct Foo {
  Foo() : m_2 { 0 } {} // error C2664: 'Pod::Pod(const Pod &)' : cannot convert argument 1 from 'int' to 'const Pod &'
  Pod m_1{ 0 }; // error C2664: 'Pod::Pod(const Pod &)' : cannot convert argument 1 from 'int' to 'const Pod &'
  Pod m_2; // ok
};
like image 42
galop1n Avatar answered Oct 23 '22 19:10

galop1n