TimeSystem.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "FrameUpdateClient.hpp"
4 #include "TimeId.hpp"
5 
7 
8 #include <map>
9 #include <set>
10 #include <queue>
11 #include <unordered_map>
12 #include <array>
13 
14 namespace iv
15 {
16 
17 class Watch;
18 class FixedUpdateClient;
19 
20 class TimeSystem : public System
21 {
22 public:
23  struct UpdateItem
24  {
25  std::function< void() > fun;
27 
28  UpdateItem( Instance * watch, std::function< void() > const & fun ) : fun( fun ), watch( watch ){}
29  };
30 
31  using timeout_iterator = std::multimap< int, UpdateItem >::iterator;
32 
33 
34 public:
35  // system
37  virtual std::string debug_name() const override { return "TimeSystem"; }
38  virtual bool flushSystem() override;
39 
40  // system control
41  void addTime( int delta_ms );
42  void nextFrame();
43 
44  // client interface
45  int get_time_ms( TimeId time_type );
46  int get_time_to_next_frame_ms( TimeId time_type );
47 
50 
51  void register_fixed_update_client( FixedUpdateClient * client, TimeId time_type );
52  void unregister_fixed_update_client( FixedUpdateClient * client, TimeId time_type );
53 
54  void speed( TimeId time_type, double speed );
55  double speed( TimeId time_type );
56 
57  void game_update_period( TimeId time_type, int period_ms );
58  int game_update_period( TimeId time_type );
59 
60  timeout_iterator timeout( Watch * watch, TimeId time_type, int time_abs_ms, std::function< void() > const & fun );
61 
62  void cancel_timeout( TimeId time_type, timeout_iterator it );
63 
64  void delay( Watch * watch, std::function< void() > const & fun );
65 
66  bool is_valid( TimeId time_type );
67 
68 private:
69  struct TimeData
70  {
71  int game_update_period_ms;
72  double speed_current; // currently used speed
73  double speed_target; // speed to be set at the beginning of next frame
74  int frame_start_time_ms; // time in ms that was on this clock when the frame started
75  double frame_start_time_remainder; // frame_start_time_ms is integral type, so when speed_current is low, we might lose digits after the decimal point. This is the remainder after conversion to integral type. We will attempt to add this to start_time_ms the next frame.
76 
77  TimeData() : game_update_period_ms( 16 ), speed_current( 1.0 ), speed_target( 1.0 ), frame_start_time_ms( 0 ), frame_start_time_remainder( 0.0 ){}
78  };
79 
80  int frame_time_ms; // how far in frame are we, in real time
81  int frame_length_ms; // how much of real time to add to frame
82 
83  std::vector< TimeData > time_data;
84 
85  std::vector< std::multimap< int, UpdateItem > > timeout_queues;
86  std::queue< UpdateItem > delayed;
87 
88  bool frame_update_queued;
89  std::set< FrameUpdateClient * > frame_clients;
90  std::set< FrameUpdateClient * >::iterator frame_clients_iterator;
91 
92  struct FixedData
93  {
94  int last_update;
95  std::set< FixedUpdateClient * > clients;
96  std::set< FixedUpdateClient * >::iterator iterator;
97 
98  FixedData() : last_update( 0 ), iterator( this->clients.end() ){}
99  };
100 
101  std::vector< FixedData > fixed;
102 };
103 
104 }