c++ - should I make member functions that work with an adjustable clock static? -
i have following 2 headers.
#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 event time. time_point time() const noexcept { return time; } ///checks if 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 event "in-place" , inserts in 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 clock until next event time , event ///is performed, if events list empty behavior undefined. void next_event() { auto event = eventslist.top(); eventslist.pop(); clock::advance_until(event.time()); event.perform(); } ///calls next_event() while events list not empty. void simulate() { while (has_pending_events()) next_event();} ///performs of events time scheduled before or @ ///moment t, advances clock until t. void simulate_until(time_point t) { while(has_pending_events() , 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 thread-independent , adjustable ///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 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
i wondering if should make member functions of simulation_engine static, because objects own independent events list , share same clock, , might happen synchronization problem.
what should do?
sorry english , extensive code. hope answer, thank in advance.
i decided this, think safer , useful
struct bad_event_scheduling : std::logic_error { bad_event_scheduling() : std::logic_error("bad_event_scheduling") {} }; template <class clock> class simulator { public: using clock = clock; using time_point = typename clock::time_point; using duration = typename clock::duration; using event_type = event<clock>; private: using calendar_type = std::priority_queue<event_type, std::vector<event_type>, later_event>; public: void reset() { currenttime = time_point(); eventslist = calendar_type(); } time_point current_time() const noexcept { return currenttime; } ///constructs event "in-place" , inserts in events list template <typename... otherargs> void schedule(const time_point& et, otherargs&&... other_args_) { if(et < currenttime) throw bad_event_scheduling(); eventslist.emplace(et, std::forward<otherargs>(other_args_)...); } bool has_pending_events() const noexcept { return not eventslist.empty(); } ///advances clock until next event time , event ///is performed, if events list empty behavior undefined. void next_event() { auto event = eventslist.top(); eventslist.pop(); currenttime = event.time(); event.perform(); } ///calls next_event() while events list not empty. void simulate() { while (has_pending_events()) next_event();} ///if t >= current_time(), performs of events time scheduled ///before or @ moment t, , advances current time until t. void simulate_until(const time_point& t) { if( t >= currenttime) { while(has_pending_events() , eventslist.top().time() <= t) next_event(); currenttime = t; } } void simulate_for(const duration& d) { simulate_until(currenttime + d); } private: calendar_type eventslist; time_point currenttime; };
Comments
Post a Comment