diff options
Diffstat (limited to 'src/server/Engine.hpp')
-rw-r--r-- | src/server/Engine.hpp | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/src/server/Engine.hpp b/src/server/Engine.hpp index 16699293..fc80d64b 100644 --- a/src/server/Engine.hpp +++ b/src/server/Engine.hpp @@ -17,9 +17,10 @@ #ifndef INGEN_ENGINE_ENGINE_HPP #define INGEN_ENGINE_ENGINE_HPP -#include <random> - #include <boost/utility.hpp> +#include <condition_variable> +#include <mutex> +#include <random> #include "ingen/EngineBase.hpp" #include "ingen/Interface.hpp" @@ -88,8 +89,27 @@ public: void set_driver(SPtr<Driver> driver); + /** Return the frame time to execute an event that arrived now. + * + * This aims to return a time one cycle from "now", so that events ideally + * have 1 cycle of latency with no jitter. + */ SampleCount event_time(); + /** Return the time this cycle began processing in microseconds. + * + * This value is comparable to the value returned by current_time(). + */ + inline uint64_t cycle_start_time(const RunContext& context) const { + return _cycle_start_time; + } + + /** Return the current time in microseconds. */ + uint64_t current_time(const RunContext& context) const; + + /** Reset the load statistics (when the expected DSP load changes). */ + void reset_load(); + /** Enqueue an event to be processed (non-realtime threads only). */ void enqueue_event(Event* ev, Event::Mode mode=Event::Mode::NORMAL); @@ -115,16 +135,53 @@ public: Worker* worker() const { return _worker; } Worker* sync_worker() const { return _sync_worker; } - RunContext& run_context() { return _run_context; } + RunContext& run_context() { return *_run_contexts[0]; } + + void locate(FrameTime s, SampleCount nframes); + void emit_notifications(FrameTime end); + bool pending_notifications(); + bool wait_for_tasks(); + void signal_tasks(); + Task* steal_task(unsigned start_thread); SPtr<Store> store() const; size_t event_queue_size() const; - bool atomic_bundles() const { return _atomic_bundles; } + size_t n_threads() const { return _run_contexts.size(); } + bool atomic_bundles() const { return _atomic_bundles; } private: Ingen::World* _world; + struct Load { + void update(uint64_t time, uint64_t available) { + const uint64_t load = time * 100 / available; + if (load < min) { + min = load; + changed = true; + } + if (load > max) { + max = load; + changed = true; + } + if (++n == 1) { + mean = load; + } else { + const float a = mean + ((float)load - mean) / (float)++n; + if (a != mean) { + changed = floorf(a) != floorf(mean); + mean = a; + } + } + } + + uint64_t min = std::numeric_limits<uint64_t>::max(); + uint64_t max = 0; + float mean = 0.0f; + uint64_t n = 0; + bool changed = false; + }; + BlockFactory* _block_factory; Broadcaster* _broadcaster; BufferFactory* _buffer_factory; @@ -144,12 +201,19 @@ private: Worker* _sync_worker; SocketListener* _listener; - RunContext _run_context; + std::vector<RunContext*> _run_contexts; + uint64_t _cycle_start_time; + Load _event_load; + Load _run_load; std::mt19937 _rand_engine; std::uniform_real_distribution<float> _uniform_dist; + std::condition_variable _tasks_available; + std::mutex _tasks_mutex; + bool _quit_flag; + bool _reset_load_flag; bool _direct_driver; bool _atomic_bundles; }; |