Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
graph_scheduler.h
1// SPDX-FileCopyrightText: © 2019-2021, 2024 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3/*
4 * This file incorporates work covered by the following copyright and
5 * permission notice:
6 *
7 * ---
8 *
9 * Copyright (C) 2017, 2019 Robin Gareus <robin@gareus.org>
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 *
24 * ---
25 */
26
27#pragma once
28
29#include "dsp/graph_node.h"
30#include "utils/mpmc_queue.h"
31#include "utils/rt_thread_id.h"
32
33#include <boost/unordered/concurrent_flat_set.hpp>
34#include <juce_wrapper.h>
35#include <moodycamel/lightweightsemaphore.h>
36
37namespace zrythm::dsp::graph
38{
39
40class GraphThread;
41
59{
60 friend class GraphThread;
61 using GraphThreadPtr = std::unique_ptr<GraphThread>;
62 static constexpr int MAX_GRAPH_THREADS = 128;
63
64public:
68 using RunOnMainThreadFunc = std::function<void (std::function<void ()>)>;
69
80 RunOnMainThreadFunc run_on_main_thread_func,
81 units::sample_rate_t sample_rate,
82 nframes_t max_block_length,
83 bool realtime_threads = true,
84 std::optional<juce::AudioWorkgroup> thread_workgroup = std::nullopt);
86 Z_DISABLE_COPY_MOVE (GraphScheduler); // copy/move don't make sense here
87
104 GraphNodeCollection &&nodes,
105 units::sample_rate_t sample_rate,
106 nframes_t max_block_length);
107
116 void start_threads (std::optional<int> num_threads = std::nullopt);
117
122
123 auto &get_nodes () { return graph_nodes_; }
124
134 EngineProcessTimeInfo time_nfo,
135 nframes_t remaining_preroll_frames,
136 const dsp::ITransport &transport,
137 const dsp::TempoMap &tempo_map);
138
142 bool contains_thread (RTThreadId::IdType thread_id);
143
144 auto get_time_nfo () const { return time_nfo_; }
145 auto get_remaining_preroll_frames () const
146 {
147 return remaining_preroll_frames_;
148 }
149
157 {
158 assert (current_transport_.has_value ());
159 return current_transport_->get ();
160 }
161
169 {
170 assert (current_tempo_map_.has_value ());
171 return current_tempo_map_->get ();
172 }
173
174private:
178 [[gnu::hot]] void trigger_node (GraphNode &node);
179
184 void prepare_nodes_for_processing ();
185
190 void release_node_resources ();
191
192private:
193 boost::concurrent_flat_set<GraphThreadPtr> threads_;
194 GraphThreadPtr main_thread_;
195
199 EngineProcessTimeInfo time_nfo_;
200
204 std::optional<std::reference_wrapper<const dsp::ITransport>> current_transport_;
205
209 std::optional<std::reference_wrapper<const dsp::TempoMap>> current_tempo_map_;
210
214 nframes_t remaining_preroll_frames_{};
215
217 moodycamel::LightweightSemaphore callback_start_sem_{ 0 };
218 moodycamel::LightweightSemaphore callback_done_sem_{ 0 };
219
221 std::atomic<int> idle_thread_cnt_ = 0;
222
224 // This is not a std::counting_semaphore due to issues on MSVC/Windows.
225 moodycamel::LightweightSemaphore trigger_sem_{ 0 };
226
228 MPMCQueue<GraphNode *> trigger_queue_;
229
233 GraphNodeCollection graph_nodes_;
234
236 std::atomic<int> terminal_refcnt_ = 0;
237
242 std::optional<juce::Thread::RealtimeOptions> realtime_thread_options_;
243
245 std::optional<juce::AudioWorkgroup> thread_workgroup_;
246
247 units::sample_rate_t sample_rate_;
248 nframes_t max_block_length_;
249
250 RunOnMainThreadFunc run_on_main_thread_func_;
251};
252
253} // namespace zrythm::dsp::graph
Interface for transport.
Definition itransport.h:17
Manages the collection of graph nodes.
Definition graph_node.h:303
Represents a node in a DSP graph.
Definition graph_node.h:131
GraphScheduler(RunOnMainThreadFunc run_on_main_thread_func, units::sample_rate_t sample_rate, nframes_t max_block_length, bool realtime_threads=true, std::optional< juce::AudioWorkgroup > thread_workgroup=std::nullopt)
Construct a new Graph Scheduler.
bool contains_thread(RTThreadId::IdType thread_id)
Returns whether the given thread is one of the graph threads.
void rechain_from_node_collection(GraphNodeCollection &&nodes, units::sample_rate_t sample_rate, nframes_t max_block_length)
Steals the nodes from the given collection and prepares for processing.
auto & get_transport_for_this_cycle() const
Returns the ITransport instance to be used in this cycle.
void terminate_threads()
Tell all threads to terminate.
void start_threads(std::optional< int > num_threads=std::nullopt)
Starts the threads that will be processing the graph.
auto & get_tempo_map_for_this_cycle() const
Returns the TempoMap instance to be used in this cycle.
std::function< void(std::function< void()>)> RunOnMainThreadFunc
Request for a function to run on the main thread (blocking).
void run_cycle(EngineProcessTimeInfo time_nfo, nframes_t remaining_preroll_frames, const dsp::ITransport &transport, const dsp::TempoMap &tempo_map)
To be called repeatedly by a system audio callback thread.
Processing graph thread.
uint32_t nframes_t
Frame count.
Definition types.h:58
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition types.h:133