#ifndef PLS_STATIC_SCHEDULER_MEMORY_H
#define PLS_STATIC_SCHEDULER_MEMORY_H

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

#include "pls/internal/scheduling/scheduler_memory.h"
#include "pls/internal/scheduling/thread_state.h"
#include "pls/internal/scheduling/thread_state_static.h"

namespace pls {
namespace internal {
namespace scheduling {

template<size_t MAX_THREADS, size_t NUM_TASKS, size_t STACK_SIZE>
class static_scheduler_memory : public scheduler_memory {
 public:
  static_scheduler_memory() : scheduler_memory{} {
    for (size_t i = 0; i < MAX_THREADS; i++) {
      thread_state_pointers_[i] = &thread_states_[i].get_thread_state();
    }
    thread_states_array_ = thread_state_pointers_.data();
  }

  size_t max_threads() const override {
    return MAX_THREADS;
  }

  base::thread &thread_for(size_t id) override {
    return threads_[id];
  }
 private:
  using thread_state_type = thread_state_static<NUM_TASKS, STACK_SIZE>;

  alignas(base::system_details::CACHE_LINE_SIZE) std::array<base::thread, MAX_THREADS> threads_;
  alignas(base::system_details::CACHE_LINE_SIZE) std::array<thread_state_type, MAX_THREADS> thread_states_;
  alignas(base::system_details::CACHE_LINE_SIZE) std::array<thread_state *, MAX_THREADS> thread_state_pointers_;
};

}
}
}

#endif // PLS_STATIC_SCHEDULER_MEMORY_H
