libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
clock.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cassert>
14#include <promeki/atomic.h>
15#include <promeki/namespace.h>
16#include <promeki/clockdomain.h>
17#include <promeki/duration.h>
18#include <promeki/error.h>
20#include <promeki/mutex.h>
21#include <promeki/result.h>
22#include <promeki/sharedptr.h>
23#include <promeki/uniqueptr.h>
24
25PROMEKI_NAMESPACE_BEGIN
26
47struct ClockJitter {
49 Duration minError;
50
52 Duration maxError;
53
55 Duration span() const { return maxError - minError; }
56
58 bool isSymmetric() const { return minError.nanoseconds() == -maxError.nanoseconds(); }
59};
60
83class ClockFilter {
84 public:
86 using UPtr = UniquePtr<ClockFilter>;
87
88 virtual ~ClockFilter() = default;
89
95 virtual int64_t filter(int64_t rawNs) = 0;
96};
97
110enum class ClockPauseMode {
111 CannotPause,
112 PausesRawKeepsRunning,
113 PausesRawStops
114};
115
154class Clock {
155 public:
166 using Ptr = SharedPtr<Clock, /*CopyOnWrite=*/false, Clock>;
167
179 Clock(const ClockDomain &domain, const Duration &fixedOffset = Duration::zero(),
180 ClockPauseMode pauseMode = ClockPauseMode::CannotPause, ClockFilter *filter = nullptr);
181
183 virtual ~Clock();
184
185 Clock(const Clock &) = delete;
186 Clock &operator=(const Clock &) = delete;
187 Clock(Clock &&) = delete;
188 Clock &operator=(Clock &&) = delete;
189
190 // ---- Identity / self-description ----
191
193 ClockDomain domain() const { return _domain; }
194
196 ClockPauseMode pauseMode() const { return _pauseMode; }
197
199 bool canPause() const { return _pauseMode != ClockPauseMode::CannotPause; }
200
205 virtual int64_t resolutionNs() const = 0;
206
211 virtual ClockJitter jitter() const = 0;
212
217 virtual double rateRatio() const { return 1.0; }
218
219 // ---- Managed readings ----
220
233 Result<MediaTimeStamp> now() const;
234
242 Result<int64_t> nowNs() const;
243
244 // ---- Offsets ----
245
247 Duration fixedOffset() const;
248
258 void setFixedOffset(const Duration &offset);
259
260 // ---- Pause ----
261
263 bool isPaused() const;
264
279 Error setPause(bool paused);
280
281 // ---- Wait primitives ----
282
304 Error sleepUntil(const MediaTimeStamp &deadline) const;
305
306 // Native shared-pointer plumbing. Clock is not copyable;
307 // _promeki_clone asserts if the SharedPtr ever tries to
308 // detach, which should be impossible for CopyOnWrite=false.
310 RefCount _promeki_refct;
311
316 virtual Clock *_promeki_clone() const {
317 assert(false && "Clock is not copyable");
318 return nullptr;
319 }
320
321 protected:
331 virtual Result<int64_t> raw() const = 0;
332
347 virtual Error sleepUntilNs(int64_t targetNs) const = 0;
348
361 virtual Error onPause(bool paused);
362
363 private:
364 Result<int64_t> applyFilter(int64_t raw) const;
365
366 ClockDomain _domain;
367 ClockPauseMode _pauseMode;
368 ClockFilter::UPtr _filter;
369
370 mutable Mutex _mutex;
371 int64_t _fixedOffsetNs;
372 int64_t _pausedOffsetNs;
373 int64_t _frozenFilteredNs;
374 bool _paused;
375
376 mutable Atomic<int64_t> _lastNowNs;
377};
378
389class WallClock : public Clock {
390 public:
392 WallClock();
393
394 int64_t resolutionNs() const override;
395 ClockJitter jitter() const override;
396
397 protected:
398 Result<int64_t> raw() const override;
399 Error sleepUntilNs(int64_t targetNs) const override;
400};
401
402PROMEKI_NAMESPACE_END
403
404#endif // PROMEKI_ENABLE_CORE