1 | #include <chrono> |
2 | #include <atomic> |
3 |
|
4 | #include "ZydecoCommon.hpp" |
5 | #include "Engine.hpp" |
6 | #include "Renderer.hpp" |
7 | #include "ThreadLooping.hpp" |
8 | #include "IEventHandler.hpp" |
9 | #include "IWindow.hpp" |
10 |
|
11 |
|
12 | Logger LOGGER("ENGINE"); |
13 | Logger EVENT_LOGGER("ENGINE::EVENT"); |
14 | Logger RENDER_LOGGER("ENGINE::RENDER"); |
15 |
|
16 |
|
17 | Engine::Engine(IEventHandler& r_event_handler, Renderer& r_renderer): |
18 | m_rEventHandler(r_event_handler), |
19 | m_rRenderer(r_renderer) |
20 | { |
21 | LOGGER.Log(Logger::TRACE, "Engine::Engine()"); |
22 |
|
23 | r_event_handler.RegisterQuitEventSubscriber(this); |
24 | std::atomic_init(&m_aIsExiting, false); |
25 | } |
26 |
|
27 | Engine::~Engine() |
28 | { |
29 | LOGGER.Log(Logger::TRACE, "Engine::~Engine()"); |
30 | } |
31 |
|
32 | void Engine::OnQuitEvent() |
33 | { |
34 | LOGGER.Log(Logger::VERBOSE, "QuitEvent occurred. Trigger exit."); |
35 |
|
36 | m_aIsExiting.store(true); |
37 | } |
38 |
|
39 | void Engine::Execute() |
40 | { |
41 | // Called from main() |
42 | LOGGER.Log(Logger::INFO, "Entering engine loop (thread handler)"); |
43 |
|
44 | // Create and start subsystem threads |
45 | LOGGER.Log(Logger::DEBUG, "Spawning subsystem threads"); |
46 |
|
47 | ThreadLooping event_thread {"Event Handler", m_rEventHandler}; |
48 | m_threads.push_back(&event_thread); |
49 | ThreadLooping render_thread {"Renderer", m_rRenderer}; |
50 | m_threads.push_back(&render_thread); |
51 |
|
52 | for (auto* thread : m_threads) |
53 | { |
54 | thread->Start(); |
55 | } |
56 |
|
57 | // Main thread busy wait until signalled to exit, or until a thread exits |
58 | while (m_aIsExiting.load() == false) |
59 | { |
60 | for (auto* thread : m_threads) |
61 | { |
62 | if (thread->IsRunning() == false) |
63 | { |
64 | m_aIsExiting.store(true); |
65 | break; |
66 | } |
67 | } |
68 | } |
69 |
|
70 | // Subsystem signaled exiting |
71 | LOGGER.Log(Logger::DEBUG, "Signal to quit"); |
72 |
|
73 | // Signal any running threads to terminate, and wait for termination |
74 | for (auto* thread : m_threads) |
75 | { |
76 | if (thread->IsRunning()) |
77 | { |
78 | thread->Terminate(); |
79 | thread->WaitUntilFinished(); |
80 | } |
81 | } |
82 |
|
83 | // All threads terminated. Exit main engine loop... |
84 | LOGGER.Log(Logger::INFO, "Exiting engine loop (thread handler)"); |
85 | } |
86 |
|