From 84437dfbe44a78f7cd945cfefb6093dc0ead5c7e Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 13 Jun 2021 21:27:46 +0100 Subject: [PATCH] Alternative approach to thread-safe Application::quit Signed-off-by: falkTX --- dgl/src/Application.cpp | 2 +- dgl/src/ApplicationPrivateData.cpp | 28 +++++++++++++++++++++++++--- dgl/src/ApplicationPrivateData.hpp | 12 ++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/dgl/src/Application.cpp b/dgl/src/Application.cpp index 80d5957c..bd2c1969 100644 --- a/dgl/src/Application.cpp +++ b/dgl/src/Application.cpp @@ -50,7 +50,7 @@ void Application::quit() bool Application::isQuiting() const noexcept { - return pData->isQuitting; + return pData->isQuitting || pData->isQuittingInNextCycle; } void Application::addIdleCallback(IdleCallback* const callback) diff --git a/dgl/src/ApplicationPrivateData.cpp b/dgl/src/ApplicationPrivateData.cpp index 409085b2..c812a64e 100644 --- a/dgl/src/ApplicationPrivateData.cpp +++ b/dgl/src/ApplicationPrivateData.cpp @@ -25,6 +25,24 @@ START_NAMESPACE_DGL typedef std::list::reverse_iterator WindowListReverseIterator; +static ThreadHandle getCurrentThreadHandle() noexcept +{ +#ifdef DISTRHO_OS_WINDOWS + return GetCurrentThread(); +#else + return pthread_self(); +#endif +} + +static bool isThisMainThread(const ThreadHandle mainThreadHandle) noexcept +{ +#ifdef DISTRHO_OS_WINDOWS + return GetCurrentThread() == mainThreadHandle; // IsGUIThread ? +#else + return pthread_equal(getCurrentThreadHandle(), mainThreadHandle) != 0; +#endif +} + // -------------------------------------------------------------------------------------------------------------------- Application::PrivateData::PrivateData(const bool standalone) @@ -35,6 +53,7 @@ Application::PrivateData::PrivateData(const bool standalone) isQuittingInNextCycle(false), isStarting(true), visibleWindows(0), + mainThreadHandle(getCurrentThreadHandle()), windows(), idleCallbacks() { @@ -108,10 +127,13 @@ void Application::PrivateData::quit() { DISTRHO_SAFE_ASSERT_RETURN(isStandalone,); - if (! isQuittingInNextCycle) + if (! isThisMainThread(mainThreadHandle)) { - isQuittingInNextCycle = true; - return; + if (! isQuittingInNextCycle) + { + isQuittingInNextCycle = true; + return; + } } isQuitting = true; diff --git a/dgl/src/ApplicationPrivateData.hpp b/dgl/src/ApplicationPrivateData.hpp index 627f2a1f..b842227f 100644 --- a/dgl/src/ApplicationPrivateData.hpp +++ b/dgl/src/ApplicationPrivateData.hpp @@ -21,6 +21,15 @@ #include +#ifdef DISTRHO_OS_WINDOWS +# include +# include +typedef HANDLE ThreadHandle; +#else +# include +typedef pthread_t ThreadHandle; +#endif + typedef struct PuglWorldImpl PuglWorld; START_NAMESPACE_DGL @@ -49,6 +58,9 @@ struct Application::PrivateData { If 0->1, application is starting. If 1->0, application is quitting/stopping. */ uint visibleWindows; + /** Handle that identifies the main thread. Used to check if calls belong to current thread or not. */ + ThreadHandle mainThreadHandle; + /** List of windows for this application. Only used during `close`. */ std::list windows;