The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
5.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. #if JUCE_MAC || JUCE_IOS
  18. #include "../native/juce_AudioWorkgroup_mac.h"
  19. #endif
  20. namespace juce
  21. {
  22. #if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
  23. class WorkgroupToken::TokenProvider
  24. {
  25. public:
  26. explicit TokenProvider (os_workgroup_t wg)
  27. : workgroup (wg), attached (attach (wg, token)) {}
  28. ~TokenProvider()
  29. {
  30. if (attached)
  31. detach (workgroup, token);
  32. }
  33. TokenProvider (const TokenProvider&) = delete;
  34. TokenProvider (TokenProvider&& other) noexcept
  35. : workgroup (std::exchange (other.workgroup, os_workgroup_t{})),
  36. token (std::exchange (other.token, os_workgroup_join_token_s{})),
  37. attached (std::exchange (other.attached, false)) {}
  38. TokenProvider& operator= (const TokenProvider&) = delete;
  39. TokenProvider& operator= (TokenProvider&& other) noexcept
  40. {
  41. TokenProvider { std::move (other) }.swap (*this);
  42. return *this;
  43. }
  44. bool isAttached() const { return attached; }
  45. os_workgroup_t getHandle() const { return workgroup; }
  46. private:
  47. static void detach (os_workgroup_t wg, os_workgroup_join_token_s token)
  48. {
  49. if (@available (macos 11.0, ios 14.0, *))
  50. {
  51. os_workgroup_leave (wg, &token);
  52. os_release (wg);
  53. }
  54. }
  55. static bool attach (os_workgroup_t wg, os_workgroup_join_token_s& tokenOut)
  56. {
  57. if (@available (macos 11.0, ios 14.0, *))
  58. {
  59. if (wg != nullptr && os_workgroup_join (wg, &tokenOut) == 0)
  60. {
  61. os_retain (wg);
  62. return true;
  63. }
  64. }
  65. return false;
  66. }
  67. void swap (TokenProvider& other) noexcept
  68. {
  69. std::swap (other.workgroup, workgroup);
  70. std::swap (other.token, token);
  71. std::swap (other.attached, attached);
  72. }
  73. os_workgroup_t workgroup;
  74. os_workgroup_join_token_s token;
  75. bool attached;
  76. };
  77. class AudioWorkgroup::WorkgroupProvider
  78. {
  79. public:
  80. explicit WorkgroupProvider (os_workgroup_t ptr) : handle (ptr) {}
  81. WorkgroupProvider clone() const
  82. {
  83. if (handle == nullptr)
  84. return WorkgroupProvider { nullptr };
  85. os_retain (handle.get());
  86. return WorkgroupProvider { handle.get() };
  87. }
  88. void join (WorkgroupToken& token) const
  89. {
  90. if (const auto* tokenProvider = token.getTokenProvider())
  91. if (tokenProvider->isAttached() && tokenProvider->getHandle() == handle.get())
  92. return;
  93. // Explicit reset before constructing the new workgroup to ensure that the old workgroup
  94. // is left before the new one is joined.
  95. token.reset();
  96. if (handle != nullptr)
  97. token = WorkgroupToken { [provider = WorkgroupToken::TokenProvider { handle.get() }] { return &provider; } };
  98. }
  99. static os_workgroup_t getWorkgroup (const AudioWorkgroup& wg)
  100. {
  101. if (auto* p = wg.getWorkgroupProvider())
  102. return p->handle.get();
  103. return nullptr;
  104. }
  105. private:
  106. struct Release
  107. {
  108. void operator() (os_workgroup_t wg) const
  109. {
  110. if (wg != nullptr)
  111. os_release (wg);
  112. }
  113. };
  114. std::unique_ptr<std::remove_pointer_t<os_workgroup_t>, Release> handle;
  115. };
  116. #else
  117. class WorkgroupToken::TokenProvider {};
  118. class AudioWorkgroup::WorkgroupProvider
  119. {
  120. public:
  121. explicit WorkgroupProvider() = default;
  122. WorkgroupProvider clone() const { return WorkgroupProvider{}; }
  123. void join (WorkgroupToken& t) const { t.reset(); }
  124. static void* getWorkgroup (const AudioWorkgroup&) { return nullptr; }
  125. };
  126. #endif
  127. AudioWorkgroup::AudioWorkgroup (const AudioWorkgroup& other)
  128. : erased ([&]() -> Erased
  129. {
  130. if (auto* p = other.getWorkgroupProvider())
  131. return [provider = p->clone()] { return &provider; };
  132. return nullptr;
  133. }()) {}
  134. bool AudioWorkgroup::operator== (const AudioWorkgroup& other) const
  135. {
  136. return WorkgroupProvider::getWorkgroup (*this) == WorkgroupProvider::getWorkgroup (other);
  137. }
  138. void AudioWorkgroup::join (WorkgroupToken& token) const
  139. {
  140. #if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
  141. if (const auto* p = getWorkgroupProvider())
  142. {
  143. p->join (token);
  144. return;
  145. }
  146. #endif
  147. token.reset();
  148. }
  149. AudioWorkgroup::operator bool() const { return WorkgroupProvider::getWorkgroup (*this) != nullptr; }
  150. #if JUCE_AUDIOWORKGROUP_TYPES_AVAILABLE
  151. AudioWorkgroup makeRealAudioWorkgroup (os_workgroup_t handle)
  152. {
  153. if (handle == nullptr)
  154. return AudioWorkgroup{};
  155. return AudioWorkgroup { [provider = AudioWorkgroup::WorkgroupProvider { handle }] { return &provider; } };
  156. }
  157. #endif
  158. } // namespace juce