TaskDispatcher.cpp 2.49 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
#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;
55
    QtConcurrent::run([this]() mutable { return this->run(); });
Valentin Platzgummer's avatar
Valentin Platzgummer committed
56
    lk1.unlock();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
57 58 59 60 61 62 63 64 65 66 67 68 69
  }
}

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

void TaskDispatcher::reset() {
  stop();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
70
  clear();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
}

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);
}

88 89
bool TaskDispatcher::idle() { return this->pendingTasks() == 0; }

90
void TaskDispatcher::run() {
Valentin Platzgummer's avatar
Valentin Platzgummer committed
91 92 93 94
  while (true) {
    ULock lk1(this->_mutex);

    if (this->_taskQueue.size() > 0 && this->_running) {
Valentin Platzgummer's avatar
Valentin Platzgummer committed
95
      Q_ASSERT(this->_taskQueue.size() == this->_promiseQueue.size());
Valentin Platzgummer's avatar
Valentin Platzgummer committed
96 97 98 99 100 101 102 103
      // 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
Valentin Platzgummer's avatar
Valentin Platzgummer committed
104 105 106 107
      QVariant var = pTask->exec();
      bool r = var.toBool();
      Q_ASSERT(r == true || r == false);
      promise.set_value(var);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
108 109 110 111 112 113 114 115 116
    } else {
      this->_running = false;
      lk1.unlock();
      break;
    }
  }
}

} // namespace nemo_interface