简体   繁体   中英

How to use c++11 std::thread to implement a QThread-like class?

std::thread is not simply inheritable by classes, cannot auto join when destruction, etc.

Lots of pitfalls like need to use std::atomic_bool for stopping, cannot simply share this of object when use std::thread as member variables to execute a member method.

Is there any good practice to implement QThread like classes using std::thread ?


I'm aiming at an inheritable Thread class, enables start() , detach() , stop() functionality.

For example I wrote one like the following:

#include <atomic>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <thread>
#include <vector>

struct Thread {
  Thread(int id) {
    std::atomic_init(&(this->id), id);
    std::atomic_init(&(this->m_stop), false);
  }

  Thread(Thread &&rhs) :
    id(),
    m_stop(),
    m_thread(std::move(rhs.m_thread))
  {
    std::atomic_init(&(this->id), rhs.id.load());
    rhs.id.store(-1);
    std::atomic_init(&(this->m_stop), rhs.m_stop.load());
  }

  virtual ~Thread() {
    this->stop();
  }

  void start() {
    this->m_thread = std::move(std::thread(&Thread::work, this));
  }

  void stop() {
    this->m_stop.store(true);

    if (this->m_thread.joinable()) {
      this->m_thread.join();
    }
  }

  virtual void work() {
    while (!(this->m_stop)) {
      std::chrono::milliseconds ts(5000);
      std::this_thread::sleep_for(ts);
    }
  }

  std::atomic_int id;
  std::atomic_bool m_stop;
  std::thread m_thread;
};


int main() {
  srand(42);

  while (true) {
    std::vector<Thread> v;

    for (int i = 0; i < 10; ++i) {
      auto t = Thread(i);
      v.push_back(std::move(t));
      printf("Start %d\n", i);
      v[i].start();
    }
    printf("Start fin!\n");

    int time_sleep = rand() % 2000 + 1000;
    std::chrono::milliseconds ts(time_sleep);
    std::this_thread::sleep_for(ts);

    for (int i = 0; i < 10; ++i) {
      printf("Stop %d\n", i);
      v[i].stop();
      printf("Pop %d\n", i);
      v.pop_back();
    }
    printf("Stop fin!\n");
  }

  return 0;
}

But I'm having a hard time getting it right, just after Stop 0 it deadlocked, or sometimes it core dumps.

std::thread is intended as the lowest building block for implementing a threading primitive. As such, it does not offer as rich an interface as QThread, but together with the synchronization primitives from the standard library, it allows you to implement more complex behavior like what's offered by QThread very easily.

You correctly noted that inheriting from std::thread is a bad idea (the absence of a virtual destructor is a dead giveaway) and I would argue that having a polymorphic Thread type is not the smartest design in the first place, but you can easily encapsulate a std::thread as a member of any class (polymorphic or not) if you want to.

Joining on destruction is really just a policy. A class encapsulating a std::thread as a member can simply call join in its destructor, effectively implementing self-joining on destruction. Concurrency is of no concern here, as object destruction is always executed non-concurrently, by definition. If you want to share ownership of a thread between multiple (possible concurrently invoked) execution paths, std::shared_ptr will handle that for you. But even here, the destructor is always executed non-concurrently by the last remaining thread that gives up its shared_ptr .

Stuff like QThread::isInterruptionRequested can be implemented with a single flag, access to which of course must be synchronized by the class (either with a mutex or by using an atomic flag).

Changing a thread's priority is not specified by the standard, as not all platforms envisioned by the standard would allow this, but you can use native_handle to implement this yourself using platform-specific code.

And so on. All the pieces are there, you just have to assemble them according to your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM