libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
mediaiorequest.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <functional>
14#include <utility>
15#include <promeki/function.h>
16#include <promeki/namespace.h>
17#include <promeki/error.h>
18#include <promeki/eventloop.h>
20
21PROMEKI_NAMESPACE_BEGIN
22
85class MediaIORequest {
86 public:
88 using Callback = Function<void(Error)>;
89
97 MediaIORequest() = default;
98
107 explicit MediaIORequest(MediaIOCommand::Ptr cmd) : _cmd(std::move(cmd)) {}
108
117 static MediaIORequest resolved(Error err);
118
132 static MediaIORequest resolved(MediaIOCommand::Ptr cmd);
133
150 Error wait(unsigned int timeoutMs = 0);
151
156 bool isReady() const;
157
172 void then(Callback cb);
173
181 void cancel();
182
184 bool isCancelled() const;
185
195 MediaIOCommand::Ptr command() const { return _cmd; }
196
222 template <typename CmdT> const CmdT *commandAs() const {
223 if (_cmd.isNull()) return nullptr;
224 return static_cast<const CmdT *>(_cmd.ptr());
225 }
226
246 MediaIOStats stats() const { return _cmd.isValid() ? _cmd->stats : MediaIOStats(); }
247
249 bool isValid() const { return _cmd.isValid() || _hasOverride; }
250
251 private:
252 MediaIOCommand::Ptr _cmd;
253 Error _overrideError = Error::Invalid;
254 bool _hasOverride = false;
255 // Sentinel-path cancellation flag — when there is no
256 // command, cancel() has nothing to forward to, so the
257 // bit lives here. When _cmd is valid the cmd's own
258 // atomic flag is the source of truth and isCancelled
259 // ORs both.
260 bool _cancelledLocal = false;
261};
262
263inline MediaIORequest MediaIORequest::resolved(Error err) {
264 MediaIORequest r;
265 r._overrideError = err;
266 r._hasOverride = true;
267 return r;
268}
269
270inline MediaIORequest MediaIORequest::resolved(MediaIOCommand::Ptr cmd) {
271 if (cmd.isValid()) cmd.modify()->markCompleted();
272 return MediaIORequest(std::move(cmd));
273}
274
275inline Error MediaIORequest::wait(unsigned int timeoutMs) {
276 if (_hasOverride) return _overrideError;
277 if (_cmd.isNull()) return Error::Invalid;
278 const Error waitErr = _cmd.modify()->waitForCompletion(timeoutMs);
279 if (waitErr == Error::Timeout) return Error::Timeout;
280 return _cmd->result;
281}
282
283inline bool MediaIORequest::isReady() const {
284 if (_hasOverride) return true;
285 return _cmd.isValid() && _cmd->isCompleted();
286}
287
288inline void MediaIORequest::then(Callback cb) {
289 if (_hasOverride) {
290 // Sentinel path: fire immediately (marshal through
291 // the current loop when one is active so the
292 // callback observes the same thread semantics as
293 // the post-completion case).
294 EventLoop *loop = EventLoop::current();
295 Error err = _overrideError;
296 if (loop != nullptr) {
297 loop->postCallable([cb = std::move(cb), err]() mutable { cb(err); });
298 } else {
299 cb(err);
300 }
301 return;
302 }
303 if (_cmd.isNull()) return;
304 _cmd.modify()->setCompletionCallback(std::move(cb), EventLoop::current());
305}
306
307inline void MediaIORequest::cancel() {
308 _cancelledLocal = true;
309 if (_cmd.isValid()) _cmd.modify()->cancelled.setValue(true);
310}
311
312inline bool MediaIORequest::isCancelled() const {
313 if (_cancelledLocal) return true;
314 return _cmd.isValid() && _cmd->cancelled.value();
315}
316
317PROMEKI_NAMESPACE_END
318
319#endif // PROMEKI_ENABLE_PROAV