mirror of
https://github.com/CalcProgrammer1/OpenRGB.git
synced 2026-05-24 22:45:55 -04:00
Add another thread in NetworkClient for handling ProfileManager requests outside of the main listener thread, to avoid deadlocking the waiting receivers
This commit is contained in:
@@ -242,6 +242,16 @@ void NetworkClient::StartClient()
|
||||
\*-----------------------------------------------------*/
|
||||
ConnectionThread = new std::thread(&NetworkClient::ConnectionThreadFunction, this);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Start the ProfileManager listen thread |
|
||||
\*-----------------------------------------------------*/
|
||||
profilemanager_thread = new NetworkClientListenerThread;
|
||||
|
||||
profilemanager_thread->id = 0;
|
||||
profilemanager_thread->index = 0;
|
||||
profilemanager_thread->online = true;
|
||||
profilemanager_thread->thread = new std::thread(&NetworkClient::ProfileManagerListenThread, this, profilemanager_thread);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Client info has changed, call the callbacks |
|
||||
\*-----------------------------------------------------*/
|
||||
@@ -278,6 +288,18 @@ void NetworkClient::StopClient()
|
||||
ListenThread = nullptr;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Close the ProfileManager listen thread |
|
||||
\*-----------------------------------------------------*/
|
||||
if(profilemanager_thread->thread)
|
||||
{
|
||||
profilemanager_thread->online = false;
|
||||
profilemanager_thread->thread->join();
|
||||
delete profilemanager_thread->thread;
|
||||
profilemanager_thread->thread = nullptr;
|
||||
delete profilemanager_thread;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Close the connection thread |
|
||||
\*-----------------------------------------------------*/
|
||||
@@ -1027,6 +1049,51 @@ void NetworkClient::SignalNetworkClientUpdate(unsigned int update_reason)
|
||||
NetworkClientCallbackMutex.unlock();
|
||||
}
|
||||
|
||||
void NetworkClient::ProfileManagerListenThread(NetworkClientListenerThread* this_thread)
|
||||
{
|
||||
while(this_thread->online == true)
|
||||
{
|
||||
std::unique_lock<std::mutex> start_lock(this_thread->start_mutex);
|
||||
this_thread->start_cv.wait(start_lock);
|
||||
|
||||
while(this_thread->queue.size() > 0)
|
||||
{
|
||||
NetworkClientListenerThreadQueueEntry queue_entry;
|
||||
|
||||
this_thread->queue_mutex.lock();
|
||||
queue_entry = this_thread->queue.front();
|
||||
this_thread->queue.pop();
|
||||
this_thread->queue_mutex.unlock();
|
||||
|
||||
switch(queue_entry.header.pkt_id)
|
||||
{
|
||||
case NET_PACKET_ID_PROFILEMANAGER_ACTIVE_PROFILE_CHANGED:
|
||||
ProcessRequest_ProfileManager_ActiveProfileChanged(queue_entry.header.pkt_size, queue_entry.data);
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_LOADED:
|
||||
ProcessRequest_ProfileManager_ProfileLoaded(queue_entry.header.pkt_size, queue_entry.data);
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_ABOUT_TO_LOAD:
|
||||
ProcessRequest_ProfileManager_ProfileAboutToLoad();
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST:
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_LIST_UPDATED:
|
||||
ProcessRequest_ProfileManager_ProfileListUpdated(queue_entry.header.pkt_size, queue_entry.data);
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_RGBCONTROLLER_SIGNALUPDATE:
|
||||
ProcessRequest_RGBController_SignalUpdate(queue_entry.header.pkt_size, queue_entry.data, queue_entry.header.pkt_dev_id);
|
||||
break;
|
||||
}
|
||||
|
||||
delete[] queue_entry.data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Client thread functions |
|
||||
\*---------------------------------------------------------*/
|
||||
@@ -1426,25 +1493,29 @@ void NetworkClient::ListenThreadFunction()
|
||||
}
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_PROFILEMANAGER_ACTIVE_PROFILE_CHANGED:
|
||||
ProcessRequest_ProfileManager_ActiveProfileChanged(header.pkt_size, data);
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_LOADED:
|
||||
ProcessRequest_ProfileManager_ProfileLoaded(header.pkt_size, data);
|
||||
break;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| ProfileManager functions are handled in a |
|
||||
| separate thread, queue the messages |
|
||||
\*-------------------------------------------------*/
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_ABOUT_TO_LOAD:
|
||||
ProcessRequest_ProfileManager_ProfileAboutToLoad();
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_PROFILEMANAGER_ACTIVE_PROFILE_CHANGED:
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_LOADED:
|
||||
case NET_PACKET_ID_PROFILEMANAGER_GET_PROFILE_LIST:
|
||||
case NET_PACKET_ID_PROFILEMANAGER_PROFILE_LIST_UPDATED:
|
||||
ProcessRequest_ProfileManager_ProfileListUpdated(header.pkt_size, data);
|
||||
break;
|
||||
|
||||
case NET_PACKET_ID_RGBCONTROLLER_SIGNALUPDATE:
|
||||
ProcessRequest_RGBController_SignalUpdate(header.pkt_size, data, header.pkt_dev_id);
|
||||
{
|
||||
profilemanager_thread->queue_mutex.lock();
|
||||
|
||||
NetworkClientListenerThreadQueueEntry new_entry;
|
||||
new_entry.data = data;
|
||||
new_entry.header = header;
|
||||
|
||||
profilemanager_thread->queue.push(new_entry);
|
||||
profilemanager_thread->queue_mutex.unlock();
|
||||
profilemanager_thread->start_cv.notify_all();
|
||||
|
||||
delete_data = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include "i2c_smbus.h"
|
||||
@@ -44,7 +45,23 @@ enum
|
||||
NETWORKCLIENT_UPDATE_REASON_PROFILEMANAGER_ACTIVE_PROFILE_CHANGED, /* Active profile changed */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NetPacketHeader header;
|
||||
unsigned char* data;
|
||||
} NetworkClientListenerThreadQueueEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int id;
|
||||
unsigned int index;
|
||||
std::queue<NetworkClientListenerThreadQueueEntry> queue;
|
||||
std::mutex queue_mutex;
|
||||
std::mutex start_mutex;
|
||||
std::condition_variable start_cv;
|
||||
std::thread* thread;
|
||||
std::atomic<bool> online;
|
||||
} NetworkClientListenerThread;
|
||||
|
||||
class NetworkClient
|
||||
{
|
||||
@@ -206,6 +223,7 @@ private:
|
||||
std::condition_variable connection_cv;
|
||||
std::thread * ConnectionThread;
|
||||
std::thread * ListenThread;
|
||||
NetworkClientListenerThread* profilemanager_thread;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Callbacks |
|
||||
@@ -237,6 +255,7 @@ private:
|
||||
\*-----------------------------------------------------*/
|
||||
void ConnectionThreadFunction();
|
||||
void ListenThreadFunction();
|
||||
void ProfileManagerListenThread(NetworkClientListenerThread* this_thread);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Private Client functions |
|
||||
|
||||
@@ -1066,7 +1066,7 @@ void NetworkServer::ControllerListenThread(NetworkServerControllerThread* this_t
|
||||
|
||||
void NetworkServer::ProfileManagerListenThread(NetworkServerControllerThread* this_thread)
|
||||
{
|
||||
while(this_thread->online == true)
|
||||
while(this_thread->online == true)
|
||||
{
|
||||
std::unique_lock<std::mutex> start_lock(this_thread->start_mutex);
|
||||
this_thread->start_cv.wait(start_lock);
|
||||
|
||||
Reference in New Issue
Block a user