task.cpp 1.45 KB
Newer Older
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
#include "pls/internal/helpers/profiler.h"

#include "pls/internal/scheduling/scheduler.h"
#include "pls/internal/scheduling/task.h"
#include "pls/internal/scheduling/thread_state.h"

namespace pls {
namespace internal {
namespace scheduling {

task::task() :
    ref_count_{0},
    parent_{nullptr},
    deque_state_{0} {}

task::task(const task &other) :
    ref_count_{0},
    parent_{other.parent_},
    deque_state_{other.deque_state_} {}

void task::execute() {
  {
    PROFILE_WORK_BLOCK("execute task")
    auto last_executing = thread_state::get()->current_task_;
    thread_state::get()->current_task_ = this;

    execute_internal();

    thread_state::get()->current_task_ = last_executing;
  }

  wait_for_all();

  if (parent_ != nullptr) {
    parent_->ref_count_--;
  }
}

39 40 41 42
bool task::try_execute_local() {
  task *local_task = thread_state::get()->scheduler_->get_local_task();
  if (local_task != nullptr) {
    local_task->execute();
43
    return true;
44 45
  } else {
    return false;
46 47 48
  }
}

49 50 51 52 53 54
bool task::try_execute_stolen() {
  task *stolen_task = thread_state::get()->scheduler_->steal_task();
  if (stolen_task != nullptr) {
    stolen_task->deque_state_ = thread_state::get()->deque_.save_state();
    stolen_task->execute();
    return true;
55 56
  }

57
  return false;
58 59
}

60 61 62 63 64 65 66
void task::wait_for_all() {
  while (ref_count_ > 0) {
    if (!try_execute_local()) {
      try_execute_stolen();
    }
  }
  thread_state::get()->deque_.release_memory_until(deque_state_);
67 68 69 70 71
}

}
}
}