react-native-audio-api 0.11.0-nightly-6ba0571-20251210 → 0.11.0-nightly-c0ffb48-20251211

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,10 @@
1
1
  #pragma once
2
- #include <thread>
3
- #include <vector>
4
2
  #include <functional>
3
+ #include <memory>
4
+ #include <thread>
5
+ #include <utility>
5
6
  #include <variant>
7
+ #include <vector>
6
8
 
7
9
  #include <audioapi/utils/MoveOnlyFunction.hpp>
8
10
  #include <audioapi/utils/SpscChannel.hpp>
@@ -17,7 +19,9 @@ namespace audioapi {
17
19
  /// @note IMPORTANT: ThreadPool is not thread-safe and events should be scheduled from a single thread only.
18
20
  class ThreadPool {
19
21
  struct StopEvent {};
20
- struct TaskEvent { audioapi::move_only_function<void()> task; };
22
+ struct TaskEvent {
23
+ audioapi::move_only_function<void()> task;
24
+ };
21
25
  using Event = std::variant<TaskEvent, StopEvent>;
22
26
 
23
27
  struct Cntrl {
@@ -25,34 +29,51 @@ class ThreadPool {
25
29
  std::atomic<size_t> tasksScheduled{0};
26
30
  };
27
31
 
28
- using Sender = channels::spsc::Sender<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>;
29
- using Receiver = channels::spsc::Receiver<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>;
30
- public:
32
+ using Sender = channels::spsc::Sender<
33
+ Event,
34
+ channels::spsc::OverflowStrategy::WAIT_ON_FULL,
35
+ channels::spsc::WaitStrategy::ATOMIC_WAIT>;
36
+ using Receiver = channels::spsc::Receiver<
37
+ Event,
38
+ channels::spsc::OverflowStrategy::WAIT_ON_FULL,
39
+ channels::spsc::WaitStrategy::ATOMIC_WAIT>;
40
+
41
+ public:
31
42
  /// @brief Construct a new ThreadPool
32
43
  /// @param numThreads The number of worker threads to create
33
44
  /// @param loadBalancerQueueSize The size of the load balancer's queue
34
45
  /// @param workerQueueSize The size of each worker thread's queue
35
- ThreadPool(size_t numThreads, size_t loadBalancerQueueSize = 32, size_t workerQueueSize = 32) {
36
- auto [sender, receiver] = channels::spsc::channel<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>(loadBalancerQueueSize);
46
+ explicit ThreadPool(
47
+ size_t numThreads,
48
+ size_t loadBalancerQueueSize = 32,
49
+ size_t workerQueueSize = 32) {
50
+ auto [sender, receiver] = channels::spsc::channel<
51
+ Event,
52
+ channels::spsc::OverflowStrategy::WAIT_ON_FULL,
53
+ channels::spsc::WaitStrategy::ATOMIC_WAIT>(loadBalancerQueueSize);
37
54
  loadBalancerSender = std::move(sender);
38
55
  std::vector<Sender> workerSenders;
39
56
  workerSenders.reserve(numThreads);
40
57
  for (size_t i = 0; i < numThreads; ++i) {
41
- auto [workerSender, workerReceiver] = channels::spsc::channel<Event, channels::spsc::OverflowStrategy::WAIT_ON_FULL, channels::spsc::WaitStrategy::ATOMIC_WAIT>(workerQueueSize);
58
+ auto [workerSender, workerReceiver] = channels::spsc::channel<
59
+ Event,
60
+ channels::spsc::OverflowStrategy::WAIT_ON_FULL,
61
+ channels::spsc::WaitStrategy::ATOMIC_WAIT>(workerQueueSize);
42
62
  workers.emplace_back(&ThreadPool::workerThreadFunc, this, std::move(workerReceiver));
43
63
  workerSenders.emplace_back(std::move(workerSender));
44
64
  }
45
- loadBalancerThread = std::thread(&ThreadPool::loadBalancerThreadFunc, this, std::move(receiver), std::move(workerSenders));
65
+ loadBalancerThread = std::thread(
66
+ &ThreadPool::loadBalancerThreadFunc, this, std::move(receiver), std::move(workerSenders));
46
67
  controlBlock_ = std::make_unique<Cntrl>();
47
68
  }
48
- ThreadPool(const ThreadPool&) = delete;
49
- ThreadPool& operator=(const ThreadPool&) = delete;
50
- ThreadPool(ThreadPool&& other):
51
- loadBalancerThread(std::move(other.loadBalancerThread)),
52
- workers(std::move(other.workers)),
53
- loadBalancerSender(std::move(other.loadBalancerSender)),
54
- controlBlock_(std::move(other.controlBlock_)) {}
55
- ThreadPool& operator=(ThreadPool&& other) {
69
+ ThreadPool(const ThreadPool &) = delete;
70
+ ThreadPool &operator=(const ThreadPool &) = delete;
71
+ ThreadPool(ThreadPool &&other)
72
+ : loadBalancerThread(std::move(other.loadBalancerThread)),
73
+ workers(std::move(other.workers)),
74
+ loadBalancerSender(std::move(other.loadBalancerSender)),
75
+ controlBlock_(std::move(other.controlBlock_)) {}
76
+ ThreadPool &operator=(ThreadPool &&other) {
56
77
  if (this != &other) {
57
78
  loadBalancerThread = std::move(other.loadBalancerThread);
58
79
  workers = std::move(other.workers);
@@ -69,7 +90,7 @@ public:
69
90
  }
70
91
  loadBalancerSender.send(StopEvent{});
71
92
  loadBalancerThread.join();
72
- for (auto& worker : workers) {
93
+ for (auto &worker : workers) {
73
94
  worker.join();
74
95
  }
75
96
  }
@@ -84,14 +105,19 @@ public:
84
105
  /// @note The task should not throw exceptions, as they will not be caught.
85
106
  /// @note The task should end at some point, otherwise the thread pool will never be able to shut down.
86
107
  /// @note IMPORTANT: This function is not thread-safe and should be called from a single thread only.
87
- template<typename Func, typename ... Args, typename = std::enable_if_t<std::is_invocable_r_v<void, Func, Args...>>>
88
- void schedule(Func &&task, Args &&... args) noexcept {
108
+ template <
109
+ typename Func,
110
+ typename... Args,
111
+ typename = std::enable_if_t<std::is_invocable_r_v<void, Func, Args...>>>
112
+ void schedule(Func &&task, Args &&...args) noexcept {
89
113
  controlBlock_->tasksScheduled.fetch_add(1, std::memory_order_release);
90
114
 
91
115
  /// We know that lifetime of each worker thus spsc thus lambda is strongly bounded by ThreadPool lifetime
92
116
  /// so we can safely capture control block pointer unsafely here
93
117
  Cntrl *cntrl = controlBlock_.get();
94
- auto boundTask = [cntrl, f= std::forward<Func>(task), ...capturedArgs = std::forward<Args>(args)]() mutable {
118
+ auto boundTask = [cntrl,
119
+ f = std::forward<Func>(task),
120
+ ... capturedArgs = std::forward<Args>(args)]() mutable {
95
121
  f(std::forward<Args>(capturedArgs)...);
96
122
  size_t left = cntrl->tasksScheduled.fetch_sub(1, std::memory_order_acq_rel) - 1;
97
123
  if (left == 0) {
@@ -121,7 +147,7 @@ public:
121
147
  return;
122
148
  }
123
149
 
124
- private:
150
+ private:
125
151
  std::thread loadBalancerThread;
126
152
  std::vector<std::thread> workers;
127
153
  Sender loadBalancerSender;
@@ -135,9 +161,9 @@ private:
135
161
  /// We use [[unlikely]] and [[likely]] attributes to help the compiler optimize the branching.
136
162
  /// we expect most of the time to receive TaskEvent, and rarely StopEvent.
137
163
  /// and whenever we receive StopEvent we can burn some cycles as it will not be expected to execute fast.
138
- if (std::holds_alternative<StopEvent>(event)) [[ unlikely ]] {
164
+ if (std::holds_alternative<StopEvent>(event)) [[unlikely]] {
139
165
  break;
140
- } else if (std::holds_alternative<TaskEvent>(event)) [[ likely ]] {
166
+ } else if (std::holds_alternative<TaskEvent>(event)) [[likely]] {
141
167
  std::get<TaskEvent>(event).task();
142
168
  }
143
169
  }
@@ -152,15 +178,15 @@ private:
152
178
  /// We use [[unlikely]] and [[likely]] attributes to help the compiler optimize the branching.
153
179
  /// we expect most of the time to receive TaskEvent, and rarely StopEvent.
154
180
  /// and whenever we receive StopEvent we can burn some cycles as it will not be expected to execute fast.
155
- if (std::holds_alternative<StopEvent>(event)) [[ unlikely ]] {
181
+ if (std::holds_alternative<StopEvent>(event)) [[unlikely]] {
156
182
  // Propagate stop event to all workers
157
183
  for (size_t i = 0; i < localWorkerSenders.size(); ++i) {
158
184
  localWorkerSenders[i].send(StopEvent{});
159
185
  }
160
186
  break;
161
- } else if (std::holds_alternative<TaskEvent>(event)) [[ likely ]] {
187
+ } else if (std::holds_alternative<TaskEvent>(event)) [[likely]] {
162
188
  // Dispatch task to the next worker in round-robin fashion
163
- auto& taskEvent = std::get<TaskEvent>(event);
189
+ auto &taskEvent = std::get<TaskEvent>(event);
164
190
  localWorkerSenders[nextWorker].send(std::move(taskEvent));
165
191
  nextWorker = (nextWorker + 1) % localWorkerSenders.size();
166
192
  }
@@ -24,21 +24,16 @@ set(REACT_NATIVE_AUDIO_API_DIR "${ROOT}/node_modules/react-native-audio-api")
24
24
  file(GLOB_RECURSE RNAUDIOAPI_SRC
25
25
  CONFIGURE_DEPENDS
26
26
  "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/*.cpp"
27
- "${REACT_NATIVE_AUDIO_API_DIR}/android/src/main/cpp/audioapi/android/core/utils/AudioDecoder.cpp"
28
27
  )
29
28
 
30
29
  # exclude HostObjects from tests
31
30
  list(FILTER RNAUDIOAPI_SRC EXCLUDE REGEX ".*/audioapi/HostObjects/.*\\.cpp$")
31
+ # exclude worklet nodes
32
+ list(FILTER RNAUDIOAPI_SRC EXCLUDE REGEX ".*/Worklet.*Node\\.cpp$")
32
33
 
33
34
  list(REMOVE_ITEM RNAUDIOAPI_SRC
34
35
  "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/core/AudioContext.cpp"
35
- "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/core/effects/WorkletNode.cpp"
36
- "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp"
37
- "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp"
38
- "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/core/sources/StreamerNode.cpp"
39
- "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/core/sources/StreamerNode.h"
40
36
  "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp"
41
- "${REACT_NATIVE_AUDIO_API_DIR}/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h"
42
37
  )
43
38
 
44
39
  file(GLOB_RECURSE RNAUDIOAPI_LIBS
@@ -78,7 +73,6 @@ add_executable(
78
73
  ${test_src}
79
74
  )
80
75
 
81
- add_compile_definitions(AUDIO_API_TEST_SUITE)
82
76
  add_compile_definitions(RN_AUDIO_API_ENABLE_WORKLETS=0)
83
77
  add_compile_definitions(RN_AUDIO_API_TEST=1)
84
78
  add_compile_definitions(RN_AUDIO_API_FFMPEG_DISABLED=1)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-audio-api",
3
- "version": "0.11.0-nightly-6ba0571-20251210",
3
+ "version": "0.11.0-nightly-c0ffb48-20251211",
4
4
  "description": "react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification",
5
5
  "bin": {
6
6
  "setup-rn-audio-api-web": "./scripts/setup-rn-audio-api-web.js"
@@ -53,7 +53,7 @@
53
53
  "format:android:cpp": "find android/src/ -path android/src/main/cpp/audioapi/android/libs -iname \"*.h\" -o -iname \"*.cpp\" | xargs clang-format -i",
54
54
  "format:android:kotlin": "ktlint -F 'android/src/main/java/**/*.kt'",
55
55
  "format:ios": "find ios/audioapi/ios -iname \"*.h\" -o -iname \"*.m\" -o -iname \"*.mm\" | xargs clang-format -i",
56
- "format:common": "find common/cpp/ -path 'common/cpp/audioapi/libs' -prune -o -path 'common/cpp/audioapi/external' -prune -o -type f -iname \"*.h\" -print -o -type f -iname \"*.cpp\" -print | xargs clang-format -i",
56
+ "format:common": "find common/cpp/ -path 'common/cpp/audioapi/libs' -prune -o -path 'common/cpp/audioapi/external' -prune -o -type f -iname \"*.h\" -print -o -type f -iname \"*.cpp\" -o -type f -iname \"*.hpp\" -print | xargs clang-format -i",
57
57
  "build": "bob build",
58
58
  "create:package": "./scripts/create-package.sh",
59
59
  "prepack": "cp ../../README.md ./README.md",