Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/dpf/distrho/extra/Runner.hpp @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
1 /* | |
2 * DISTRHO Plugin Framework (DPF) | |
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com> | |
4 * | |
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with | |
6 * or without fee is hereby granted, provided that the above copyright notice and this | |
7 * permission notice appear in all copies. | |
8 * | |
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #ifndef DISTRHO_RUNNER_HPP_INCLUDED | |
18 #define DISTRHO_RUNNER_HPP_INCLUDED | |
19 | |
20 #include "../DistrhoUtils.hpp" | |
21 | |
22 #ifndef DISTRHO_OS_WASM | |
23 # include "Thread.hpp" | |
24 #else | |
25 # include "String.hpp" | |
26 # include <emscripten/html5.h> | |
27 #endif | |
28 | |
29 START_NAMESPACE_DISTRHO | |
30 | |
31 #ifdef DISTRHO_RUNNER_INDIRECT_WASM_CALLS | |
32 long d_emscripten_set_interval(void (*)(void*), double, void*); | |
33 void d_emscripten_clear_interval(long); | |
34 #else | |
35 # define d_emscripten_set_interval emscripten_set_interval | |
36 # define d_emscripten_clear_interval emscripten_clear_interval | |
37 #endif | |
38 | |
39 // ------------------------------------------------------------------------------------------------------------------- | |
40 // Runner class | |
41 | |
42 /** | |
43 Runner class for DPF. | |
44 | |
45 This is a handy class that handles "idle" time in either background or main thread, | |
46 whichever is more suitable to the target platform. | |
47 Typically background threads on desktop platforms, main thread on web. | |
48 | |
49 A single function is expected to be implemented by subclasses, | |
50 which directly allows it to stop the runner by returning false. | |
51 | |
52 You can use it for quick operations that do not need to be handled in the main thread if possible. | |
53 The target is to spread out execution over many runs, instead of spending a lot of time on a single task. | |
54 */ | |
55 class Runner | |
56 { | |
57 protected: | |
58 /* | |
59 * Constructor. | |
60 */ | |
61 Runner(const char* const runnerName = nullptr) noexcept | |
62 #ifndef DISTRHO_OS_WASM | |
63 : fRunnerThread(this, runnerName), | |
64 fTimeInterval(0) | |
65 #else | |
66 : fRunnerName(runnerName), | |
67 fIntervalId(0) | |
68 #endif | |
69 { | |
70 } | |
71 | |
72 /* | |
73 * Destructor. | |
74 */ | |
75 virtual ~Runner() /*noexcept*/ | |
76 { | |
77 DISTRHO_SAFE_ASSERT(! isRunnerActive()); | |
78 | |
79 stopRunner(); | |
80 } | |
81 | |
82 /* | |
83 * Virtual function to be implemented by the subclass. | |
84 * Return true to keep running, false to stop execution. | |
85 */ | |
86 virtual bool run() = 0; | |
87 | |
88 /* | |
89 * Check if the runner should stop. | |
90 * To be called from inside the runner to know if a stop request has been made. | |
91 */ | |
92 bool shouldRunnerStop() const noexcept | |
93 { | |
94 #ifndef DISTRHO_OS_WASM | |
95 return fRunnerThread.shouldThreadExit(); | |
96 #else | |
97 return fIntervalId == 0; | |
98 #endif | |
99 } | |
100 | |
101 // --------------------------------------------------------------------------------------------------------------- | |
102 | |
103 public: | |
104 /* | |
105 * Check if the runner is active. | |
106 */ | |
107 bool isRunnerActive() noexcept | |
108 { | |
109 #ifndef DISTRHO_OS_WASM | |
110 return fRunnerThread.isThreadRunning(); | |
111 #else | |
112 return fIntervalId != 0; | |
113 #endif | |
114 } | |
115 | |
116 /* | |
117 * Start the thread. | |
118 */ | |
119 bool startRunner(const uint timeIntervalMilliseconds = 0) noexcept | |
120 { | |
121 #ifndef DISTRHO_OS_WASM | |
122 DISTRHO_SAFE_ASSERT_RETURN(!fRunnerThread.isThreadRunning(), false); | |
123 fTimeInterval = timeIntervalMilliseconds; | |
124 return fRunnerThread.startThread(); | |
125 #else | |
126 DISTRHO_SAFE_ASSERT_RETURN(fIntervalId == 0, false); | |
127 fIntervalId = d_emscripten_set_interval(_entryPoint, timeIntervalMilliseconds, this); | |
128 return true; | |
129 #endif | |
130 } | |
131 | |
132 /* | |
133 * Stop the runner. | |
134 * This will signal the runner to stop if active, and wait until it finishes. | |
135 */ | |
136 bool stopRunner() noexcept | |
137 { | |
138 #ifndef DISTRHO_OS_WASM | |
139 return fRunnerThread.stopThread(-1); | |
140 #else | |
141 signalRunnerShouldStop(); | |
142 return true; | |
143 #endif | |
144 } | |
145 | |
146 /* | |
147 * Tell the runner to stop as soon as possible. | |
148 */ | |
149 void signalRunnerShouldStop() noexcept | |
150 { | |
151 #ifndef DISTRHO_OS_WASM | |
152 fRunnerThread.signalThreadShouldExit(); | |
153 #else | |
154 if (fIntervalId != 0) | |
155 { | |
156 d_emscripten_clear_interval(fIntervalId); | |
157 fIntervalId = 0; | |
158 } | |
159 #endif | |
160 } | |
161 | |
162 // --------------------------------------------------------------------------------------------------------------- | |
163 | |
164 /* | |
165 * Returns the name of the runner. | |
166 * This is the name that gets set in the constructor. | |
167 */ | |
168 const String& getRunnerName() const noexcept | |
169 { | |
170 #ifndef DISTRHO_OS_WASM | |
171 return fRunnerThread.getThreadName(); | |
172 #else | |
173 return fRunnerName; | |
174 #endif | |
175 } | |
176 | |
177 // --------------------------------------------------------------------------------------------------------------- | |
178 | |
179 private: | |
180 #ifndef DISTRHO_OS_WASM | |
181 class RunnerThread : public Thread | |
182 { | |
183 Runner* const runner; | |
184 | |
185 public: | |
186 RunnerThread(Runner* const r, const char* const rn) | |
187 : Thread(rn), | |
188 runner(r) {} | |
189 | |
190 protected: | |
191 void run() override | |
192 { | |
193 const uint timeInterval = runner->fTimeInterval; | |
194 | |
195 while (!shouldThreadExit()) | |
196 { | |
197 bool stillRunning = false; | |
198 | |
199 try { | |
200 stillRunning = runner->run(); | |
201 } catch(...) {} | |
202 | |
203 if (stillRunning && !shouldThreadExit()) | |
204 { | |
205 if (timeInterval != 0) | |
206 d_msleep(timeInterval); | |
207 | |
208 // FIXME | |
209 // pthread_yield(); | |
210 continue; | |
211 } | |
212 | |
213 break; | |
214 } | |
215 } | |
216 } fRunnerThread; | |
217 | |
218 uint fTimeInterval; | |
219 #else | |
220 const String fRunnerName; | |
221 long fIntervalId; | |
222 | |
223 void _runEntryPoint() noexcept | |
224 { | |
225 bool stillRunning = false; | |
226 | |
227 try { | |
228 stillRunning = run(); | |
229 } catch(...) {} | |
230 | |
231 if (fIntervalId != 0 && !stillRunning) | |
232 { | |
233 d_emscripten_clear_interval(fIntervalId); | |
234 fIntervalId = 0; | |
235 } | |
236 } | |
237 | |
238 static void _entryPoint(void* const userData) noexcept | |
239 { | |
240 static_cast<Runner*>(userData)->_runEntryPoint(); | |
241 } | |
242 #endif | |
243 | |
244 DISTRHO_DECLARE_NON_COPYABLE(Runner) | |
245 }; | |
246 | |
247 // ------------------------------------------------------------------------------------------------------------------- | |
248 | |
249 END_NAMESPACE_DISTRHO | |
250 | |
251 #endif // DISTRHO_RUNNER_HPP_INCLUDED |