scheduler.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /******************************************************************************
  2. *
  3. * Copyright (C) 2019 by
  4. * The Salk Institute for Biological Studies and
  5. * Pittsburgh Supercomputing Center, Carnegie Mellon University
  6. *
  7. * Use of this source code is governed by an MIT-style
  8. * license that can be found in the LICENSE file or at
  9. * https://opensource.org/licenses/MIT.
  10. *
  11. ******************************************************************************/
  12. #ifndef SRC4_SCHEDULER_H_
  13. #define SRC4_SCHEDULER_H_
  14. #include <deque>
  15. #include <list>
  16. #include <mutex>
  17. #include "base_event.h"
  18. namespace Json {
  19. class Value;
  20. }
  21. namespace MCell {
  22. // we should represent the time interval with a precisely
  23. // represented floating point value
  24. const double BUCKET_TIME_INTERVAL = 1;
  25. class Bucket {
  26. public:
  27. Bucket(double start_time_) :
  28. start_time(start_time_) {
  29. }
  30. ~Bucket();
  31. void insert(BaseEvent* event);
  32. void dump() const;
  33. double start_time;
  34. std::list<BaseEvent*> events;
  35. };
  36. typedef std::deque<Bucket> BucketDeque;
  37. class Calendar {
  38. public:
  39. Calendar() :
  40. cached_next_barrier_time(TIME_INVALID) {
  41. // create at least one item?
  42. queue.push_back(Bucket(TIME_SIMULATION_START));
  43. }
  44. ~Calendar() {
  45. // implicitly calls destructors of items in queue and
  46. // deletes all events
  47. }
  48. void insert(BaseEvent* event);
  49. double get_next_time();
  50. BaseEvent* pop_next();
  51. void dump() const;
  52. void to_data_model(Json::Value& mcell_node, const bool only_for_viz) const;
  53. const BaseEvent* find_next_event_with_type_index(
  54. const event_type_index_t event_type_index) const;
  55. void get_all_events_with_type_index(
  56. const event_type_index_t event_type_index, std::vector<BaseEvent*>& events);
  57. void get_all_events_with_type_index(
  58. const event_type_index_t event_type_index, std::vector<const BaseEvent*>& events) const;
  59. double get_time_up_to_next_barrier(const double current_time, const double max_time_step);
  60. void print_periodic_stats() const {
  61. std::cout << "Calendar: queue.size() = " << queue.size() << "\n";
  62. }
  63. private:
  64. // differs from get_next_time - does not clear empty buckets
  65. // and returns bucket start time, not the next event time
  66. double get_first_bucket_start_time() {
  67. assert(queue.size() != 0);
  68. return queue.front().start_time;
  69. }
  70. double event_time_to_bucket_start_time(const double time) {
  71. // flooring to a multiple of BUCKET_TIME_INTERVAL
  72. return floor_to_multiple_f(time, BUCKET_TIME_INTERVAL);
  73. }
  74. BucketDeque::iterator get_or_create_bucket(const double time);
  75. void clear_empty_buckets();
  76. // queue might be empty
  77. BucketDeque queue;
  78. // used in get_time_up_to_next_barrier
  79. double cached_next_barrier_time;
  80. };
  81. // Structure used to return information about the event that was just handled
  82. struct EventExecutionInfo {
  83. EventExecutionInfo(
  84. const double time_, const event_type_index_t type_index_, const bool return_from_run_iterations_) :
  85. time(time_), type_index(type_index_), return_from_run_iterations(return_from_run_iterations_) {
  86. }
  87. double time;
  88. event_type_index_t type_index;
  89. bool return_from_run_iterations;
  90. };
  91. class Scheduler {
  92. public:
  93. Scheduler() :
  94. event_being_executed(nullptr),
  95. async_event_queue_lock(mtx, std::defer_lock),
  96. have_async_events_to_schedule(false) {
  97. }
  98. // - scheduler becomes owner of the base_event object
  99. // - event's time must be valid and not be in the past
  100. void schedule_event(BaseEvent* event);
  101. // - similar as schedule_event only guarded by a critical section and
  102. // inserts the event into a separate queue of events,
  103. // - every method whose outcome might be changed by the events in the async queue
  104. // must call schedule_events_from_async_queue to schedule these events correctly
  105. // - events that have event_time == TIME_INVALID will get time for the next iteration
  106. // so that they are executed in the right order
  107. void schedule_event_asynchronously(BaseEvent* event);
  108. // returns the time of next event
  109. double get_next_event_time(const bool skip_async_events_check = false);
  110. // returns time of the event that was handled
  111. EventExecutionInfo handle_next_event();
  112. // skip events for checkpointing,
  113. // may take long time if periodic events are scheduled
  114. void skip_events_up_to_time(const double start_time);
  115. void dump() const;
  116. void to_data_model(Json::Value& mcell_node, const bool only_for_viz) const;
  117. const BaseEvent* find_next_event_with_type_index(
  118. const event_type_index_t event_type_index) {
  119. schedule_events_from_async_queue();
  120. return calendar.find_next_event_with_type_index(event_type_index);
  121. }
  122. void get_all_events_with_type_index(
  123. const event_type_index_t event_type_index, std::vector<BaseEvent*>& events) {
  124. schedule_events_from_async_queue();
  125. return calendar.get_all_events_with_type_index(event_type_index, events);
  126. }
  127. BaseEvent* get_event_being_executed() {
  128. return event_being_executed;
  129. }
  130. const BaseEvent* get_event_being_executed() const {
  131. return event_being_executed;
  132. }
  133. void print_periodic_stats() const {
  134. calendar.print_periodic_stats();
  135. }
  136. private:
  137. // checks if there are events in the async queue and schedules them
  138. // not really const but maintains the consistency of events visible to the outside
  139. void schedule_events_from_async_queue();
  140. Calendar calendar;
  141. // callback might need to query which event is being executed right now
  142. // is nullptr when no event is running
  143. BaseEvent* event_being_executed;
  144. // lock for asynchronous scheduling of events
  145. std::mutex mtx;
  146. std::unique_lock<std::mutex> async_event_queue_lock;
  147. std::vector<BaseEvent*> async_event_queue;
  148. volatile bool have_async_events_to_schedule; // unguarded flag for fast check whether async_event_queue is empty
  149. };
  150. } // namespace mcell
  151. #endif // SRC4_SCHEDULER_H_