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
132 EngineProcessTimeInfo time_nfo,
133 nframes_t remaining_preroll_frames,
134 const dsp::ITransport &transport);
135
139 bool contains_thread (RTThreadId::IdType thread_id);
140
141 auto get_time_nfo () const { return time_nfo_; }
142 auto get_remaining_preroll_frames () const
143 {
144 return remaining_preroll_frames_;
145 }
146
154 {
155 assert (current_transport_.has_value ());
156 return current_transport_->get ();
157 }
158
159private:
163 [[gnu::hot]] void trigger_node (GraphNode &node);
164
169 void prepare_nodes_for_processing ();
170
175 void release_node_resources ();
176
177private:
178 boost::concurrent_flat_set<GraphThreadPtr> threads_;
179 GraphThreadPtr main_thread_;
180
184 EngineProcessTimeInfo time_nfo_;
185
189 std::optional<std::reference_wrapper<const dsp::ITransport>> current_transport_;
190
194 nframes_t remaining_preroll_frames_{};
195
197 moodycamel::LightweightSemaphore callback_start_sem_{ 0 };
198 moodycamel::LightweightSemaphore callback_done_sem_{ 0 };
199
201 std::atomic<int> idle_thread_cnt_ = 0;
202
204 // This is not a std::counting_semaphore due to issues on MSVC/Windows.
205 moodycamel::LightweightSemaphore trigger_sem_{ 0 };
206
208 MPMCQueue<GraphNode *> trigger_queue_;
209
213 GraphNodeCollection graph_nodes_;
214
216 std::atomic<int> terminal_refcnt_ = 0;
217
222 std::optional<juce::Thread::RealtimeOptions> realtime_thread_options_;
223
225 std::optional<juce::AudioWorkgroup> thread_workgroup_;
226
227 units::sample_rate_t sample_rate_;
228 nframes_t max_block_length_;
229
230 RunOnMainThreadFunc run_on_main_thread_func_;
231};
232
233} // namespace zrythm::dsp::graph
Interface for transport.
Definition itransport.h:17
Manages the collection of graph nodes.
Definition graph_node.h:298
Represents a node in a DSP graph.
Definition graph_node.h:129
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 run_cycle(EngineProcessTimeInfo time_nfo, nframes_t remaining_preroll_frames, const dsp::ITransport &transport)
To be called repeatedly by a system audio callback thread.
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.
std::function< void(std::function< void()>)> RunOnMainThreadFunc
Request for a function to run on the main thread (blocking).
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