c++ - 我应该使与可调时钟一起工作的成员函数静态化吗?

标签 c++ c++11 simulator

我有以下两个 header 。

#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 的成员函数设为静态,因为对象拥有独立的事件列表并共享相同的时钟,并且可能会发生同步问题。

我该怎么办?

抱歉我的英语和大量代码。 我希望你的回答,提前谢谢你。

最佳答案

我最终决定这样做,我认为这样更安全有用

  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 an event "in-place" and inserts it in the 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 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();
         CurrentTime = Event.time();
         Event.perform();
      }

      ///Calls next_event() while the events list is not empty.
      void simulate()
      { while (has_pending_events()) next_event();}


      ///if t >= current_time(), performs all of events whose time is scheduled
      ///before or just at the moment t, and then advances the current time until t.

      void simulate_until(const time_point& t)
      {
        if( t >= CurrentTime)
        {
          while(has_pending_events() and 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;
   };

关于c++ - 我应该使与可调时钟一起工作的成员函数静态化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16473666/

相关文章:

c++ - 你知道在 C++ 中获取线程本地存储的不同方法的一些性能测试吗?

c++ - g++ - 为什么在使用 std::thread 时必须传递 "-pthread"选项?

ios - Xcode6中的iPhone Simulator发送Mac的OS版本

ipad - 无法在 bundle 中加载NIB: 'NSBundle'

c++ - SDL2 调整表面大小

c++ - 判断两棵树是否同构

c++ - 从类内部线程化成员函数

gtk - 如何在 Windows 上安装 GTKWave?

c++ - HippoMocks 坚持要销毁 mock

c++ - std::map 插入另一个 map