TaskDispatcher.cpp 2.38 KB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
#include "TaskDispatcher.h"

#include "QtConcurrent"

typedef std::unique_lock<std::mutex> ULock;

namespace nemo_interface {

TaskDispatcher::TaskDispatcher() : _running(false) {}

TaskDispatcher::~TaskDispatcher() { stop(); }

std::future<QVariant> TaskDispatcher::dispatch(std::unique_ptr<Task> c) {
  ULock lk1(this->_mutex);

  this->_taskQueue.push_back(std::move(c));
  std::promise<QVariant> promise;
  auto future = promise.get_future();
  this->_promiseQueue.push_back(std::move(promise));

  if (!this->_running) {
    lk1.unlock();
    this->start();
  }

  return future;
}

std::future<QVariant> TaskDispatcher::dispatchNext(std::unique_ptr<Task> c) {
  ULock lk1(this->_mutex);

  this->_taskQueue.push_front(std::move(c));
  std::promise<QVariant> promise;
  auto future = promise.get_future();
  this->_promiseQueue.push_front(std::move(promise));

  if (!this->_running) {
    lk1.unlock();
    this->start();
  }

  return future;
}

void TaskDispatcher::clear() {
  ULock lk(this->_mutex);
  this->_taskQueue.clear();
  this->_promiseQueue.clear();
}

void TaskDispatcher::start() {
  ULock lk1(this->_mutex);
  if (!_running) {
    this->_running = true;
    lk1.unlock();
    _future = QtConcurrent::run([this]() mutable { return this->run(); });
  }
}

void TaskDispatcher::stop() {
  ULock lk1(this->_mutex);
  if (_running) {
    this->_running = false;
    lk1.unlock();
    this->_future.waitForFinished();
  }
}

void TaskDispatcher::reset() {
  clear();
  stop();
}

bool TaskDispatcher::isInterruptionRequested() {
  ULock lk1(this->_mutex);
  return !_running;
}

bool TaskDispatcher::isRunning() {
  ULock lk1(this->_mutex);
  return _running;
}

std::size_t TaskDispatcher::pendingTasks() {
  ULock lk1(this->_mutex);
  return this->_taskQueue.size() + (_running ? 1 : 0);
}

void TaskDispatcher::run() {
  while (true) {
    ULock lk1(this->_mutex);

    if (this->_taskQueue.size() > 0 && this->_running) {
Valentin Platzgummer's avatar
Valentin Platzgummer committed
94
      Q_ASSERT(this->_taskQueue.size() == this->_promiseQueue.size());
Valentin Platzgummer's avatar
Valentin Platzgummer committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
      // pop task and promise
      auto pTask = std::move(this->_taskQueue.front());
      auto promise = std::move(this->_promiseQueue.front());
      this->_taskQueue.pop_front();
      this->_promiseQueue.pop_front();
      lk1.unlock();

      // exec task
      promise.set_value(pTask->exec());
    } else {
      this->_running = false;
      lk1.unlock();
      break;
    }
  }
}

} // namespace nemo_interface