次の2つのヘッダーがあります。
#ifndef DRD_EVENT_HPP
#define DRD_EVENT_HPP
#include <functional>
namespace drd
{
template <typename Clock>
class event
{
public:
using clock = Clock;
using time_point = typename clock::time_point;
template <class F, class... Args>
event(time_point et, F&& f, Args&&... args) :
Task(std::bind<void>(std::forward<F>(f), std::forward<Args>(args)...)),
Time(et) {}
void perform() ///Can throw std::bad_function_call
{
Task();
Task = nullptr;
}
///Returns the event time.
time_point time() const noexcept
{ return Time; }
///Checks if the event has not been performed yet.
bool pending() const noexcept
{ return static_cast<bool>(Task); }
private:
std::function< void()> Task;
time_point Time;
};
struct later_event
{
template <class Clock>
bool operator()(const event<Clock>& lhs, const event<Clock>& rhs)
const noexcept
{
return lhs.time() > rhs.time();
}
};
}
#endif // DRD_EVENT_HPP
#ifndef DRD_DISCRETE_SIMULATION_HPP
#define DRD_DISCRETE_SIMULATION_HPP
#include <exception>
#include <chrono>
#include <queue>
#include "event.hpp"
namespace drd
{
namespace des ///Discrete event simulation
{
template <class Rep, class Period = std::ratio<1>>
class simulation_engine
{
public:
class clock;
using time_point = typename clock::time_point;
using duration = typename clock::duration;
using event_type = event<clock>;
public:
///Constructs an event "in-place" and inserts it in the events list
template <typename... EventArgs>
void schedule(EventArgs&&... event_args_)
{
EventsList.emplace(std::forward<EventArgs>(event_args_)...);
}
bool has_pending_events() const noexcept
{ return not EventsList.empty(); }
///Advances the clock until the next event time and then the event
///is performed, if the events list was empty the behavior is undefined.
void next_event()
{
auto Event = EventsList.top();
EventsList.pop();
clock::advance_until(Event.time());
Event.perform();
}
///Calls next_event() while the events list is not empty.
void simulate()
{ while (has_pending_events()) next_event();}
///Performs all of events whose time is scheduled before or just at the
///moment t, then advances the clock until t.
void simulate_until(time_point t)
{
while(has_pending_events() and EventsList.top().time() <= t)
next_event();
clock::advance_until(t);
}
void simulate_for(duration d)
{ simulate_until(clock::now() + d); }
private:
std::priority_queue<event_type, std::vector<event_type>,
later_event> EventsList;
};
///clock type that is thread-independent and adjustable by
///simulation_engine
template <class Rep, class Period>
class simulation_engine<Rep,Period>::clock
{
public:
using rep = Rep;
using period = Period;
using duration = std::chrono::duration<rep,period>;
using time_point = std::chrono::time_point<clock>;
public:
static constexpr bool is_steady = false;
public:
static time_point now() noexcept
{ return CurrentTime;}
private:
static void reset() noexcept
{ CurrentTime = time_point(); }
static void adjust(time_point t) noexcept
{ CurrentTime = t; }
static void advance_until(time_point t)
{
if(t < CurrentTime)
throw std::logic_error("advance_until cannot set the clock back.");
CurrentTime = t;
}
friend simulation_engine<Rep,Period>;
private:
static thread_local time_point CurrentTime;
};
template <class Rep, class Period>
thread_local typename simulation_engine<Rep,Period>::clock::time_point
simulation_engine<Rep,Period>::clock::CurrentTime;
}
}
#endif //DRD_DISCRETE_SIMULATION_HPP
オブジェクトは独立したイベント リストを所有し、同じクロックを共有し、同期の問題が発生する可能性があるため、simulation_engine のメンバー関数を静的にする必要があるかどうか疑問に思っていました。
私は何をすべきか?
私の英語と広範なコードで申し訳ありません。ご回答いただければ幸いです。よろしくお願いします。