samedi 1 janvier 2022

Pausing and resuming a function in an std::thread

I am using an std::thread in my C++ code to run a function. I would like to be able to start the function, and pause it and resume it at will from another thread. This is how the starting and pause/resume is meant to work:

Task task(&myFun);

task.start(); // this starts the function myFun

task.pause(); // this pauses the function myFun wherever it's at

task.resume(); // this resumes myFun at the point where it paused

task.stop(); // this indefinitely stops myFun

Here is the class declaration:

class Task {
 public:
  Task(std::function<void()> func);

  void start();

  void pause();

  void resume();

  void stop();

 private:
  std::string status;
  std::function<void()> fun;

  std::mutex m;
  std::condition_variable condVar;

  std::thread taskThread;
};

With the constructor being:

Task(F func) : fun(std::move(func)) {
  this->status = "paused";
}

Here is my current implementation of the scheduling, pausing, resuming and stopping methods:

void start() {
  status = "running";

  taskThread = std::thread([this]{
    for (;;) {
      std::unique_lock<decltype(this->m)> l(this->m);
      this->condVar.wait(l, [this]{ return status == "running"; });

      fun();
      status = "completed";
    }
  });
}

void pause() {
  if(status == "running") {
    {
      std::lock_guard<decltype(this->m)> l(this->m);
      status = "paused";
    }
    this->condVar.notify_one();
  }
}

void resume() {
  if(status == "paused") {
    {
      std::lock_guard<decltype(this->m)> l(this->m);
      status = "running";
    }
    this->condVar.notify_one();
  }
}

void stop() {
  if (status == "running" or status == "paused") {
    {
      std::lock_guard<decltype(this->m)> l(this->m);
      status = "stopped";
    }
    this->condVar.notify_one();
  }
}

My current implementation allows for the function fun to be started and completed with the correct "running" and "completed" flags. However, when I try to pause, the method pause() waits at the line std::lock_guard<decltype(this->m)> l(this->m); until myFun is completed, and then changes the status of task.

My question is: in C++, is there a way to pause the thread while myFun is running, hence pausing / resuming myFun?

Aucun commentaire:

Enregistrer un commentaire