OpenShot Audio Library | OpenShotAudio 0.4.0
juce_AudioWorkgroup.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
27
28class WorkgroupToken::TokenProvider
29{
30public:
31 explicit TokenProvider (os_workgroup_t wg)
32 : workgroup (wg), attached (attach (wg, token)) {}
33
34 ~TokenProvider()
35 {
36 if (attached)
37 detach (workgroup, token);
38 }
39
40 TokenProvider (const TokenProvider&) = delete;
41 TokenProvider (TokenProvider&& other) noexcept
42 : workgroup (std::exchange (other.workgroup, os_workgroup_t{})),
43 token (std::exchange (other.token, os_workgroup_join_token_s{})),
44 attached (std::exchange (other.attached, false)) {}
45
46 TokenProvider& operator= (const TokenProvider&) = delete;
47 TokenProvider& operator= (TokenProvider&& other) noexcept
48 {
49 TokenProvider { std::move (other) }.swap (*this);
50 return *this;
51 }
52
53 bool isAttached() const { return attached; }
54 os_workgroup_t getHandle() const { return workgroup; }
55
56private:
57 static void detach (os_workgroup_t wg, os_workgroup_join_token_s token)
58 {
59 if (@available (macos 11.0, ios 14.0, *))
60 os_workgroup_leave (wg, &token);
61 }
62
63 static bool attach (os_workgroup_t wg, os_workgroup_join_token_s& tokenOut)
64 {
65 if (@available (macos 11.0, ios 14.0, *))
66 {
67 if (wg != nullptr && os_workgroup_join (wg, &tokenOut) == 0)
68 return true;
69 }
70
71 return false;
72 }
73
74 void swap (TokenProvider& other) noexcept
75 {
76 std::swap (other.workgroup, workgroup);
77 std::swap (other.token, token);
78 std::swap (other.attached, attached);
79 }
80
81 os_workgroup_t workgroup;
82 os_workgroup_join_token_s token;
83 bool attached;
84};
85
86class AudioWorkgroup::WorkgroupProvider
87{
88public:
89 explicit WorkgroupProvider (os_workgroup_t ptr) : handle { ptr } {}
90
91 void join (WorkgroupToken& token) const
92 {
93 if (const auto* tokenProvider = token.getTokenProvider())
94 if (tokenProvider->isAttached() && tokenProvider->getHandle() == handle.get())
95 return;
96
97 // Explicit reset before constructing the new workgroup to ensure that the old workgroup
98 // is left before the new one is joined.
99 token.reset();
100
101 if (handle.get() != nullptr)
102 token = WorkgroupToken { [provider = WorkgroupToken::TokenProvider { handle.get() }] { return &provider; } };
103 }
104
105 static os_workgroup_t getWorkgroup (const AudioWorkgroup& wg)
106 {
107 if (auto* provider = wg.getWorkgroupProvider())
108 return provider->handle.get();
109
110 return nullptr;
111 }
112
113private:
114 struct ScopedWorkgroupRetainer
115 {
116 ScopedWorkgroupRetainer (os_workgroup_t wg) : handle { wg }
117 {
118 if (handle != nullptr)
119 os_retain (handle);
120 }
121
122 ~ScopedWorkgroupRetainer()
123 {
124 if (handle != nullptr)
125 os_release (handle);
126 }
127
128 ScopedWorkgroupRetainer (const ScopedWorkgroupRetainer& other)
129 : ScopedWorkgroupRetainer { other.handle } {}
130
131 ScopedWorkgroupRetainer& operator= (const ScopedWorkgroupRetainer& other)
132 {
133 ScopedWorkgroupRetainer { other }.swap (*this);
134 return *this;
135 }
136
137 ScopedWorkgroupRetainer (ScopedWorkgroupRetainer&& other) noexcept
138 {
139 swap (other);
140 }
141
142 ScopedWorkgroupRetainer& operator= (ScopedWorkgroupRetainer&& other) noexcept
143 {
144 swap (other);
145 return *this;
146 }
147
148 void swap (ScopedWorkgroupRetainer& other) noexcept
149 {
150 std::swap (handle, other.handle);
151 }
152
153 os_workgroup_t get() const noexcept { return handle; }
154
155 private:
156 os_workgroup_t handle { nullptr };
157 };
158
159 ScopedWorkgroupRetainer handle;
160};
161
162#else
163
164class WorkgroupToken::TokenProvider {};
165
166class AudioWorkgroup::WorkgroupProvider
167{
168public:
169 explicit WorkgroupProvider() = default;
170
171 void join (WorkgroupToken& t) const { t.reset(); }
172
173 static void* getWorkgroup (const AudioWorkgroup&) { return nullptr; }
174};
175
176#endif
177
179 : erased ([&]() -> Erased
180 {
181 if (auto* p = other.getWorkgroupProvider())
182 return [provider = *p] { return &provider; };
183
184 return nullptr;
185 }()) {}
186
188{
189 return WorkgroupProvider::getWorkgroup (*this) == WorkgroupProvider::getWorkgroup (other);
190}
191
193{
194 #if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
195
196 if (const auto* p = getWorkgroupProvider())
197 {
198 p->join (token);
199 return;
200 }
201
202 #endif
203
204 token.reset();
205}
206
208{
209 #if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
210
211 if (@available (macos 11.0, ios 14.0, *))
212 {
213 if (auto wg = WorkgroupProvider::getWorkgroup (*this))
214 return (size_t) os_workgroup_max_parallel_threads (wg, nullptr);
215 }
216
217 #endif
218
219 return 0;
220}
221
222AudioWorkgroup::operator bool() const { return WorkgroupProvider::getWorkgroup (*this) != nullptr; }
223
224#if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
225
226AudioWorkgroup makeRealAudioWorkgroup (os_workgroup_t handle)
227{
228 if (handle == nullptr)
229 return AudioWorkgroup{};
230
231 return AudioWorkgroup { [provider = AudioWorkgroup::WorkgroupProvider { handle }] { return &provider; } };
232}
233
234#endif
235
236} // namespace juce
AudioWorkgroup & operator=(AudioWorkgroup &&)=default
size_t getMaxParallelThreadCount() const
AudioWorkgroup()=default
bool operator==(const AudioWorkgroup &other) const
void join(WorkgroupToken &token) const
FixedSizeFunction< 64, const WorkgroupProvider *()> Erased
WorkgroupToken & operator=(const WorkgroupToken &)=delete