Home > Back-end >  Class with no blocking methodes with multithreading
Class with no blocking methodes with multithreading

Time:12-16

I am programming a class which should use multithreading features. The goal is that I don't have any blocking methods from the outside although I use libraries in the class that have blocking functions. I want to run them in their own threads. Unfortunately I get a memory fault (core dumped) error.

What would be the best practice in c 11 to implement something like this and why do I get the error,how can I specify the memory for the function I want to call in the thread best in advance?

My Class

.. 
class foo {

  void startUp();

  foo();
  ~foo();
  
  std::thread foo_worker;
  int retValue;

};

void foo::startUp() {
  int retValue = 0;

  std::thread t([this] () {
  retValue = blocking_lib_func();
});

foo_worker = std::move(t);

}

foo::~foo() {
  ....
  foo_worker.join();
}

My Main

int main() 

  foo test();
  test.statUp()
}

CodePudding user response:

The lambda associated with your thread is capturing a reference to local stack variable. When startUp returns, the thread will continue on, but the address of retValue is now off limits, including to the thread. The thread will create undefined behavior by trying to assign something to that reference to retValue. That is very likely the source of the crash that you describe. Or worse, stack corruption on the main thread corrupting your program in other ways.

The solution is simple. First, make retValue a member variable of your class. And while we are at it, no reason for foo_worker to be a pointer.

class foo {
public:
  void startUp();

  foo();
  ~foo();

private:      
  std::thread foo_worker;
  int retValue;

};

Then your startUp code can be this. We can use std::move to move the thread from the local t thread variable to the member variable of the class instance.

void foo::startUp() {

  std::thread t([this] () {
      retValue = blocking_lib_func(); // assign to the member variable of foo
  });
  foo_worker = std::move(t);
}

Then your destructor can invoke join as follows:

foo::~foo() {
  ....
  foo_worker.join();
}

And as other in the comments have pointed out, volatile isn't useful. It's mostly deprecated as a keyword when proper thread and locking semantics are used.

  • Related