From 53f9506115b2b7f1df5122b8bc07eb3013059274 Mon Sep 17 00:00:00 2001 From: Hane Date: Sat, 18 Jan 2025 18:01:35 +0100 Subject: [PATCH] fixed newly arisen race cons (busywaits) --- src/back/backlasses.cpp | 31 +++++++++++++++++++++++++++++-- src/back/backlasses.h | 10 ++++++++-- src/cont/contclasses.cpp | 20 ++++++++++++++++++-- src/cont/contclasses.h | 9 ++++----- 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/back/backlasses.cpp b/src/back/backlasses.cpp index 4b64b8e..cead61f 100644 --- a/src/back/backlasses.cpp +++ b/src/back/backlasses.cpp @@ -48,8 +48,10 @@ HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSe Session* newSession = new Session(this->eph->getEndpoint(), sessionControl); SessionThreadParams tp = { .eph = this->eph, .session = newSession, .isDelete = false }; - std::thread newSessionThread(EndpointNewSessionCallback::createSessionThread, tp); + wait = true; + std::thread newSessionThread(&EndpointNewSessionCallback::createSessionThread, this, tp); newSessionThread.detach(); + while(wait); } return S_OK; @@ -57,6 +59,7 @@ HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSe void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) { params.eph->addSessionSendFront(params.session); + this->wait = false; } EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){ @@ -103,8 +106,10 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify for (int i = 0; i < pNotify->nChannels; i++) { channelVolumes[i] = pNotify->afChannelVolumes[i]; } + wait = true; std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes); updateVolumeThread.detach(); + while(wait); return S_OK; } @@ -112,6 +117,9 @@ void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA new //delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller; //osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.freeData4(); //Could've made a function or = override to hide this within Nguid, but back in cont = bad. + osh->handlersPlaybackMutex.lock(); + osh->handlersCaptureMutex.lock(); + osh->lockEndpoints(); osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \ = newVolume.guidEventContext.Data1; osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \ @@ -146,9 +154,15 @@ void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA new j++; } free(channelVolumes); + osh->unlockEndpoints(); + osh->handlersPlaybackMutex.unlock(); + osh->handlersCaptureMutex.unlock(); + wait = false; } - +void EndpointVolumeCallback::reportFinished() { + this->wait = false; +} EndpointSituationCallback::EndpointSituationCallback(Overseer* os){ this->os = os; @@ -235,18 +249,26 @@ HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, D newState = EndpointState::ENDPOINT_UNPLUGGED; break; } + isEpStateChanging = true; std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh, endpointId, newState); newEndpointThread.detach(); + while(isEpStateChanging); return S_OK; } HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { + isEpStateChanging = true; std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId)); propertyThread.detach(); + while(isEpStateChanging); return S_OK; } +void EndpointSituationCallback::reportFinishedStateChange() { + this->isEpStateChanging = false; +} + Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx) { this->endpoint = ep; this->idx = idx; @@ -665,6 +687,10 @@ Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow = return endpoint; } +void Overseer::reportFinishedStateChange() { + epsc.reportFinishedStateChange(); +} + Overseer::Overseer() : epsc(this) { log_debugcpp("Initializing Overseer"); @@ -718,6 +744,7 @@ void Overseer::updateEndpointInfo(std::wstring endpointId) { } } playbackMutex.unlock(); + epsc.reportFinishedStateChange(); } Overseer::~Overseer(){ diff --git a/src/back/backlasses.h b/src/back/backlasses.h index 4fdf888..9f79924 100644 --- a/src/back/backlasses.h +++ b/src/back/backlasses.h @@ -119,11 +119,13 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback { HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update); void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes); + void reportFinished(); //~EndpointVolumeCallback(); private: ULONG ref = 1; Endpoint* ep; + bool wait = false; }; class EndpointSituationCallback : public IMMNotificationClient { @@ -137,10 +139,11 @@ class EndpointSituationCallback : public IMMNotificationClient { HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId); HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState); HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key); - + void reportFinishedStateChange(); private: ULONG ref = 1; Overseer* os; + bool isEpStateChanging = false; }; class Overseer { @@ -156,6 +159,8 @@ class Overseer { void createEndpoints(Flows flow); Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow); + + void reportFinishedStateChange(); std::mutex playbackMutex; std::mutex captureMutex; @@ -196,9 +201,10 @@ class EndpointNewSessionCallback : public IAudioSessionNotification { ULONG Release(); HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); HRESULT OnSessionCreated(IAudioSessionControl *NewSession); - static void createSessionThread(SessionThreadParams params); + void createSessionThread(SessionThreadParams params); private: + bool wait = false; ULONG ref = 1; EndpointHandler *eph; diff --git a/src/cont/contclasses.cpp b/src/cont/contclasses.cpp index 3cfa3da..27ae4a6 100644 --- a/src/cont/contclasses.cpp +++ b/src/cont/contclasses.cpp @@ -348,6 +348,10 @@ EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */ return newEph; } +void OverseerHandler::reportFinishedStateChange() { + os->reportFinishedStateChange(); +} + NGuid OverseerHandler::getGuid() { return this->os->getGuid(); } @@ -397,24 +401,26 @@ void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointSta //debug Flows flow; if (!eph) { - if (state ^ EndpointState::ENDPOINT_ACTIVE) return; + if (state ^ EndpointState::ENDPOINT_ACTIVE) goto end; //flow = Flows::FLOW_CAPTURE; eph = osh->addEndpoint(endpointId, &flow); } else flow = eph->getFlow(); //todo: mic done but disabled. Tab-kun will come... - if (flow == Flows::FLOW_CAPTURE) return; + if (flow == Flows::FLOW_CAPTURE) goto end; if (eph && EndpointState::ENDPOINT_ACTIVE & state) { this->addEndpointWidget(eph); } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE) { this->removeEndpointWidget(eph->getFrontVisibilityIndex()); } + end: handlersPlaybackMutex.unlock(); handlersCaptureMutex.unlock(); os->playbackMutex.unlock(); os->captureMutex.unlock(); + os->reportFinishedStateChange(); return; } @@ -430,3 +436,13 @@ void OverseerHandler::setEndpointHandlers(std::vector ephs){ this->playbackEndpointHandlers = ephs; } +void OverseerHandler::lockEndpoints() { + os->playbackMutex.lock(); + os->captureMutex.lock(); +} + +void OverseerHandler::unlockEndpoints() { + os->playbackMutex.unlock(); + os->captureMutex.unlock(); +} + diff --git a/src/cont/contclasses.h b/src/cont/contclasses.h index 91d225b..2034986 100644 --- a/src/cont/contclasses.h +++ b/src/cont/contclasses.h @@ -138,15 +138,14 @@ public: uint64_t getPlaybackEndpointsCount(); uint64_t getCaptureEndpointsCount(); void createEndpointHandlers(); - EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); + EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); + void reportFinishedStateChange(); NGuid getGuid(); std::mutex handlersPlaybackMutex; std::mutex handlersCaptureMutex; - /* - * void setSessionVolumeCallback(std::function changeSessionVolume); - * void setSessionVolume(float newValue, ); - */ + void lockEndpoints(); + void unlockEndpoints(); private: Overseer *os;