-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathCoroutineHelper.h
More file actions
148 lines (124 loc) · 3.47 KB
/
Copy pathCoroutineHelper.h
File metadata and controls
148 lines (124 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma once
#include <coroutine>
#include <functional>
#include <vector>
#include <optional>
#include <cassert>
#include <type_traits>
#include "LinkedListLib.hpp"
enum class YieldInstructionType
{
None,
WaitForFixedUpdate,
Null,
WaitForSeconds,
WaitForFrames,
WaitUntil,
WaitForSignal,
WaitForEndOfFrame,
OnRender
};
struct YieldInstruction
{
YieldInstructionType type = YieldInstructionType::None;
float timeRemaining = 0.0f;
int frameRemaining = 0;
std::function<bool()> condition;
bool* signal = nullptr;
friend YieldInstruction WaitForSeconds(float sec);
friend YieldInstruction WaitForFrames(int frames);
friend YieldInstruction WaitUntil(std::function<bool()> func);
friend YieldInstruction WaitForSignal(bool* signalFlag);
friend YieldInstruction WaitForFixedUpdate();
friend YieldInstruction WaitForEndOfFrame();
bool Tick(float deltaTime)
{
switch (type)
{
case YieldInstructionType::WaitForSeconds:
timeRemaining -= deltaTime;
return timeRemaining <= 0.0f;
case YieldInstructionType::WaitForFrames:
--frameRemaining;
return frameRemaining <= 0;
case YieldInstructionType::WaitUntil:
return condition && condition();
case YieldInstructionType::WaitForSignal:
return signal && *signal;
case YieldInstructionType::WaitForFixedUpdate:
case YieldInstructionType::WaitForEndOfFrame:
case YieldInstructionType::Null:
case YieldInstructionType::None:
case YieldInstructionType::OnRender:
return true; // 처리 큐 전환 후 1프레임 대기
default:
return true;
}
}
};
template<typename T = YieldInstruction>
struct Coroutine {
struct promise_type;
using handle_type = std::coroutine_handle<promise_type>;
struct promise_type
{
std::optional<T> current_value;
Coroutine get_return_object()
{
return Coroutine{ handle_type::from_promise(*this) };
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
std::suspend_always yield_value(T value)
{
current_value = std::move(value);
return {};
}
void return_void() {}
void unhandled_exception() { std::terminate(); }
};
handle_type handle;
explicit Coroutine(handle_type h) : handle(h) {}
Coroutine(const Coroutine&) = delete;
Coroutine(Coroutine&& other) noexcept : handle(other.handle) {
other.handle = nullptr;
}
~Coroutine()
{
if (handle)
handle.destroy();
}
Coroutine& operator=(const Coroutine&) = delete;
Coroutine& operator=(Coroutine&& other) noexcept
{
if (this != &other)
{
if (handle) handle.destroy();
handle = other.handle;
other.handle = nullptr;
}
return *this;
}
bool resume()
{
if (!handle.done())
handle.resume();
return !handle.done();
}
T& current() const
{
static T nullValue = T{};
if (handle.promise().current_value.has_value())
{
return handle.promise().current_value.value();
}
else
{
return nullValue;
}
}
bool is_done() const
{
return handle.done();
}
};