3

次の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 のメンバー関数を静的にする必要があるかどうか疑問に思っていました。

私は何をすべきか?

私の英語と広範なコードで申し訳ありません。ご回答いただければ幸いです。よろしくお願いします。

4

2 に答える 2

1

私は最終的にこれを行うことにしました。これははるかに安全で便利だと思います

  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;
   };
于 2013-05-10T07:52:42.453 に答える
0

私はすべての変数を静的にしようとしているので、メンバー関数を静的にする必要があるのは理にかなっています。ただし、そうでない場合は、すべての静的関数を使用しないでください。スレッドセーフにしたい場合は、すべての機能をロックする必要があります。シングルトン設計パターンも実装したいと思うかもしれません。http://en.wikipedia.org/wiki/Singleton_pattern

于 2013-05-10T01:51:17.443 に答える