4

sorry for the verbosity - I did my best to condense my code sample into a minimally functional class and main() method.

I'm trying to use an atomic_flag to notify _rx() within my worker thread to quit when stop() is called.

I believe the issue is in trying to create my worker thread,

thread SanityTestThread(&SanityTest::_rx, *this);

which somehow clashes with my atomic_flag

code sample (does not compile):

 #include <cstdio>
 #include <chrono>

 #include <unistd.h>
 #include <atomic>
 #include <iostream>
 #include <thread>

 using namespace std;

 class SanityTest
 {

   public:
     SanityTest(){}
     void start();
     void stop();

   private:
     void _rx();
     atomic_flag flag;

 }; // end class SanityTest

void SanityTest::_rx()
{
  while(flag.test_and_set())
  {
    this_thread::sleep_for(chrono::seconds(1));
    cout << "'sup foo" << endl;
  }
} // end _rx

void SanityTest::start()
{
  flag.test_and_set();
  thread SanityTestThread(&SanityTest::_rx, *this);
  SanityTestThread.detach();
} // end start

void SanityTest::stop()
{
  flag.clear();
} // end start

int main(){
  SanityTest s;// = SanityTest();
  s.start();
  this_thread::sleep_for(chrono::seconds(10));
  s.stop();
  return 0;
} // end main

For the record, I can get my program to compile and run by removing all references to my atomic_flag and replacing my _rx() loop with a for loop like so:

void SanityTest::_rx()
{
  for(int i=0; i <=10; ++ i)
  {
    this_thread::sleep_for(chrono::seconds(1));
    cout << "'sup foo" << endl;
  }
} // end _rx

Compiler Error:

In file included from ./SanityTest.cpp:1:0:
./SanityTest.hpp:14:7: note: ‘SanityTest::SanityTest(SanityTest&&)’ is implicitly deleted because the default definition would be ill-formed:
 class SanityTest
       ^
./SanityTest.hpp:14:7: error: use of deleted function ‘std::atomic_flag::atomic_flag(const std::atomic_flag&)’
In file included from /usr/include/c++/4.8/atomic:41:0,
                 from ./SanityTest.hpp:8,
                 from ./SanityTest.cpp:1:
/usr/include/c++/4.8/bits/atomic_base.h:275:5: error: declared here
     atomic_flag(const atomic_flag&) = delete;
     ^
In file included from /usr/include/c++/4.8/functional:55:0,
                 from /usr/include/c++/4.8/thread:39,
                 from ./SanityTest.hpp:10,
                 from ./SanityTest.cpp:1:

...

In file included from ./SanityTest.cpp:1:0:
./SanityTest.hpp:14:7: note: ‘SanityTest::SanityTest(SanityTest&&)’ is implicitly deleted because the default definition would be ill-formed:
 class SanityTest
       ^
./SanityTest.hpp:14:7: error: use of deleted function ‘std::atomic_flag::atomic_flag(const std::atomic_flag&)’
In file included from /usr/include/c++/4.8/atomic:41:0,
                 from ./SanityTest.hpp:8,
                 from ./SanityTest.cpp:1:
/usr/include/c++/4.8/bits/atomic_base.h:275:5: error: declared here
     atomic_flag(const atomic_flag&) = delete;
     ^
In file included from /usr/include/c++/4.8/functional:55:0,
                 from /usr/include/c++/4.8/thread:39,
                 from ./SanityTest.hpp:10,
                 from ./SanityTest.cpp:1:

p.s. This is compiled with, g++ -pthread -std=c++0x -o SanityTest ./SanityTest.cpp

darkpbj
  • 2,892
  • 4
  • 22
  • 32
  • 1
    See [this](http://stackoverflow.com/a/21048974/4074081) answer to similar issue. – dewaffled Jun 17 '15 at 14:07
  • Thanks @frymode! I didn't have enough insight into my own issue to really know what to search for in the first place – darkpbj Jun 17 '15 at 14:11
  • Check it out, I turned this into a blog post: http://darkpbj.com/main/index.php/2015/06/30/embedded-multi-threading-with-c/ – darkpbj Jun 30 '15 at 20:08

1 Answers1

2

Just replace

thread SanityTestThread(&SanityTest::_rx, *this);

with

thread SanityTestThread(&SanityTest::_rx, this);

You probably intended to pass a pointer to the object and not the object itself (which would result in that object being copied and the member function pointer &SanityTest::_rx being invoked on that copy instead of the original object).

The reason for the error message is essentially that std::atomic_flag doesn't have a copy constructor and so the compiler doesn't generate a default one for your SanityTest class either, but again: you don't want to copy your SanityTest object here anyway.

MikeMB
  • 20,029
  • 9
  • 57
  • 102
  • Also it is possible to pass argument as reference with `std::ref(*this)` – dewaffled Jun 17 '15 at 14:04
  • Thanks, it's been like mental gymnastics trying to wrap my head around C++ after a few years off. C++11 has been a huge help, but it's also made me feel like a stranger to the game again. Long story short, thanks for the easy fix. – darkpbj Jun 17 '15 at 14:15