fixed newly arisen race cons (busywaits)

This commit is contained in:
Hane 2025-01-18 18:01:35 +01:00
commit 53f9506115
4 changed files with 59 additions and 11 deletions

View file

@ -48,8 +48,10 @@ HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSe
Session* newSession = new Session(this->eph->getEndpoint(), sessionControl); Session* newSession = new Session(this->eph->getEndpoint(), sessionControl);
SessionThreadParams tp = { .eph = this->eph, .session = newSession, .isDelete = false }; 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(); newSessionThread.detach();
while(wait);
} }
return S_OK; return S_OK;
@ -57,6 +59,7 @@ HRESULT EndpointNewSessionCallback::OnSessionCreated(IAudioSessionControl *NewSe
void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) { void EndpointNewSessionCallback::createSessionThread(SessionThreadParams params) {
params.eph->addSessionSendFront(params.session); params.eph->addSessionSendFront(params.session);
this->wait = false;
} }
EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){ EndpointVolumeCallback::EndpointVolumeCallback(Endpoint* ep){
@ -103,8 +106,10 @@ HRESULT EndpointVolumeCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify
for (int i = 0; i < pNotify->nChannels; i++) { for (int i = 0; i < pNotify->nChannels; i++) {
channelVolumes[i] = pNotify->afChannelVolumes[i]; channelVolumes[i] = pNotify->afChannelVolumes[i];
} }
wait = true;
std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes); std::thread updateVolumeThread(&EndpointVolumeCallback::updateVolumeInfo, this, paramCopy, channelVolumes);
updateVolumeThread.detach(); updateVolumeThread.detach();
while(wait);
return S_OK; return S_OK;
} }
@ -112,6 +117,9 @@ void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA new
//delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller; //delete osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller;
//osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.freeData4(); //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. //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 \ osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data1 \
= newVolume.guidEventContext.Data1; = newVolume.guidEventContext.Data1;
osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \ osh->getPlaybackEndpointHandlers().at(this->ep->getIndex())->getCallbackInfo()->caller.data2 \
@ -146,9 +154,15 @@ void EndpointVolumeCallback::updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA new
j++; j++;
} }
free(channelVolumes); free(channelVolumes);
osh->unlockEndpoints();
osh->handlersPlaybackMutex.unlock();
osh->handlersCaptureMutex.unlock();
wait = false;
} }
void EndpointVolumeCallback::reportFinished() {
this->wait = false;
}
EndpointSituationCallback::EndpointSituationCallback(Overseer* os){ EndpointSituationCallback::EndpointSituationCallback(Overseer* os){
this->os = os; this->os = os;
@ -235,18 +249,26 @@ HRESULT EndpointSituationCallback::OnDeviceStateChanged(LPCWSTR pwstrDeviceId, D
newState = EndpointState::ENDPOINT_UNPLUGGED; newState = EndpointState::ENDPOINT_UNPLUGGED;
break; break;
} }
isEpStateChanging = true;
std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh, std::thread newEndpointThread(&OverseerHandler::reviseEndpointShowing, osh,
endpointId, newState); endpointId, newState);
newEndpointThread.detach(); newEndpointThread.detach();
while(isEpStateChanging);
return S_OK; return S_OK;
} }
HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) { HRESULT EndpointSituationCallback::OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) {
isEpStateChanging = true;
std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId)); std::thread propertyThread(&Overseer::updateEndpointInfo, os, std::wstring(pwstrDeviceId));
propertyThread.detach(); propertyThread.detach();
while(isEpStateChanging);
return S_OK; return S_OK;
} }
void EndpointSituationCallback::reportFinishedStateChange() {
this->isEpStateChanging = false;
}
Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx) { Endpoint::Endpoint(IMMDevice* ep, IPolicyConfig7* policyConfig, uint64_t idx) {
this->endpoint = ep; this->endpoint = ep;
this->idx = idx; this->idx = idx;
@ -665,6 +687,10 @@ Endpoint* Overseer::addEndpoint(std::wstring endpointId, /* out */Flows* flow =
return endpoint; return endpoint;
} }
void Overseer::reportFinishedStateChange() {
epsc.reportFinishedStateChange();
}
Overseer::Overseer() : epsc(this) { Overseer::Overseer() : epsc(this) {
log_debugcpp("Initializing Overseer"); log_debugcpp("Initializing Overseer");
@ -718,6 +744,7 @@ void Overseer::updateEndpointInfo(std::wstring endpointId) {
} }
} }
playbackMutex.unlock(); playbackMutex.unlock();
epsc.reportFinishedStateChange();
} }
Overseer::~Overseer(){ Overseer::~Overseer(){

View file

@ -119,11 +119,13 @@ class EndpointVolumeCallback : public IAudioEndpointVolumeCallback {
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update); HRESULT OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA update);
void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes); void updateVolumeInfo(AUDIO_VOLUME_NOTIFICATION_DATA newVolume, float* channelVolumes);
void reportFinished();
//~EndpointVolumeCallback(); //~EndpointVolumeCallback();
private: private:
ULONG ref = 1; ULONG ref = 1;
Endpoint* ep; Endpoint* ep;
bool wait = false;
}; };
class EndpointSituationCallback : public IMMNotificationClient { class EndpointSituationCallback : public IMMNotificationClient {
@ -137,10 +139,11 @@ class EndpointSituationCallback : public IMMNotificationClient {
HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId); HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId);
HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState); HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState);
HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key); HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key);
void reportFinishedStateChange();
private: private:
ULONG ref = 1; ULONG ref = 1;
Overseer* os; Overseer* os;
bool isEpStateChanging = false;
}; };
class Overseer { class Overseer {
@ -157,6 +160,8 @@ class Overseer {
void createEndpoints(Flows flow); void createEndpoints(Flows flow);
Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow); Endpoint* addEndpoint(std::wstring endpointId, /* out */ Flows* flow);
void reportFinishedStateChange();
std::mutex playbackMutex; std::mutex playbackMutex;
std::mutex captureMutex; std::mutex captureMutex;
//void setEndpointStatusCallback(); //void setEndpointStatusCallback();
@ -196,9 +201,10 @@ class EndpointNewSessionCallback : public IAudioSessionNotification {
ULONG Release(); ULONG Release();
HRESULT QueryInterface(REFIID riid, VOID **ppvInterface); HRESULT QueryInterface(REFIID riid, VOID **ppvInterface);
HRESULT OnSessionCreated(IAudioSessionControl *NewSession); HRESULT OnSessionCreated(IAudioSessionControl *NewSession);
static void createSessionThread(SessionThreadParams params); void createSessionThread(SessionThreadParams params);
private: private:
bool wait = false;
ULONG ref = 1; ULONG ref = 1;
EndpointHandler *eph; EndpointHandler *eph;

View file

@ -348,6 +348,10 @@ EndpointHandler* OverseerHandler::addEndpoint(std::wstring endpointId, /* out */
return newEph; return newEph;
} }
void OverseerHandler::reportFinishedStateChange() {
os->reportFinishedStateChange();
}
NGuid OverseerHandler::getGuid() { NGuid OverseerHandler::getGuid() {
return this->os->getGuid(); return this->os->getGuid();
} }
@ -397,24 +401,26 @@ void OverseerHandler::reviseEndpointShowing(std::wstring endpointId, EndpointSta
//debug //debug
Flows flow; Flows flow;
if (!eph) { if (!eph) {
if (state ^ EndpointState::ENDPOINT_ACTIVE) return; if (state ^ EndpointState::ENDPOINT_ACTIVE) goto end;
//flow = Flows::FLOW_CAPTURE; //flow = Flows::FLOW_CAPTURE;
eph = osh->addEndpoint(endpointId, &flow); eph = osh->addEndpoint(endpointId, &flow);
} else } else
flow = eph->getFlow(); flow = eph->getFlow();
//todo: mic done but disabled. Tab-kun will come... //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) { if (eph && EndpointState::ENDPOINT_ACTIVE & state) {
this->addEndpointWidget(eph); this->addEndpointWidget(eph);
} else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE) { } else if (eph && eph->getFrontVisibilityState() == EndpointState::ENDPOINT_ACTIVE) {
this->removeEndpointWidget(eph->getFrontVisibilityIndex()); this->removeEndpointWidget(eph->getFrontVisibilityIndex());
} }
end:
handlersPlaybackMutex.unlock(); handlersPlaybackMutex.unlock();
handlersCaptureMutex.unlock(); handlersCaptureMutex.unlock();
os->playbackMutex.unlock(); os->playbackMutex.unlock();
os->captureMutex.unlock(); os->captureMutex.unlock();
os->reportFinishedStateChange();
return; return;
} }
@ -430,3 +436,13 @@ void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> ephs){
this->playbackEndpointHandlers = ephs; this->playbackEndpointHandlers = ephs;
} }
void OverseerHandler::lockEndpoints() {
os->playbackMutex.lock();
os->captureMutex.lock();
}
void OverseerHandler::unlockEndpoints() {
os->playbackMutex.unlock();
os->captureMutex.unlock();
}

View file

@ -139,14 +139,13 @@ public:
uint64_t getCaptureEndpointsCount(); uint64_t getCaptureEndpointsCount();
void createEndpointHandlers(); void createEndpointHandlers();
EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow); EndpointHandler* addEndpoint(std::wstring endpointId, Flows *flow);
void reportFinishedStateChange();
NGuid getGuid(); NGuid getGuid();
std::mutex handlersPlaybackMutex; std::mutex handlersPlaybackMutex;
std::mutex handlersCaptureMutex; std::mutex handlersCaptureMutex;
/* void lockEndpoints();
* void setSessionVolumeCallback(std::function<void(float)> changeSessionVolume); void unlockEndpoints();
* void setSessionVolume(float newValue, );
*/
private: private:
Overseer *os; Overseer *os;