mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
195 lines
3.4 KiB
C++
195 lines
3.4 KiB
C++
#include "CtrlCore.h"
|
|
|
|
#define LLOG(x) // if(!IsMainThread()) DLOG((int)GetCurrentThreadId() << " " << x)
|
|
|
|
NAMESPACE_UPP
|
|
|
|
#ifdef _MULTITHREADED
|
|
|
|
static int NonMain;
|
|
static StaticMutex NonMainLock;
|
|
|
|
void EnterGuiMutex()
|
|
{
|
|
LLOG("Thread " << IsMainThread() << " trying to lock" << ", nonmain: " << NonMain);
|
|
bool nonmain = !IsMainThread();
|
|
if(nonmain)
|
|
NonMainLock.Enter();
|
|
EnterGMutex();
|
|
if(nonmain)
|
|
NonMain++;
|
|
LLOG("Thread " << IsMainThread() << " LOCK" << ", nonmain: " << NonMain);
|
|
}
|
|
|
|
void LeaveGuiMutex()
|
|
{
|
|
LLOG("Thread " << IsMainThread() << " trying to unlock" << ", nonmain: " << NonMain);
|
|
bool nonmain = !IsMainThread();
|
|
if(nonmain)
|
|
NonMain--;
|
|
LeaveGMutex();
|
|
if(nonmain)
|
|
NonMainLock.Leave();
|
|
LLOG("Thread " << IsMainThread() << " UNLOCK" << ", nonmain: " << NonMain);
|
|
}
|
|
|
|
struct Ctrl::CallBox {
|
|
Semaphore sem;
|
|
Callback cb;
|
|
};
|
|
|
|
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
|
|
{
|
|
cbox->cb();
|
|
LLOG("Sem release");
|
|
cbox->sem.Release();
|
|
}
|
|
|
|
Callback Ctrl::CtrlCall;
|
|
static Mutex CtrlCallMutex;
|
|
|
|
void WakeUpGuiThread();
|
|
|
|
bool Ctrl::DoCall()
|
|
{
|
|
LLOG("DoCall");
|
|
GuiLock __;
|
|
{
|
|
Mutex::Lock __(CtrlCallMutex);
|
|
CtrlCall();
|
|
CtrlCall.Clear();
|
|
}
|
|
LLOG("--- DoCall, nonmain: " << NonMain);
|
|
return NonMain;
|
|
}
|
|
|
|
void Ctrl::ICall(Callback cb)
|
|
{
|
|
LLOG("Ctrl::Call " << IsMainThread() << ", nonmain: " << NonMain);
|
|
if(IsMainThread())
|
|
cb();
|
|
else {
|
|
GuiLock __;
|
|
CallBox cbox;
|
|
cbox.cb = cb;
|
|
{
|
|
Mutex::Lock __(CtrlCallMutex);
|
|
CtrlCall = callback1(PerformCall, &cbox);
|
|
}
|
|
int level = LeaveGMutexAll();
|
|
WakeUpGuiThread();
|
|
LLOG("Waiting for semaphore");
|
|
if(!Thread::IsShutdownThreads())
|
|
cbox.sem.Wait();
|
|
EnterGMutex(level);
|
|
}
|
|
LLOG("-- Ctrl::Call " << IsMainThread());
|
|
}
|
|
|
|
void Ctrl::Call(Callback cb)
|
|
{
|
|
if(IsMainThread())
|
|
cb();
|
|
else {
|
|
GuiLock __;
|
|
CallBox cbox;
|
|
cbox.cb = cb;
|
|
UPP::PostCallback(callback1(PerformCall, &cbox));
|
|
int n = NonMain;
|
|
int nn = n;
|
|
NonMain = 0;
|
|
for(int i = 0; i < n; i++)
|
|
NonMainLock.Leave();
|
|
int level = LeaveGMutexAll();
|
|
WakeUpGuiThread();
|
|
if(!Thread::IsShutdownThreads())
|
|
cbox.sem.Wait();
|
|
for(int i = 0; i < n; i++)
|
|
NonMainLock.Enter();
|
|
EnterGMutex(level);
|
|
NonMain = n;
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
bool Ctrl::DoCall()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void Ctrl::ICall(Callback cb)
|
|
{
|
|
cb();
|
|
}
|
|
|
|
void Ctrl::Call(Callback cb)
|
|
{
|
|
cb();
|
|
}
|
|
#endif
|
|
|
|
void Ctrl::GuiSleep(int ms)
|
|
{
|
|
Call(callback1(&Ctrl::GuiSleep0, ms));
|
|
}
|
|
|
|
void Ctrl::WndDestroy()
|
|
{
|
|
ICall(callback(this, &Ctrl::WndDestroy0));
|
|
}
|
|
|
|
void Ctrl::WndShow(bool b)
|
|
{
|
|
ICall(THISBACK1(WndShow0, b));
|
|
}
|
|
|
|
void Ctrl::WndUpdate()
|
|
{
|
|
ICall(THISBACK(WndUpdate0));
|
|
}
|
|
|
|
void Ctrl::SetWndForeground()
|
|
{
|
|
ICall(THISBACK(SetWndForeground0));
|
|
}
|
|
|
|
bool Ctrl::WndEnable(bool b)
|
|
{
|
|
ICall(THISBACK1(WndEnable0, &b));
|
|
return b;
|
|
}
|
|
|
|
bool Ctrl::SetWndFocus()
|
|
{
|
|
bool b;
|
|
ICall(THISBACK1(SetWndFocus0, &b));
|
|
return b;
|
|
}
|
|
|
|
void Ctrl::WndInvalidateRect(const Rect& r)
|
|
{
|
|
ICall(THISBACK1(WndInvalidateRect0, r));
|
|
}
|
|
|
|
void Ctrl::WndSetPos(const Rect& rect)
|
|
{
|
|
ICall(THISBACK1(WndSetPos0, rect));
|
|
}
|
|
|
|
void Ctrl::WndUpdate(const Rect& r)
|
|
{
|
|
ICall(THISBACK1(WndUpdate0r, r));
|
|
}
|
|
|
|
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
|
|
{
|
|
ICall(THISBACK3(WndScrollView0, r, dx, dy));
|
|
}
|
|
|
|
void Ctrl::EventLoop(Ctrl *ctrl)
|
|
{
|
|
Call(callback1(&Ctrl::EventLoop0, ctrl));
|
|
}
|
|
|
|
END_UPP_NAMESPACE
|