mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
121 lines
2.1 KiB
C++
121 lines
2.1 KiB
C++
#include "CtrlCore.h"
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
|
|
namespace Upp {
|
|
|
|
static StaticMutex sGLock;
|
|
|
|
// #define DELAY_WATCH 1000 _DBG_
|
|
|
|
static thread_local int sGLockLevel = 0;
|
|
|
|
void EnterGuiMutex()
|
|
{
|
|
LLOG(">EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread());
|
|
if(sGLockLevel++ == 0) {
|
|
#if DELAY_WATCH
|
|
for(int i = 0; i < DELAY_WATCH; i++) {
|
|
if(sGLock.TryEnter()) return;
|
|
Sleep(1);
|
|
}
|
|
Panic("Long timer procedure detected!");
|
|
#else
|
|
sGLock.Enter();
|
|
#endif
|
|
}
|
|
LLOG("EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread());
|
|
}
|
|
|
|
void EnterGuiMutex(int n)
|
|
{
|
|
LLOG(">EnterGuiMutex: " << n << ' ' << sGLockLevel << ' ' << IsMainThread());
|
|
if(n > 0) {
|
|
if(sGLockLevel == 0)
|
|
sGLock.Enter();
|
|
sGLockLevel += n;
|
|
}
|
|
LLOG("EnterGuiMutex " << sGLockLevel << ' ' << IsMainThread());
|
|
}
|
|
|
|
bool TryEnterGuiMutex()
|
|
{
|
|
if(sGLockLevel || sGLock.TryEnter()) {
|
|
sGLockLevel++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void LeaveGuiMutex()
|
|
{
|
|
LLOG(">LeaveGuiMutex " << sGLockLevel << ' ' << IsMainThread());
|
|
ASSERT(sGLockLevel > 0);
|
|
if(--sGLockLevel == 0)
|
|
sGLock.Leave();
|
|
LLOG("LeaveGuiMutex " << sGLockLevel << ' ' << IsMainThread());
|
|
}
|
|
|
|
int LeaveGuiMutexAll()
|
|
{
|
|
LLOG(">LeaveGuiMutexAll " << sGLockLevel << ' ' << IsMainThread());
|
|
int q = sGLockLevel;
|
|
if(q) {
|
|
sGLock.Leave();
|
|
sGLockLevel = 0;
|
|
}
|
|
LLOG("LeaveGuiMutexAll " << q << ' ' << IsMainThread());
|
|
return q;
|
|
}
|
|
|
|
bool ThreadHasGuiLock()
|
|
{
|
|
return Thread::IsMain() || sGLockLevel;
|
|
}
|
|
|
|
int GetGuiLockLevel()
|
|
{
|
|
return sGLockLevel;
|
|
}
|
|
|
|
void WakeUpGuiThread();
|
|
|
|
struct Ctrl::CallBox {
|
|
Semaphore sem;
|
|
Event<> cb;
|
|
};
|
|
|
|
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
|
|
{
|
|
cbox->cb();
|
|
cbox->sem.Release();
|
|
}
|
|
|
|
void Ctrl::Call(Function<void ()> cb)
|
|
{
|
|
if(IsMainThread())
|
|
cb();
|
|
else {
|
|
CallBox cbox;
|
|
cbox.cb << cb;
|
|
UPP::PostCallback(callback1(PerformCall, &cbox));
|
|
WakeUpGuiThread();
|
|
int level = LeaveGuiMutexAll(); // Unlock GUI to give main thread chance to handle Call
|
|
cbox.sem.Wait();
|
|
EnterGuiMutex(level);
|
|
}
|
|
}
|
|
|
|
void Ctrl::ShutdownThreads()
|
|
{
|
|
Thread::BeginShutdownThreads();
|
|
while(Thread::GetCount()) {
|
|
Thread::TryShutdownThreads();
|
|
ProcessEvents();
|
|
GuiUnlock __;
|
|
Sleep(100);
|
|
}
|
|
Thread::EndShutdownThreads();
|
|
}
|
|
|
|
}
|