Make hyprctl thread safe

This commit is contained in:
vaxerski 2022-04-21 22:00:03 +02:00
parent 304b93a4f6
commit 883d389bc2
3 changed files with 63 additions and 13 deletions

View file

@ -111,6 +111,60 @@ std::string dispatchKeyword(std::string in) {
return retval; return retval;
} }
void HyprCtl::tickHyprCtl() {
if (!requestMade)
return;
std::string reply = "";
try {
if (request == "monitors")
reply = monitorsRequest();
else if (request == "workspaces")
reply = workspacesRequest();
else if (request == "clients")
reply = clientsRequest();
else if (request == "activewindow")
reply = activeWindowRequest();
else if (request == "layers")
reply = layersRequest();
else if (request.find("dispatch") == 0)
reply = dispatchRequest(request);
else if (request.find("keyword") == 0)
reply = dispatchKeyword(request);
} catch (std::exception& e) {
Debug::log(ERR, "Error in request: %s", e.what());
reply = "Err: " + std::string(e.what());
}
request = reply;
requestMade = false;
requestReady = true;
}
std::string getRequestFromThread(std::string rq) {
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
HyprCtl::request = rq;
HyprCtl::requestMade = true;
while (!HyprCtl::requestReady) {
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
HyprCtl::requestReady = false;
HyprCtl::requestMade = false;
std::string toReturn = HyprCtl::request;
HyprCtl::request = "";
return toReturn;
}
void HyprCtl::startHyprCtlSocket() { void HyprCtl::startHyprCtlSocket() {
std::thread([&]() { std::thread([&]() {
uint16_t connectPort = 9187; uint16_t connectPort = 9187;
@ -164,19 +218,7 @@ void HyprCtl::startHyprCtlSocket() {
std::string request(readBuffer); std::string request(readBuffer);
std::string reply = ""; std::string reply = getRequestFromThread(request);
try {
if (request == "monitors") reply = monitorsRequest();
else if (request == "workspaces") reply = workspacesRequest();
else if (request == "clients") reply = clientsRequest();
else if (request == "activewindow") reply = activeWindowRequest();
else if (request == "layers") reply = layersRequest();
else if (request.find("dispatch") == 0) reply = dispatchRequest(request);
else if (request.find("keyword") == 0) reply = dispatchKeyword(request);
} catch (std::exception& e) {
Debug::log(ERR, "Error in request: %s", e.what());
reply = "Err: " + std::string(e.what());
}
write(ACCEPTEDCONNECTION, reply.c_str(), reply.length()); write(ACCEPTEDCONNECTION, reply.c_str(), reply.length());

View file

@ -8,5 +8,10 @@ namespace HyprCtl {
void startHyprCtlSocket(); void startHyprCtlSocket();
void tickHyprCtl(); void tickHyprCtl();
// very simple thread-safe request method
inline bool requestMade = false;
inline bool requestReady = false;
inline std::string request = "";
inline std::ifstream requestStream; inline std::ifstream requestStream;
}; };

View file

@ -3,6 +3,7 @@
#include "../managers/InputManager.hpp" #include "../managers/InputManager.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
#include "Events.hpp" #include "Events.hpp"
#include "../debug/HyprCtl.hpp"
// --------------------------------------------------------- // // --------------------------------------------------------- //
// __ __ ____ _ _ _____ _______ ____ _____ _____ // // __ __ ____ _ _ _____ _______ ____ _____ _____ //
@ -133,6 +134,8 @@ void Events::listener_monitorFrame(void* owner, void* data) {
g_pAnimationManager->tick(); g_pAnimationManager->tick();
g_pCompositor->cleanupWindows(); g_pCompositor->cleanupWindows();
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
if (g_pConfigManager->m_bWantsMonitorReload) if (g_pConfigManager->m_bWantsMonitorReload)