Skip to content

Commit

Permalink
Prevent audio thread from starving UI thread from CSoundGen::m_csAPULock
Browse files Browse the repository at this point in the history
  • Loading branch information
nyanpasu64 committed Dec 21, 2023
1 parent 6f85855 commit e2feee0
Showing 1 changed file with 19 additions and 0 deletions.
19 changes: 19 additions & 0 deletions Source/SoundGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,17 @@ class CSoundGen : IAudioCallback
// Thread synchronization
private:
mutable std::mutex m_csAPULock; // // //
/// Acquired whenever waiting for m_csAPULock.
///
/// This ensures that if the audio thread holds m_csAPULock,
/// and the UI thread is waiting for m_csAPULock (while holding m_waitingForApuLock),
/// the audio thread cannot release and reacquire m_csAPULock (starving the UI thread of access).
///
/// Instead the audio thread blocks on m_waitingForApuLock
/// until the UI thread acquires m_csAPULock and releases m_waitingForApuLock.
/// Then the audio thread must wait for the UI thread to release m_csAPULock.
mutable std::mutex m_waitingForApuLock;

mutable std::mutex m_csVisualizerWndLock;

// Handles
Expand Down Expand Up @@ -515,10 +526,18 @@ class CSoundGen : IAudioCallback

public:
std::unique_lock<std::mutex> Lock() {
auto waiting = std::unique_lock(m_waitingForApuLock);

// Unlocks `waiting`.
return std::unique_lock<std::mutex>(m_csAPULock);
}

std::optional<std::unique_lock<std::mutex>> TryLock() {
auto waiting = std::unique_lock(m_waitingForApuLock, std::defer_lock);
if (!waiting.try_lock()) {
return {};
}

std::optional out = std::unique_lock<std::mutex>(m_csAPULock, std::defer_lock);
if (!out->try_lock()) {
out = {};
Expand Down

0 comments on commit e2feee0

Please sign in to comment.