GlPortal Class Reference  0.1.1
Source code documentation of the free and open 3D action puzzle game.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SystemManager.hpp
Go to the documentation of this file.
1 #ifndef RADIX_SYSTEM_MANAGER_HPP
2 #define RADIX_SYSTEM_MANAGER_HPP
3 
4 #include <condition_variable>
5 #include <limits>
6 #include <map>
7 #include <memory>
8 #include <mutex>
9 #include <queue>
10 #include <set>
11 #include <stack>
12 #include <thread>
13 #include <vector>
14 
16 #include <radix/system/System.hpp>
17 
18 namespace radix {
19 
20 class World;
21 
23 protected:
24  friend class World;
25  World &w;
27 
28  void dispatchEvent(const Event&);
29  void run(TDelta dtime);
30 
31 public:
32  World& world() const {
33  return w;
34  }
35 
36  using SystemPtrVector = std::vector<std::unique_ptr<System>>;
37  struct SystemGraphNode;
38  using SystemGraphNodeVector = std::vector<std::unique_ptr<SystemGraphNode>>;
39  struct SystemGraphNode {
43 
44  std::set<SystemTypeId> predecessors, successors;
45 
46  /* Tarjan's strongly connected components algothm data */
48  bool onStack;
49  static constexpr decltype(index) indexUndef = std::numeric_limits<decltype(index)>::max();
50  static constexpr decltype(lowlink) lowlinkUndef = std::numeric_limits<decltype(lowlink)>::max();
51 
52  /* System execution variables */
53  unsigned int counter;
54  std::mutex counterMut;
55 
57  };
58 
59 protected:
60  struct SystemRunner {
61  std::vector<std::thread> threads;
62  std::queue<SystemTypeId> queue;
63  std::mutex queueMutex;
64  std::condition_variable queueCondVar;
65  bool exit;
68  std::mutex runCountMutex;
69  std::condition_variable runCountCondVar;
70  SystemRunner(SystemManager&);
71  ~SystemRunner();
72  void threadProc(SystemManager&);
73  } systemRun;
74 
77  std::map<std::string, System&> systemsByName;
78 
79  void computeSystemOrder();
80 
81 public:
82  using SystemLoopPath = std::stack<SystemTypeId>;
83  using SystemLoopVector = std::vector<std::set<SystemTypeId>>;
84 
85  struct RunsBeforeCreatesLoopsException : public std::logic_error, SystemLoopVector {
87  std::logic_error("Execution graph contain loops"),
88  SystemLoopVector(slv) {}
89  };
90  struct RunsAfterCreatesLoopException : public std::logic_error, SystemLoopPath {
92  std::logic_error("Inserting a System into the execution graph according to"
93  "System::runsAfter() would create a loop"),
94  SystemLoopPath(slp) {}
95  };
96 
97  struct SystemAddedEvent : public Event {
98  static constexpr StaticEventTypeName TypeName = "radix/SystemManager:SystemAdded";
99  const EventTypeName getTypeName() const {
100  return TypeName;
101  }
102  static constexpr StaticEventType Type = TypeNameHash(TypeName);
103  const EventType getType() const {
104  return Type;
105  }
106 
110  sysMan(sm), system(s) {}
111  };
112  struct SystemRemovedEvent : public Event {
113  static constexpr StaticEventTypeName TypeName = "radix/SystemManager:SystemRemoved";
114  const EventTypeName getTypeName() const {
115  return TypeName;
116  }
117  static constexpr StaticEventType Type = TypeNameHash(TypeName);
118  const EventType getType() const {
119  return Type;
120  }
121 
125  sysMan(sm), system(s) {}
126  };
127 
128  class Transaction final {
129  public:
131 
132  private:
133  friend class SystemManager;
134  Transaction(SystemManager &sm) : sm(sm) {}
135 
136  public:
137  Transaction(const Transaction&) = delete;
138  Transaction& operator=(const Transaction&) = delete;
139 
140  Transaction(Transaction&&) = default;
141  Transaction& operator=(Transaction&&) = default;
142 
144  sm.computeSystemOrder();
145  }
146 
147  template<class T, typename... ArgsT> void addSystem(ArgsT... args) {
148  static_assert(std::is_base_of<System, T>::value, "T must be a System");
149  const SystemTypeId stid = System::getTypeId<T>();
150  if (sm.systems.size() <= stid) {
151  sm.systems.resize(stid + 1);
152  }
153  sm.systems.at(System::getTypeId<T>()).reset(new T(sm.w, std::forward<ArgsT>(args)...));
154  System &sys = *sm.systems.at(System::getTypeId<T>());
155  sm.systemsByName.emplace(std::piecewise_construct,
156  std::forward_as_tuple(sys.getName()),
157  std::forward_as_tuple(sys));
158  sm.dispatchEvent(SystemAddedEvent(sm, *sm.systems.at(System::getTypeId<T>())));
159  }
160 
161  template<class T> void removeSystem() {
162  System &sys = *sm.systems.at(System::getTypeId<T>());
163  sm.dispatchEvent(SystemRemovedEvent(sm, sys));
164  sm.systemsByName.erase(sys.getName());
165  sm.systemGraph.at(System::getTypeId<T>()).reset(nullptr);
166  sm.systems.at(System::getTypeId<T>()).reset(nullptr);
167  }
168  };
169 
171  return Transaction(*this);
172  }
173 
174  template<class T> T& get() {
175  // We're casting down the class hierarchy, maybe use dynamic_cast instead ?
176  // But unless the systems collection break, it should always be ok.
177  return static_cast<T&>(*systems.at(System::getTypeId<T>()));
178  }
179 
180  template<class T, typename... ArgsT> void add(ArgsT... args) {
181  Transaction st(*this);
182  st.addSystem<T>(std::forward(args)...);
183  }
184 
185  template<class T> void remove() {
186  Transaction st(*this);
187  st.removeSystem<T>();
188  }
189 };
190 
191 } /* namespace radix */
192 
193 #endif /* RADIX_SYSTEM_MANAGER_HPP */
System & system
Definition: SystemManager.hpp:123
Definition: GameController.hpp:7
SystemGraphNodeVector & graph
Definition: SystemManager.hpp:42
void dispatchEvent(const Event &)
Definition: SystemManager.cpp:273
Definition: System.hpp:21
std::size_t SystemTypeId
Definition: System.hpp:10
Definition: Event.hpp:15
SystemManager & sysMan
Definition: SystemManager.hpp:107
SystemTypeId index
Definition: SystemManager.hpp:47
void add(ArgsT...args)
Definition: SystemManager.hpp:180
std::set< SystemTypeId > predecessors
Definition: SystemManager.hpp:44
void removeSystem()
Definition: SystemManager.hpp:161
bool onStack
Definition: SystemManager.hpp:48
std::vector< std::unique_ptr< SystemGraphNode >> SystemGraphNodeVector
Definition: SystemManager.hpp:38
void addSystem(ArgsT...args)
Definition: SystemManager.hpp:147
Definition: Uncollider.hpp:10
const EventType getType() const
Definition: SystemManager.hpp:103
struct radix::SystemManager::SystemRunner systemRun
System & system
Definition: SystemManager.hpp:108
SystemAddedEvent(SystemManager &sm, System &s)
Definition: SystemManager.hpp:109
RunsBeforeCreatesLoopsException(SystemLoopVector &&slv)
Definition: SystemManager.hpp:86
Definition: TimeDelta.hpp:8
SystemGraphNodeVector systemGraph
Definition: SystemManager.hpp:76
std::mutex runCountMutex
Definition: SystemManager.hpp:68
const EventType getType() const
Definition: SystemManager.hpp:118
const uint32_t StaticEventType
Definition: Event.hpp:10
Transaction(SystemManager &sm)
Definition: SystemManager.hpp:134
std::condition_variable queueCondVar
Definition: SystemManager.hpp:64
TDelta dtime
Definition: SystemManager.hpp:66
std::string EventTypeName
Definition: Event.hpp:13
SystemRemovedEvent(SystemManager &sm, System &s)
Definition: SystemManager.hpp:124
static decltype(lowlink) constexpr lowlinkUndef
Definition: SystemManager.hpp:50
SystemPtrVector systems
Definition: SystemManager.hpp:75
SystemTypeId lowlink
Definition: SystemManager.hpp:47
const EventTypeName getTypeName() const
Definition: SystemManager.hpp:99
std::queue< SystemTypeId > queue
Definition: SystemManager.hpp:62
static decltype(index) constexpr indexUndef
Definition: SystemManager.hpp:49
~Transaction()
Definition: SystemManager.hpp:143
void run(TDelta dtime)
Definition: SystemManager.cpp:277
Definition: SystemManager.hpp:60
const SystemTypeId system
Definition: SystemManager.hpp:40
std::mutex queueMutex
Definition: SystemManager.hpp:63
Definition: SystemManager.hpp:128
Definition: SystemManager.hpp:39
Transaction transact()
Definition: SystemManager.hpp:170
SystemManager & sysMan
Definition: SystemManager.hpp:122
SystemTypeId runCount
Definition: SystemManager.hpp:67
void computeSystemOrder()
Definition: SystemManager.cpp:163
SystemManager(World &)
Definition: SystemManager.cpp:268
RunsAfterCreatesLoopException(SystemLoopPath &&slp)
Definition: SystemManager.hpp:91
std::vector< std::unique_ptr< System >> SystemPtrVector
Definition: SystemManager.hpp:36
std::condition_variable runCountCondVar
Definition: SystemManager.hpp:69
std::set< SystemTypeId > successors
Definition: SystemManager.hpp:44
std::map< std::string, System & > systemsByName
Definition: SystemManager.hpp:77
unsigned int counter
Definition: SystemManager.hpp:53
bool exit
Definition: SystemManager.hpp:65
uint32_t EventType
Definition: Event.hpp:11
Definition: World.hpp:32
const char *const StaticEventTypeName
Definition: Event.hpp:12
std::stack< SystemTypeId > SystemLoopPath
Definition: SystemManager.hpp:82
virtual const char * getName() const =0
Definition: SystemManager.hpp:97
SystemPtrVector & systems
Definition: SystemManager.hpp:41
std::vector< std::thread > threads
Definition: SystemManager.hpp:61
Definition: SystemManager.hpp:112
World & w
Definition: SystemManager.hpp:25
std::mutex counterMut
Definition: SystemManager.hpp:54
World & world() const
Definition: SystemManager.hpp:32
Definition: SystemManager.hpp:22
std::vector< std::set< SystemTypeId >> SystemLoopVector
Definition: SystemManager.hpp:83
const EventTypeName getTypeName() const
Definition: SystemManager.hpp:114
SystemManager & sm
Definition: SystemManager.hpp:130