Mountain  1.0.0
Simple C++ 2D Game Framework
coroutine.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <chrono>
4 #include <coroutine>
5 #include <functional>
6 #include <unordered_map>
7 
8 #include "Mountain/core.hpp"
10 
13 
14 namespace Mountain
15 {
16  // Everything named using the snake_case convention in this file is required by C++20 coroutines: https://en.cppreference.com/w/cpp/language/coroutines
17 
61  class Coroutine
62  {
63  struct Awaitable;
64 
65  public:
67  using AwaitType = std::chrono::duration<double_t>;
68 
73  struct promise_type
74  {
76  AwaitType awaitValue = AwaitType::zero();
77 
79  MOUNTAIN_API Coroutine get_return_object();
80 
82  MOUNTAIN_API std::suspend_always initial_suspend();
83 
85  MOUNTAIN_API std::suspend_always final_suspend() noexcept;
86 
88  [[noreturn]]
89  MOUNTAIN_API void unhandled_exception();
90 
92  MOUNTAIN_API void return_void();
93 
95  MOUNTAIN_API Awaitable await_transform(const AwaitType& duration);
96 
98  MOUNTAIN_API Awaitable await_transform(float_t duration);
99 
101  MOUNTAIN_API std::suspend_always yield_value(nullptr_t);
102  };
103 
104  private:
105  struct Awaitable
106  {
108  MOUNTAIN_API bool_t await_ready();
109 
111  MOUNTAIN_API void await_suspend(std::coroutine_handle<promise_type>);
112 
114  MOUNTAIN_API void await_resume();
115  };
116 
117  MOUNTAIN_API static inline std::unordered_map<Guid, Coroutine> m_RunningRoutines;
118 
119  public:
121  using HandleType = std::coroutine_handle<promise_type>;
122 
123  MOUNTAIN_API static Guid Start(Coroutine&& coroutine);
124 
128  MOUNTAIN_API static void Start(Coroutine&& coroutine, Guid* coroutineId);
129 
130  MOUNTAIN_API static void UpdateAll();
131 
132  MOUNTAIN_API static void Stop(const Guid& coroutineId);
133 
134  MOUNTAIN_API static void StopAll();
135 
136  [[nodiscard]]
137  MOUNTAIN_API static bool_t IsRunning(const Guid& coroutineId);
138 
139  [[nodiscard]]
140  MOUNTAIN_API static bool_t IsRunningAndNotEmpty(const Guid& coroutineId);
141 
142  [[nodiscard]]
143  MOUNTAIN_API static size_t GetRunningCount();
144 
145  MOUNTAIN_API Coroutine() = default;
146 
147  // ReSharper disable once CppNonExplicitConvertingConstructor
149  [[nodiscard]]
150  MOUNTAIN_API Coroutine(HandleType handle);
151 
152  MOUNTAIN_API Coroutine& operator=(HandleType handle) noexcept;
153 
154  MOUNTAIN_API ~Coroutine();
155 
156  // Delete copy operations
157  Coroutine(const Coroutine&) = delete;
158  Coroutine& operator=(const Coroutine&) = delete;
159 
160  // Define move operations
161  [[nodiscard]]
162  MOUNTAIN_API Coroutine(Coroutine&& other) noexcept;
163  MOUNTAIN_API Coroutine& operator=(Coroutine&& other) noexcept;
164 
167  MOUNTAIN_API void Resume() const;
168 
171  MOUNTAIN_API void ResumeSafe() const;
172 
175  [[nodiscard]]
176  MOUNTAIN_API bool_t Finished() const;
177 
183  [[nodiscard]]
184  MOUNTAIN_API bool_t FinishedSafe() const;
185 
188  MOUNTAIN_API void Destroy();
189 
192  MOUNTAIN_API void DestroySafe();
193 
196  [[nodiscard]]
197  MOUNTAIN_API bool_t Valid() const;
198 
201  MOUNTAIN_API void Reset();
202 
204  [[nodiscard]]
205  MOUNTAIN_API Guid GetId() const;
206 
207  private:
208  HandleType m_Handle;
209 
210  Guid m_Id;
211 
212  Coroutine(const Guid& guid, HandleType handle);
213  };
214 
216  template <typename... Args>
217  using CoroutineFunction = std::function<Coroutine(Args...)>;
218 }
MOUNTAIN_API bool_t FinishedSafe() const
Safely returns whether the Coroutine finished its execution by first checking if Valid() is true...
MOUNTAIN_API Awaitable await_transform(const AwaitType &duration)
Converts a AwaitType value to an Awaitable. Called when co_await is used with an AwaitType value...
MOUNTAIN_API bool_t Finished() const
Returns whether the Coroutine finished its execution.
std::coroutine_handle< promise_type > HandleType
The coroutine handle type.
Definition: coroutine.hpp:121
AwaitType awaitValue
The last co_await value.
Definition: coroutine.hpp:76
MOUNTAIN_API Guid GetId() const
Returns the Guid of this Coroutine.
MOUNTAIN_API void return_void()
Called when co_return is used in a Coroutine body. Empty implementation.
STL namespace.
std::function< Coroutine(Args...)> CoroutineFunction
Coroutine function prototype.
Definition: coroutine.hpp:217
MOUNTAIN_API void Destroy()
Destroys the Coroutine. It can&#39;t be resumed afterward.
Wrapper around C++20 Coroutines.
Definition: coroutine.hpp:61
MOUNTAIN_API std::suspend_always final_suspend() noexcept
Empty implementation.
MOUNTAIN_API bool_t Valid() const
Gets whether the Coroutine is valid, e.g. if it hasn&#39;t been default-initialized.
MOUNTAIN_API std::suspend_always initial_suspend()
Empty implementation.
MOUNTAIN_API void DestroySafe()
Safely destroys the Coroutine by first checking if Valid() is true.
MOUNTAIN_API std::suspend_always yield_value(nullptr_t)
Yields the coroutine using a nullptr value. The coroutine will be resumed on the next frame...
MOUNTAIN_API void unhandled_exception()
Logs the exception and rethrows it.
MOUNTAIN_API void ResumeSafe() const
Safely resumes the Coroutine by first checking if Valid() is true.
MOUNTAIN_API void Reset()
Resets the Coroutine.
Defines the Mountain::Guid class.
Stands for Global Unique Identifier, it represents a unique ID that&#39;s used to link pointers during se...
Definition: guid.hpp:17
MOUNTAIN_API Coroutine get_return_object()
Returns the object that will be returns to the caller of a CoroutineFunc.
MOUNTAIN_API void Resume() const
Resumes the Coroutine.
std::chrono::duration< double_t > AwaitType
Default duration type for Coroutine wait, equivalent to floating-point seconds.
Definition: coroutine.hpp:67
Promise type for C++20 coroutines.
Definition: coroutine.hpp:73
Contains all declarations of the Mountain Framework.
Definition: audio.hpp:22