90 class TGWin32CallBackObject :
public TObject {
92 TGWin32CallBack fCallBack;
95 TGWin32CallBackObject(TGWin32CallBack cb,
void *p):fCallBack(cb),fParam(p) {}
96 ~TGWin32CallBackObject() {
if (fParam)
delete fParam; }
100 class TGWin32ProxyBasePrivate {
103 TGWin32ProxyBasePrivate();
104 ~TGWin32ProxyBasePrivate();
110 TGWin32ProxyBasePrivate::TGWin32ProxyBasePrivate()
112 fEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
118 TGWin32ProxyBasePrivate::~TGWin32ProxyBasePrivate()
120 if (fEvent) ::CloseHandle(fEvent);
125 ULong_t TGWin32ProxyBase::fgPostMessageId = 0;
126 ULong_t TGWin32ProxyBase::fgPingMessageId = 0;
127 ULong_t TGWin32ProxyBase::fgMainThreadId = 0;
128 ULong_t TGWin32ProxyBase::fgUserThreadId = 0;
129 Long_t TGWin32ProxyBase::fgLock = 0;
130 UInt_t TGWin32ProxyBase::fMaxResponseTime = 0;
136 TGWin32ProxyBase::TGWin32ProxyBase()
138 fIsVirtualX = kFALSE;
141 fListOfCallBacks =
new TList();
143 fId = ::GetCurrentThreadId();
144 fPimpl =
new TGWin32ProxyBasePrivate();
146 if (!fgPostMessageId) fgPostMessageId = ::RegisterWindowMessage(
"TGWin32ProxyBase::Post");
147 if (!fgPingMessageId) fgPingMessageId = ::RegisterWindowMessage(
"TGWin32ProxyBase::Ping");
153 TGWin32ProxyBase::~TGWin32ProxyBase()
155 fListOfCallBacks->Delete();
156 delete fListOfCallBacks;
157 fListOfCallBacks = 0;
165 void TGWin32ProxyBase::Lock()
173 void TGWin32ProxyBase::Unlock()
181 void TGWin32ProxyBase::GlobalLock()
183 if (IsGloballyLocked())
return;
184 ::InterlockedIncrement(&fgLock);
190 void TGWin32ProxyBase::GlobalUnlock()
192 if (!IsGloballyLocked())
return;
193 ::InterlockedDecrement(&fgLock);
199 Bool_t TGWin32ProxyBase::Ping()
201 return ::PostThreadMessage(fgMainThreadId, fgPingMessageId, (WPARAM)0, 0L);
207 Double_t TGWin32ProxyBase::GetMilliSeconds()
209 static LARGE_INTEGER freq;
210 static Bool_t first = kTRUE;
212 static Double_t overhead = 0;
215 LARGE_INTEGER count0;
216 ::QueryPerformanceFrequency(&freq);
217 ::QueryPerformanceCounter(&count0);
220 dummy = ((Double_t)count0.QuadPart - overhead)*1000./((Double_t)freq.QuadPart);
222 ::QueryPerformanceCounter(&count);
223 overhead = (Double_t)count.QuadPart - (Double_t)count0.QuadPart;
227 ::QueryPerformanceCounter(&count);
228 return ((Double_t)count.QuadPart - overhead)*1000./((Double_t)freq.QuadPart);
235 void TGWin32ProxyBase::ExecuteCallBack(Bool_t sync)
238 if (fListOfCallBacks && fListOfCallBacks->GetSize()) {
239 TIter next(fListOfCallBacks);
240 TGWin32CallBackObject *obj;
242 while ((obj = (TGWin32CallBackObject*)next())) {
243 obj->fCallBack(obj->fParam);
247 if (fCallBack) fCallBack(fParam);
248 ::SetEvent(fPimpl->fEvent);
262 Bool_t TGWin32ProxyBase::ForwardCallBack(Bool_t sync)
266 if (!fgMainThreadId)
return kFALSE;
268 while (IsGloballyLocked()) {
270 #ifdef OLD_THREAD_IMPLEMENTATION
271 if (GetCurrentThreadId() == fgMainThreadId)
275 if (!fgMainThreadId)
return kFALSE;
278 Bool_t batch = !sync && (fListOfCallBacks->GetSize() < fBatchLimit);
282 if (!fgUserThreadId && fIsVirtualX &&
283 (GetCurrentThreadId() != fgMainThreadId) &&
284 (fListOfCallBacks->GetSize() < fBatchLimit))
288 fListOfCallBacks->Add(
new TGWin32CallBackObject(fCallBack, fParam));
292 while (!::PostThreadMessage(fgMainThreadId, fgPostMessageId, (WPARAM)
this, 0L)) {
295 if (wait++ > 5)
return kFALSE;
298 #ifdef OLD_THREAD_IMPLEMENTATION
302 DWORD res = WAIT_TIMEOUT;
303 while (res == WAIT_TIMEOUT) {
304 res = ::WaitForSingleObject(fPimpl->fEvent, 100);
305 #ifdef OLD_THREAD_IMPLEMENTATION
306 if ((GetCurrentThreadId() == fgMainThreadId) ||
307 (!gROOT->IsLineProcessing() && IsGloballyLocked())) {
310 if (cnt++ > 20)
break;
313 ::ResetEvent(fPimpl->fEvent);
315 if (res == WAIT_TIMEOUT) {
320 fListOfCallBacks->Delete();
327 Bool_t TGWin32ProxyBase::IsGloballyLocked()
335 void TGWin32ProxyBase::SendExitMessage()
337 ::PostThreadMessage(fgMainThreadId, WM_QUIT, 0, 0L);