Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2026 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #pragma once
23 :
24 : #include <cassert>
25 : #include <cstddef>
26 : #include <memory>
27 : #include <thread>
28 : #include <utility>
29 :
30 : #include "global/functional/inplace_function_mv.h"
31 :
32 : namespace muse::audio {
33 : class AudioWorkgroupTokenProvider;
34 :
35 : using ErasedAudioWorkgroupTokenProvider = muse::functional::MoveOnlyInplaceFunction<const AudioWorkgroupTokenProvider* (), 64>;
36 :
37 : class AudioWorkgroupToken
38 : {
39 : public:
40 48 : AudioWorkgroupToken() = default;
41 : AudioWorkgroupToken(const AudioWorkgroupToken&) = delete;
42 : AudioWorkgroupToken& operator=(const AudioWorkgroupToken&) = delete;
43 : AudioWorkgroupToken(AudioWorkgroupToken&& other) noexcept
44 : {
45 : moveFrom(std::move(other));
46 : }
47 :
48 : AudioWorkgroupToken& operator=(AudioWorkgroupToken&& other) noexcept
49 : {
50 : if (this != &other) {
51 : reset();
52 : moveFrom(std::move(other));
53 : }
54 :
55 : return *this;
56 : }
57 :
58 46 : ~AudioWorkgroupToken()
59 : {
60 46 : reset();
61 47 : }
62 :
63 : private:
64 : friend class AudioWorkGroup;
65 :
66 : explicit AudioWorkgroupToken(ErasedAudioWorkgroupTokenProvider provider)
67 : {
68 : setProvider(std::move(provider));
69 : }
70 :
71 : const AudioWorkgroupTokenProvider* provider() const
72 : {
73 : assertCurrentThread();
74 : return m_provider ? m_provider() : nullptr;
75 : }
76 :
77 : void setProvider(ErasedAudioWorkgroupTokenProvider workgroup)
78 : {
79 : reset();
80 : m_provider = std::move(workgroup);
81 : if (m_provider) {
82 : m_threadId = std::this_thread::get_id();
83 : }
84 : }
85 :
86 46 : void reset()
87 : {
88 46 : assertCurrentThread();
89 47 : m_provider = nullptr;
90 46 : m_threadId = {};
91 47 : }
92 :
93 : void moveFrom(AudioWorkgroupToken&& other) noexcept
94 : {
95 : other.assertCurrentThread();
96 : m_provider = std::move(other.m_provider);
97 : m_threadId = other.m_threadId;
98 : other.m_threadId = {};
99 : }
100 :
101 46 : void assertCurrentThread() const
102 : {
103 46 : assert((!m_provider || m_threadId == std::this_thread::get_id())
104 : && "AudioWorkgroupToken must be used on the thread that joined the audio workgroup");
105 47 : }
106 :
107 : ErasedAudioWorkgroupTokenProvider m_provider;
108 : std::thread::id m_threadId;
109 : };
110 :
111 : class AudioWorkgroupProvider;
112 :
113 : class AudioWorkGroup
114 : {
115 : public:
116 : AudioWorkGroup();
117 : AudioWorkGroup(const AudioWorkGroup&);
118 : AudioWorkGroup(AudioWorkGroup&&) noexcept;
119 : AudioWorkGroup& operator=(const AudioWorkGroup&);
120 : AudioWorkGroup& operator=(AudioWorkGroup&&) noexcept;
121 : ~AudioWorkGroup();
122 :
123 : bool join(AudioWorkgroupToken& token);
124 :
125 51 : const AudioWorkgroupProvider* getProvider() const { return m_provider.get(); }
126 :
127 : size_t getMaxParallelThreadCount() const;
128 :
129 : private:
130 : friend class AudioWorkgroupProvider;
131 : friend AudioWorkGroup makeAudioWorkgroup(void* opaqueHandle);
132 :
133 : explicit AudioWorkGroup(std::unique_ptr<AudioWorkgroupProvider> provider);
134 :
135 : static const AudioWorkgroupTokenProvider* providerFor(const AudioWorkgroupToken& token) { return token.provider(); }
136 : static void setProviderFor(AudioWorkgroupToken& token, ErasedAudioWorkgroupTokenProvider provider)
137 : {
138 : token.setProvider(std::move(provider));
139 : }
140 :
141 : static void resetProviderFor(AudioWorkgroupToken& token) { token.reset(); }
142 :
143 : std::unique_ptr<AudioWorkgroupProvider> m_provider;
144 : };
145 :
146 : AudioWorkGroup makeAudioWorkgroup(void* opaqueHandle);
147 : } // namespace muse::audio
|