Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Sources/CSFBAudioEngine/Player/AudioPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
#import <deque>
#import <memory>
#import <mutex>
#if defined(__has_include) && __has_include(<stop_token>)
#import <stop_token>
#endif /* defined(__has_include) && __has_include(<stop_token>) */
#import <thread>
#import <vector>

Expand Down Expand Up @@ -67,12 +69,20 @@ class AudioPlayer final {
mutable CXXUnfairLock::UnfairLock queuedDecodersLock_;

/// Thread used for decoding
#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
std::jthread decodingThread_;
#else
std::thread decodingThread_;
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
/// Dispatch semaphore used for communication with the decoding thread
dispatch_semaphore_t decodingSemaphore_ {};

/// Thread used for event processing
#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
std::jthread eventThread_;
#else
std::thread eventThread_;
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
/// Dispatch semaphore used for communication with the event processing thread
dispatch_semaphore_t eventSemaphore_ {};

Expand Down Expand Up @@ -256,6 +266,12 @@ class AudioPlayer final {
unmuteAfterDequeue = 1u << 4,
/// Mismatch between rendering format and decoder processing format
formatMismatch = 1u << 5,
#if !(defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L)
/// The decoding thread should exit
stopDecodingThread = 1u << 6,
/// The event thread should exit
stopEventThread = 1u << 7,
#endif /* !(defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L) */
};

// MARK: - Decoding
Expand Down
44 changes: 42 additions & 2 deletions Sources/CSFBAudioEngine/Player/AudioPlayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,13 @@ bool PerformSeekIfRequired() noexcept

// Launch the decoding and event processing threads
try {
#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
decodingThread_ = std::jthread(std::bind_front(&SFB::AudioPlayer::ProcessDecoders, this));
eventThread_ = std::jthread(std::bind_front(&SFB::AudioPlayer::SequenceAndProcessEvents, this));
#else
decodingThread_ = std::thread(&SFB::AudioPlayer::ProcessDecoders, this);
eventThread_ = std::thread(&SFB::AudioPlayer::SequenceAndProcessEvents, this);
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
} catch(const std::exception& e) {
os_log_error(log_, "Unable to create thread: %{public}s", e.what());
throw;
Expand Down Expand Up @@ -454,26 +459,41 @@ bool PerformSeekIfRequired() noexcept

Stop();

#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
// Register a stop callback for the decoding thread
std::stop_callback decodingThreadStopCallback(decodingThread_.get_stop_token(), [this] {
dispatch_semaphore_signal(decodingSemaphore_);
});

// Issue a stop request to the decoding thread and wait for it to exit
decodingThread_.request_stop();
#else
// Stop the decoding thread
flags_.fetch_or(static_cast<unsigned int>(Flags::stopDecodingThread), std::memory_order_acq_rel);
dispatch_semaphore_signal(decodingSemaphore_);
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */

try {
decodingThread_.join();
} catch(const std::exception& e) {
os_log_error(log_, "Unable to join decoding thread: %{public}s", e.what());
}


#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
// Register a stop callback for the event processing thread
std::stop_callback eventThreadStopCallback(eventThread_.get_stop_token(), [this] {
dispatch_semaphore_signal(eventSemaphore_);
});

// Issue a stop request to the event processing thread and wait for it to exit
eventThread_.request_stop();
#else
// Stop the event processing thread
flags_.fetch_or(static_cast<unsigned int>(Flags::stopEventThread), std::memory_order_acq_rel);
dispatch_semaphore_signal(eventSemaphore_);
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */

try {
eventThread_.join();
} catch(const std::exception& e) {
Expand Down Expand Up @@ -978,7 +998,11 @@ bool PerformSeekIfRequired() noexcept

// MARK: - Decoding

#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
void SFB::AudioPlayer::ProcessDecoders(std::stop_token stoken) noexcept
#else
void SFB::AudioPlayer::ProcessDecoders() noexcept
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
{
pthread_setname_np("AudioPlayer.Decoding");
pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0);
Expand Down Expand Up @@ -1017,7 +1041,13 @@ bool PerformSeekIfRequired() noexcept
}

// Terminate the thread if requested after processing cancelations
if(stoken.stop_requested())
if(
#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
stoken.stop_requested()
#else
flags_.load(std::memory_order_acquire) & static_cast<unsigned int>(Flags::stopDecodingThread)
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
)
break;

// Process pending seeks
Expand Down Expand Up @@ -1344,14 +1374,24 @@ bool PerformSeekIfRequired() noexcept

// MARK: - Event Processing

#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
void SFB::AudioPlayer::SequenceAndProcessEvents(std::stop_token stoken) noexcept
#else
void SFB::AudioPlayer::SequenceAndProcessEvents() noexcept
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
{
pthread_setname_np("AudioPlayer.Events");
pthread_set_qos_class_self_np(QOS_CLASS_USER_INITIATED, 0);

os_log_debug(log_, "<AudioPlayer: %p> event processing thread starting", this);

while(!stoken.stop_requested()) {
while(
#if defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L
!stoken.stop_requested()
#else
!(flags_.load(std::memory_order_acquire) & static_cast<unsigned int>(Flags::stopEventThread))
#endif /* defined(__cpp_lib_jthread) && __cpp_lib_jthread >= 201911L */
) {
auto decodeEventHeader = decodeEventRingBuffer_.ReadValue<DecodingEventHeader>();
auto renderEventHeader = renderEventRingBuffer_.ReadValue<RenderingEventHeader>();

Expand Down