
#ifndef PLS_THREAD_STATE_H
#define PLS_THREAD_STATE_H

#include <random>

#include "pls/internal/base/thread.h"

#include "pls/internal/data_structures/aligned_stack.h"
#include "pls/internal/data_structures/deque.h"

namespace pls {
namespace internal {
namespace scheduling {

// forward declaration
class scheduler;
class task;

struct thread_state {
  alignas(base::system_details::CACHE_LINE_SIZE) scheduler *scheduler_;
  alignas(base::system_details::CACHE_LINE_SIZE) task *current_task_;
  alignas(base::system_details::CACHE_LINE_SIZE) data_structures::aligned_stack *task_stack_;
  alignas(base::system_details::CACHE_LINE_SIZE) data_structures::deque<task> deque_;
  alignas(base::system_details::CACHE_LINE_SIZE) size_t id_;
  alignas(base::system_details::CACHE_LINE_SIZE) std::minstd_rand random_;

  thread_state() :
      scheduler_{nullptr},
      current_task_{nullptr},
      task_stack_{nullptr},
      deque_{task_stack_},
      id_{0},
      random_{id_} {};

  thread_state(scheduler *scheduler, data_structures::aligned_stack *task_stack, unsigned int id) :
      scheduler_{scheduler},
      current_task_{nullptr},
      task_stack_{task_stack},
      deque_{task_stack_},
      id_{id},
      random_{id_} {}

  /**
   * Convenience helper to get the thread_state instance associated with this thread.
   * Must only be called on threads that are associated with a thread_state,
   * this will most likely be threads created by the scheduler.
   *
   * @return The thread_state of this thread.
   */
  static thread_state *get() { return base::this_thread::state<thread_state>(); }
};

}
}
}

#endif //PLS_THREAD_STATE_H
