ultimatepp/uppsrc/CtrlCore/CtrlMt.cpp
cxl 48fa0dd5ea CtrlCore: ASSERTs to detect global variable widgets and missing GuiLock
git-svn-id: svn://ultimatepp.org/upp/trunk@5588 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2012-11-28 19:16:10 +00:00

161 lines
2.3 KiB
C++

#include "CtrlCore.h"
#define LLOG(x) // DLOG(x)
NAMESPACE_UPP
#ifdef _MULTITHREADED
static StaticMutex sGLock;
static thread__ int sGLockLevel = 0;
void EnterGuiMutex()
{
if(sGLockLevel++ == 0)
sGLock.Enter();
LLOG("EnterGuiMutex " << sGLockLevel);
}
void EnterGuiMutex(int n)
{
if(n > 0) {
if(sGLockLevel == 0)
sGLock.Enter();
sGLockLevel += n;
}
LLOG("EnterGuiMutex " << sGLockLevel);
}
void LeaveGuiMutex()
{
ASSERT(sGLockLevel > 0);
if(--sGLockLevel == 0)
sGLock.Leave();
LLOG("LeaveGuiMutex " << sGLockLevel);
}
int LeaveGuiMutexAll()
{
int q = sGLockLevel;
if(q) {
sGLock.Leave();
sGLockLevel = 0;
}
LLOG("LeaveGuiMutex all " << q);
return q;
}
bool ThreadHasGuiLock()
{
return Thread::IsMain() || sGLockLevel;
}
void WakeUpGuiThread();
struct Ctrl::CallBox {
Semaphore sem;
Callback cb;
};
void Ctrl::PerformCall(Ctrl::CallBox *cbox)
{
cbox->cb();
LLOG("Sem release");
cbox->sem.Release();
}
void Ctrl::Call(Callback cb)
{
if(IsMainThread())
cb();
else {
int ms = msecs();
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()) {
ProcessEvents();
Sleep(0);
}
Thread::EndShutdownThreads();
}
#else
void Ctrl::Call(Callback cb)
{
cb();
}
#endif
void Ctrl::GuiSleep(int ms)
{
Call(callback1(&Ctrl::GuiSleep0, ms));
}
void Ctrl::WndDestroy()
{
Call(PTEBACK(WndDestroy0));
}
void Ctrl::WndShow(bool b)
{
Call(PTEBACK1(WndShow0, b));
}
void Ctrl::WndUpdate()
{
Call(PTEBACK(WndUpdate0));
}
void Ctrl::SetWndForeground()
{
Call(PTEBACK(SetWndForeground0));
}
bool Ctrl::WndEnable(bool b)
{
Call(PTEBACK1(WndEnable0, &b));
return b;
}
bool Ctrl::SetWndFocus()
{
bool b;
Call(PTEBACK1(SetWndFocus0, &b));
return b;
}
void Ctrl::WndSetPos(const Rect& rect)
{
Call(PTEBACK1(WndSetPos0, rect));
}
void Ctrl::WndUpdate(const Rect& r)
{
Call(PTEBACK1(WndUpdate0r, r));
}
void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
{
Call(PTEBACK3(WndScrollView0, r, dx, dy));
}
void Ctrl::EventLoop(Ctrl *ctrl)
{
Call(callback1(&Ctrl::EventLoop0, ctrl));
}
END_UPP_NAMESPACE