diff --git a/thread/inc/TWin32Condition.h b/thread/inc/TWin32Condition.h index 265a8343dc83a6987d30cd78467a0d0ce730da2f..0ce8e70f7d7380884edd7dbb255ea45732d34072 100644 --- a/thread/inc/TWin32Condition.h +++ b/thread/inc/TWin32Condition.h @@ -1,79 +1,79 @@ -// @(#)root/thread:$Name: $:$Id: TWin32Condition.h,v 1.1.1.1 2000/05/16 17:00:48 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_TWin32Condition -#define ROOT_TWin32Condition - - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32Condition // -// // -// This class provides an interface to the win32 condition variable // -// routines. // -// // -////////////////////////////////////////////////////////////////////////// - -#ifndef ROOT_TConditionImp -#include "TConditionImp.h" -#endif - -#include "Windows4Root.h" - -#ifndef __CINT__ -typedef struct -{ - int waiters_count_; - // Number of waiting threads. - - CRITICAL_SECTION waiters_count_lock_; - // Serialize access to <waiters_count_>. - - HANDLE sema_; - // Semaphore used to queue up threads waiting for the condition to - // become signaled. - - HANDLE waiters_done_; - // An auto-reset event used by the broadcast/signal thread to wait - // for all the waiting thread(s) to wake up and be released from the - // semaphore. - - size_t was_broadcast_; - // Keeps track of whether we were broadcasting or signaling. This - // allows us to optimize the code if we're just signaling. -} pthread_cond_t; -#else -struct pthread_cond_t; -#endif - -class TMutexImp; -class TWin32Mutex; - - -class TWin32Condition : public TConditionImp { - -private: - pthread_cond_t fCond; // the pthread condition variable - TWin32Mutex *fMutex; // mutex used around Wait() and TimedWait() - -public: - TWin32Condition(TMutexImp *m); - virtual ~TWin32Condition(); - - Int_t Wait(); - Int_t TimedWait(ULong_t secs, ULong_t nanoSecs = 0); - Int_t Signal(); - Int_t Broadcast(); - - ClassDef(TWin32Condition,0) // Posix condition variable -}; - -#endif +// @(#)root/thread:$Name: $:$Id: TWin32Condition.h,v 1.1 2004/11/02 13:07:57 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TWin32Condition +#define ROOT_TWin32Condition + + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32Condition // +// // +// This class provides an interface to the win32 condition variable // +// routines. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TConditionImp +#include "TConditionImp.h" +#endif + +#include "Windows4Root.h" + +#ifndef __CINT__ +typedef struct +{ + int waiters_count_; + // Number of waiting threads. + + CRITICAL_SECTION waiters_count_lock_; + // Serialize access to <waiters_count_>. + + HANDLE sema_; + // Semaphore used to queue up threads waiting for the condition to + // become signaled. + + HANDLE waiters_done_; + // An auto-reset event used by the broadcast/signal thread to wait + // for all the waiting thread(s) to wake up and be released from the + // semaphore. + + size_t was_broadcast_; + // Keeps track of whether we were broadcasting or signaling. This + // allows us to optimize the code if we're just signaling. +} pthread_cond_t; +#else +struct pthread_cond_t; +#endif + +class TMutexImp; +class TWin32Mutex; + + +class TWin32Condition : public TConditionImp { + +private: + pthread_cond_t fCond; // the pthread condition variable + TWin32Mutex *fMutex; // mutex used around Wait() and TimedWait() + +public: + TWin32Condition(TMutexImp *m); + virtual ~TWin32Condition(); + + Int_t Wait(); + Int_t TimedWait(ULong_t secs, ULong_t nanoSecs = 0); + Int_t Signal(); + Int_t Broadcast(); + + ClassDef(TWin32Condition,0) // Posix condition variable +}; + +#endif diff --git a/thread/inc/TWin32Mutex.h b/thread/inc/TWin32Mutex.h index fd89bdd80ac80b9ccdd3e7ea0589d74d8b8aa3c1..3c6be2c89eceda72d204e959b96aa698d801fce2 100644 --- a/thread/inc/TWin32Mutex.h +++ b/thread/inc/TWin32Mutex.h @@ -1,48 +1,48 @@ -// @(#)root/thread:$Name: $:$Id: TWin32Mutex.h,v 1.1 2004/11/02 13:07:57 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_TWin32Mutex -#define ROOT_TWin32Mutex - - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32Mutex // -// // -// This class provides an interface to the Win32 mutex routines. // -// // -////////////////////////////////////////////////////////////////////////// - -#ifndef ROOT_TMutexImp -#include "TMutexImp.h" -#endif - -#include "Windows4Root.h" - -class TWin32Mutex : public TMutexImp { - -friend class TWin32Condition; - -private: - HANDLE fHMutex; - -public: - TWin32Mutex(); - virtual ~TWin32Mutex(); - - Int_t Lock(); - Int_t UnLock(); - Int_t TryLock(); - - ClassDef(TWin32Mutex,0) // Win32 mutex lock -}; - -#endif +// @(#)root/thread:$Name: $:$Id: TWin32Mutex.h,v 1.2 2004/12/10 12:13:33 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TWin32Mutex +#define ROOT_TWin32Mutex + + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32Mutex // +// // +// This class provides an interface to the Win32 mutex routines. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TMutexImp +#include "TMutexImp.h" +#endif + +#include "Windows4Root.h" + +class TWin32Mutex : public TMutexImp { + +friend class TWin32Condition; + +private: + HANDLE fHMutex; + +public: + TWin32Mutex(); + virtual ~TWin32Mutex(); + + Int_t Lock(); + Int_t UnLock(); + Int_t TryLock(); + + ClassDef(TWin32Mutex,0) // Win32 mutex lock +}; + +#endif diff --git a/thread/inc/TWin32Thread.h b/thread/inc/TWin32Thread.h index 5607e848f8bfc954a25ffc1563991b4c81c66539..b5e7f8aae1f8b01906e219f8945ac1bd8a16181b 100644 --- a/thread/inc/TWin32Thread.h +++ b/thread/inc/TWin32Thread.h @@ -1,77 +1,77 @@ -// @(#)root/thread:$Name: $:$Id: TWin32Thread.h,v 1.2 2004/12/10 12:13:33 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -#ifndef ROOT_TWin32Thread -#define ROOT_TWin32Thread - - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32Thread // -// // -// This class provides an interface to the Win32 thread routines. // -// // -////////////////////////////////////////////////////////////////////////// - -#ifndef ROOT_TThreadImp -#include "TThreadImp.h" -#endif - -#include "Windows4Root.h" - -class TWin32ThreadCleanUp; - -class TWin32Thread : public TThreadImp { - -private: - TWin32ThreadCleanUp *fCleanUp; - -public: - TWin32Thread() { } - ~TWin32Thread() { } - - virtual Int_t Join(TThread *th, void **ret); - virtual Long_t SelfId(); - virtual Int_t Run(TThread *th); - - virtual Int_t Kill(TThread *th); - - virtual Int_t SetCancelOff(); - virtual Int_t SetCancelOn(); - virtual Int_t SetCancelAsynchronous(); - virtual Int_t SetCancelDeferred(); - virtual Int_t CancelPoint(); - - virtual Int_t CleanUpPush(void **main, void *free,void *arg); - virtual Int_t CleanUpPop(void **main, Int_t exe); - virtual Int_t CleanUp(void **main); - - virtual Int_t Exit(void *ret); - - ClassDef(TWin32Thread,0) // TWin32Thread class -}; - - -class TWin32ThreadCleanUp { - -friend class TWin32Thread; - -private: - void *fRoutine; - void *fArgument; - TWin32ThreadCleanUp *fNext; - -public: - TWin32ThreadCleanUp(void **main,void *routine,void *arg); - ~TWin32ThreadCleanUp() { } -}; - -#endif +// @(#)root/thread:$Name: $:$Id: TWin32Thread.h,v 1.3 2004/12/14 15:06:18 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TWin32Thread +#define ROOT_TWin32Thread + + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32Thread // +// // +// This class provides an interface to the Win32 thread routines. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TThreadImp +#include "TThreadImp.h" +#endif + +#include "Windows4Root.h" + +class TWin32ThreadCleanUp; + +class TWin32Thread : public TThreadImp { + +private: + TWin32ThreadCleanUp *fCleanUp; + +public: + TWin32Thread() { } + ~TWin32Thread() { } + + virtual Int_t Join(TThread *th, void **ret); + virtual Long_t SelfId(); + virtual Int_t Run(TThread *th); + + virtual Int_t Kill(TThread *th); + + virtual Int_t SetCancelOff(); + virtual Int_t SetCancelOn(); + virtual Int_t SetCancelAsynchronous(); + virtual Int_t SetCancelDeferred(); + virtual Int_t CancelPoint(); + + virtual Int_t CleanUpPush(void **main, void *free,void *arg); + virtual Int_t CleanUpPop(void **main, Int_t exe); + virtual Int_t CleanUp(void **main); + + virtual Int_t Exit(void *ret); + + ClassDef(TWin32Thread,0) // TWin32Thread class +}; + + +class TWin32ThreadCleanUp { + +friend class TWin32Thread; + +private: + void *fRoutine; + void *fArgument; + TWin32ThreadCleanUp *fNext; + +public: + TWin32ThreadCleanUp(void **main,void *routine,void *arg); + ~TWin32ThreadCleanUp() { } +}; + +#endif diff --git a/thread/inc/TWin32ThreadFactory.h b/thread/inc/TWin32ThreadFactory.h index b4c19019c4292ce76bdfda89735e3368a171b69f..56697148dbb29185fa06c953a5c9ff2f99f4d24a 100644 --- a/thread/inc/TWin32ThreadFactory.h +++ b/thread/inc/TWin32ThreadFactory.h @@ -1,46 +1,46 @@ -// @(#)root/thread:$Name: $:$Id: TWin32ThreadFactory.h,v 1.1.1.1 2000/05/16 17:00:48 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - - -#ifndef ROOT_TWin32ThreadFactory -#define ROOT_TWin32ThreadFactory - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32ThreadFactory // -// // -// This is a factory for Win32 thread components. // -// // -////////////////////////////////////////////////////////////////////////// - -#ifndef ROOT_TThreadFactory -#include "TThreadFactory.h" -#endif - -class TMutexImp; -class TConditionImp; -class TThreadImp; - - -class TWin32ThreadFactory : public TThreadFactory { - -public: - TWin32ThreadFactory(const char *name = "Win32", const char *title = "Win32 Thread Factory"); - virtual ~TWin32ThreadFactory() { } - - virtual TMutexImp *CreateMutexImp(); - virtual TConditionImp *CreateConditionImp(TMutexImp *m); - virtual TThreadImp *CreateThreadImp(); - - ClassDef(TWin32ThreadFactory,0) // Win32 thread factory -}; - -#endif +// @(#)root/thread:$Name: $:$Id: TWin32ThreadFactory.h,v 1.1 2004/11/02 13:07:57 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + + +#ifndef ROOT_TWin32ThreadFactory +#define ROOT_TWin32ThreadFactory + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32ThreadFactory // +// // +// This is a factory for Win32 thread components. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TThreadFactory +#include "TThreadFactory.h" +#endif + +class TMutexImp; +class TConditionImp; +class TThreadImp; + + +class TWin32ThreadFactory : public TThreadFactory { + +public: + TWin32ThreadFactory(const char *name = "Win32", const char *title = "Win32 Thread Factory"); + virtual ~TWin32ThreadFactory() { } + + virtual TMutexImp *CreateMutexImp(); + virtual TConditionImp *CreateConditionImp(TMutexImp *m); + virtual TThreadImp *CreateThreadImp(); + + ClassDef(TWin32ThreadFactory,0) // Win32 thread factory +}; + +#endif diff --git a/thread/src/TWin32Condition.cxx b/thread/src/TWin32Condition.cxx index e33f68a23520c8700cd2f5f32c3ccc5b3988cd3a..652ab01c2d4e33199543e628477495ae6957fe59 100644 --- a/thread/src/TWin32Condition.cxx +++ b/thread/src/TWin32Condition.cxx @@ -1,199 +1,207 @@ -// @(#)root/thread:$Name: $:$Id: TWin32Condition.cxx,v 1.1 2004/11/02 13:07:57 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32Condition // -// // -// This class provides an interface to the win32 condition variable // -// routines. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TWin32Condition.h" -#include "TWin32Mutex.h" -#include "Windows4Root.h" - -#include <errno.h> - -ClassImp(TWin32Condition) - -//______________________________________________________________________________ -TWin32Condition::TWin32Condition(TMutexImp *m) -{ - // Create Condition variable. Ctor must be given a pointer to an - // existing mutex. The condition variable is then linked to the mutex, - // so that there is an implicit unlock and lock around Wait() and - // TimedWait(). - - fMutex = (TWin32Mutex *) m; - - fCond.waiters_count_ = 0; - fCond.was_broadcast_ = 0; - fCond.sema_ = CreateSemaphore(0, // no security - 0, // initially 0 - 0x7fffffff, // max count - 0); // unnamed - InitializeCriticalSection (&fCond.waiters_count_lock_); - fCond.waiters_done_ = CreateEvent(0, // no security - FALSE, // auto-reset - FALSE, // non-signaled initially - 0); // unnamed -} - -//______________________________________________________________________________ -TWin32Condition::~TWin32Condition() -{ - // TCondition dtor. - -} - -//______________________________________________________________________________ -Int_t TWin32Condition::Wait() -{ - // Wait for the condition variable to be signalled. The mutex is - // implicitely released before waiting and locked again after waking up. - // If Wait() is called by multiple threads, a signal may wake up more - // than one thread. See POSIX threads documentation for details. - - // Avoid race conditions. - EnterCriticalSection(&fCond.waiters_count_lock_); - fCond.waiters_count_++; - LeaveCriticalSection(&fCond.waiters_count_lock_); - - // This call atomically releases the mutex and waits on the - // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast> - // are called by another thread. - SignalObjectAndWait(fMutex->fHMutex, fCond.sema_, INFINITE, FALSE); - - // Reacquire lock to avoid race conditions. - EnterCriticalSection(&fCond.waiters_count_lock_); - - // We're no longer waiting... - fCond.waiters_count_--; - - // Check to see if we're the last waiter after <pthread_cond_broadcast>. - int last_waiter = fCond.was_broadcast_ && fCond.waiters_count_ == 0; - - LeaveCriticalSection(&fCond.waiters_count_lock_); - - // If we're the last waiter thread during this particular broadcast - // then let all the other threads proceed. - if (last_waiter) - // This call atomically signals the <waiters_done_> event and waits until - // it can acquire the <fMutex->fHMutex>. This is required to ensure fairness. - SignalObjectAndWait(fCond.waiters_done_, fMutex->fHMutex, INFINITE, FALSE); - else - // Always regain the external mutex since that's the guarantee we - // give to our callers. - WaitForSingleObject(fMutex->fHMutex, INFINITE); - - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Condition::TimedWait(ULong_t secs, ULong_t nanoSecs) -{ - // TimedWait() is given an absolute time to wait until. To wait for a - // relative time from now, use TThread::GetTime(). See POSIX threads - // documentation for why absolute times are better than relative. - // Returns 0 if successfully signalled, 1 if time expired. - - DWORD dwMilliseconds = (DWORD)((secs * 1000) + (nanoSecs / 1000000)); - // Avoid race conditions. - EnterCriticalSection(&fCond.waiters_count_lock_); - fCond.waiters_count_++; - LeaveCriticalSection(&fCond.waiters_count_lock_); - - // This call atomically releases the mutex and waits on the - // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast> - // are called by another thread. - SignalObjectAndWait(fMutex->fHMutex, fCond.sema_, dwMilliseconds, FALSE); - - // Reacquire lock to avoid race conditions. - EnterCriticalSection(&fCond.waiters_count_lock_); - - // We're no longer waiting... - fCond.waiters_count_--; - - // Check to see if we're the last waiter after <pthread_cond_broadcast>. - int last_waiter = fCond.was_broadcast_ && fCond.waiters_count_ == 0; - - LeaveCriticalSection(&fCond.waiters_count_lock_); - - // If we're the last waiter thread during this particular broadcast - // then let all the other threads proceed. - if (last_waiter) - // This call atomically signals the <waiters_done_> event and waits until - // it can acquire the <fMutex->fHMutex>. This is required to ensure fairness. - SignalObjectAndWait(fCond.waiters_done_, fMutex->fHMutex, dwMilliseconds, FALSE); - else - // Always regain the external mutex since that's the guarantee we - // give to our callers. - WaitForSingleObject(fMutex->fHMutex, INFINITE); - - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Condition::Signal() -{ - // If one or more threads have called Wait(), Signal() wakes up at least - // one of them, possibly more. See POSIX threads documentation for details. - - EnterCriticalSection (&fCond.waiters_count_lock_); - int have_waiters = fCond.waiters_count_ > 0; - LeaveCriticalSection (&fCond.waiters_count_lock_); - - // If there aren't any waiters, then this is a no-op. - if (have_waiters) - ReleaseSemaphore(fCond.sema_, 1, 0); - - return 0; -} - - -//______________________________________________________________________________ -Int_t TWin32Condition::Broadcast() -{ - // Broadcast is like signal but wakes all threads which have called Wait(). - - // This is needed to ensure that <waiters_count_> and <was_broadcast_> are - // consistent relative to each other. - EnterCriticalSection(&fCond.waiters_count_lock_); - int have_waiters = 0; - - if (fCond.waiters_count_ > 0) { - // We are broadcasting, even if there is just one waiter... - // Record that we are broadcasting, which helps optimize - // <pthread_cond_wait> for the non-broadcast case. - fCond.was_broadcast_ = 1; - have_waiters = 1; - } - - if (have_waiters) { - // Wake up all the waiters atomically. - ReleaseSemaphore(fCond.sema_, fCond.waiters_count_, 0); - - LeaveCriticalSection(&fCond.waiters_count_lock_); - - // Wait for all the awakened threads to acquire the counting - // semaphore. - WaitForSingleObject(fCond.waiters_done_, INFINITE); - // This assignment is okay, even without the <waiters_count_lock_> held - // because no other waiter threads can wake up to access it. - fCond.was_broadcast_ = 0; - } - else - LeaveCriticalSection(&fCond.waiters_count_lock_); - - return 0; -} +// @(#)root/thread:$Name: $:$Id: TWin32Condition.cxx,v 1.2 2004/12/10 12:13:33 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32Condition // +// // +// This class provides an interface to the win32 condition variable // +// routines. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TWin32Condition.h" +#include "TWin32Mutex.h" +#include "TTimeStamp.h" +#include "Windows4Root.h" + +#include <errno.h> + +ClassImp(TWin32Condition) + +//______________________________________________________________________________ +TWin32Condition::TWin32Condition(TMutexImp *m) +{ + // Create Condition variable. Ctor must be given a pointer to an + // existing mutex. The condition variable is then linked to the mutex, + // so that there is an implicit unlock and lock around Wait() and + // TimedWait(). + + fMutex = (TWin32Mutex *) m; + + fCond.waiters_count_ = 0; + fCond.was_broadcast_ = 0; + fCond.sema_ = CreateSemaphore(0, // no security + 0, // initially 0 + 0x7fffffff, // max count + 0); // unnamed + InitializeCriticalSection (&fCond.waiters_count_lock_); + fCond.waiters_done_ = CreateEvent(0, // no security + FALSE, // auto-reset + FALSE, // non-signaled initially + 0); // unnamed +} + +//______________________________________________________________________________ +TWin32Condition::~TWin32Condition() +{ + // TCondition dtor. + +} + +//______________________________________________________________________________ +Int_t TWin32Condition::Wait() +{ + // Wait for the condition variable to be signalled. The mutex is + // implicitely released before waiting and locked again after waking up. + // If Wait() is called by multiple threads, a signal may wake up more + // than one thread. See POSIX threads documentation for details. + + // Avoid race conditions. + EnterCriticalSection(&fCond.waiters_count_lock_); + fCond.waiters_count_++; + LeaveCriticalSection(&fCond.waiters_count_lock_); + + // This call atomically releases the mutex and waits on the + // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast> + // are called by another thread. + SignalObjectAndWait(fMutex->fHMutex, fCond.sema_, INFINITE, FALSE); + + // Reacquire lock to avoid race conditions. + EnterCriticalSection(&fCond.waiters_count_lock_); + + // We're no longer waiting... + fCond.waiters_count_--; + + // Check to see if we're the last waiter after <pthread_cond_broadcast>. + int last_waiter = fCond.was_broadcast_ && fCond.waiters_count_ == 0; + + LeaveCriticalSection(&fCond.waiters_count_lock_); + + // If we're the last waiter thread during this particular broadcast + // then let all the other threads proceed. + if (last_waiter) + // This call atomically signals the <waiters_done_> event and waits until + // it can acquire the <fMutex->fHMutex>. This is required to ensure fairness. + SignalObjectAndWait(fCond.waiters_done_, fMutex->fHMutex, INFINITE, FALSE); + else + // Always regain the external mutex since that's the guarantee we + // give to our callers. + WaitForSingleObject(fMutex->fHMutex, INFINITE); + + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Condition::TimedWait(ULong_t secs, ULong_t nanoSecs) +{ + // TimedWait() is given an absolute time to wait until. To wait for a + // relative time from now, use TThread::GetTime(). See POSIX threads + // documentation for why absolute times are better than relative. + // Returns 0 if successfully signalled, 1 if time expired. + + TTimeStamp t; + // Get actual time + ULong_t secNow = t.GetSec(); + ULong_t nanosecNow = t.GetNanoSec(); + DWORD dwMillisecondsNow = (DWORD)((secNow * 1000) + (nanosecNow / 1000000)); + DWORD dwMilliseconds = (DWORD)((secs * 1000) + (nanoSecs / 1000000)); + // Calculate delta T to obtain the real time to wait for + DWORD dwTimeWait = (DWORD)(dwMilliseconds - dwMillisecondsNow); + // Avoid race conditions. + EnterCriticalSection(&fCond.waiters_count_lock_); + fCond.waiters_count_++; + LeaveCriticalSection(&fCond.waiters_count_lock_); + + // This call atomically releases the mutex and waits on the + // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast> + // are called by another thread. + SignalObjectAndWait(fMutex->fHMutex, fCond.sema_, dwTimeWait, FALSE); + + // Reacquire lock to avoid race conditions. + EnterCriticalSection(&fCond.waiters_count_lock_); + + // We're no longer waiting... + fCond.waiters_count_--; + + // Check to see if we're the last waiter after <pthread_cond_broadcast>. + int last_waiter = fCond.was_broadcast_ && fCond.waiters_count_ == 0; + + LeaveCriticalSection(&fCond.waiters_count_lock_); + + // If we're the last waiter thread during this particular broadcast + // then let all the other threads proceed. + if (last_waiter) + // This call atomically signals the <waiters_done_> event and waits until + // it can acquire the <fMutex->fHMutex>. This is required to ensure fairness. + SignalObjectAndWait(fCond.waiters_done_, fMutex->fHMutex, dwTimeWait, FALSE); + else + // Always regain the external mutex since that's the guarantee we + // give to our callers. + WaitForSingleObject(fMutex->fHMutex, INFINITE); + + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Condition::Signal() +{ + // If one or more threads have called Wait(), Signal() wakes up at least + // one of them, possibly more. See POSIX threads documentation for details. + + EnterCriticalSection (&fCond.waiters_count_lock_); + int have_waiters = fCond.waiters_count_ > 0; + LeaveCriticalSection (&fCond.waiters_count_lock_); + + // If there aren't any waiters, then this is a no-op. + if (have_waiters) + ReleaseSemaphore(fCond.sema_, 1, 0); + + return 0; +} + + +//______________________________________________________________________________ +Int_t TWin32Condition::Broadcast() +{ + // Broadcast is like signal but wakes all threads which have called Wait(). + + // This is needed to ensure that <waiters_count_> and <was_broadcast_> are + // consistent relative to each other. + EnterCriticalSection(&fCond.waiters_count_lock_); + int have_waiters = 0; + + if (fCond.waiters_count_ > 0) { + // We are broadcasting, even if there is just one waiter... + // Record that we are broadcasting, which helps optimize + // <pthread_cond_wait> for the non-broadcast case. + fCond.was_broadcast_ = 1; + have_waiters = 1; + } + + if (have_waiters) { + // Wake up all the waiters atomically. + ReleaseSemaphore(fCond.sema_, fCond.waiters_count_, 0); + + LeaveCriticalSection(&fCond.waiters_count_lock_); + + // Wait for all the awakened threads to acquire the counting + // semaphore. + WaitForSingleObject(fCond.waiters_done_, INFINITE); + // This assignment is okay, even without the <waiters_count_lock_> held + // because no other waiter threads can wake up to access it. + fCond.was_broadcast_ = 0; + } + else + LeaveCriticalSection(&fCond.waiters_count_lock_); + + return 0; +} diff --git a/thread/src/TWin32Mutex.cxx b/thread/src/TWin32Mutex.cxx index 6612d4c129b5ced2e3bf7a98a66dd16d1df08a6c..d1778a221236673f9f0c80c61fd03f91f0e5f2f8 100644 --- a/thread/src/TWin32Mutex.cxx +++ b/thread/src/TWin32Mutex.cxx @@ -1,77 +1,77 @@ -// @(#)root/thread:$Name: $:$Id: TWin32Mutex.cxx,v 1.1 2004/11/02 13:07:57 rdm Exp $ -// Author: Bertrand Bellenot 23/10/04 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32Mutex // -// // -// This class provides an interface to the Win32 mutex routines. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TThread.h" -#include "TWin32Mutex.h" - -ClassImp(TWin32Mutex) - -//______________________________________________________________________________ -TWin32Mutex::TWin32Mutex() -{ - // Create a Win32 mutex lock. - - fHMutex = ::CreateMutex(0, 0, 0); - if (!fHMutex) - SysError("TMutex", "CreateMutex error"); -} - -//______________________________________________________________________________ -TWin32Mutex::~TWin32Mutex() -{ - // TMutex dtor. - - ::CloseHandle(fHMutex); -} - -//______________________________________________________________________________ -Int_t TWin32Mutex::Lock() -{ - // Lock the mutex. - - if (::WaitForSingleObject(fHMutex, INFINITE) != WAIT_OBJECT_0) - return -1; - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Mutex::TryLock() -{ - // Try locking the mutex. Returns 0 if mutex can be locked. - - switch (::WaitForSingleObject(fHMutex, 1000)) { - case WAIT_OBJECT_0: - return 1; - case WAIT_TIMEOUT: - return 0; - default: - break; - } - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Mutex::UnLock(void) -{ - // Unlock the mutex. - - if (::ReleaseMutex(fHMutex) == 0) - return -1; - return 0; -} +// @(#)root/thread:$Name: $:$Id: TWin32Mutex.cxx,v 1.2 2004/12/10 12:13:33 rdm Exp $ +// Author: Bertrand Bellenot 23/10/04 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32Mutex // +// // +// This class provides an interface to the Win32 mutex routines. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TThread.h" +#include "TWin32Mutex.h" + +ClassImp(TWin32Mutex) + +//______________________________________________________________________________ +TWin32Mutex::TWin32Mutex() +{ + // Create a Win32 mutex lock. + + fHMutex = ::CreateMutex(0, 0, 0); + if (!fHMutex) + SysError("TMutex", "CreateMutex error"); +} + +//______________________________________________________________________________ +TWin32Mutex::~TWin32Mutex() +{ + // TMutex dtor. + + ::CloseHandle(fHMutex); +} + +//______________________________________________________________________________ +Int_t TWin32Mutex::Lock() +{ + // Lock the mutex. + + if (::WaitForSingleObject(fHMutex, INFINITE) != WAIT_OBJECT_0) + return -1; + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Mutex::TryLock() +{ + // Try locking the mutex. Returns 0 if mutex can be locked. + + switch (::WaitForSingleObject(fHMutex, 1000)) { + case WAIT_OBJECT_0: + return 1; + case WAIT_TIMEOUT: + return 0; + default: + break; + } + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Mutex::UnLock(void) +{ + // Unlock the mutex. + + if (::ReleaseMutex(fHMutex) == 0) + return -1; + return 0; +} diff --git a/thread/src/TWin32Thread.cxx b/thread/src/TWin32Thread.cxx index 4a070b8df1a23541b12a0740533edd926d18d82b..957006644c15c4f6c5a85ee027f1df70237a9ecc 100644 --- a/thread/src/TWin32Thread.cxx +++ b/thread/src/TWin32Thread.cxx @@ -1,166 +1,166 @@ -// @(#)root/thread:$Name: $:$Id: TWin32Thread.cxx,v 1.2 2004/12/10 12:13:33 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32Thread // -// // -// This class provides an interface to the win32 thread routines. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TWin32Thread.h" -#include <process.h> - -ClassImp(TWin32Thread) - -//______________________________________________________________________________ -Int_t TWin32Thread::Run(TThread *th) -{ - // Win32 threads -- spawn new thread (like pthread_create). - // Win32 has a thread handle in addition to the thread ID. - - DWORD dwThreadId; - HANDLE hHandle = CreateThread(0, 0, - (LPTHREAD_START_ROUTINE)&TThread::Function, - th, 0, (DWORD*)&dwThreadId); - if (th->fDetached) { - ::CloseHandle(hHandle); - th->fHandle = 0L; - } else - th->fHandle = (Long_t)hHandle; - - th->fId = SelfId(); - - return hHandle ? 0 : EINVAL; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::Join(TThread *th, void **ret) -{ - // Wait for specified thread execution (if any) to complete - // (like pthread_join). - - DWORD R = WaitForSingleObject((HANDLE)th->fHandle, INFINITE); - - if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) ) { - //::CloseHandle((HANDLE)th->fHandle); - return 0; - } - if ( R == WAIT_TIMEOUT ) - return EAGAIN; - return EINVAL; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::Exit(void *ret) -{ - // Exit the thread. - - ExitThread(0); - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::Kill(TThread *th) -{ - // This is a somewhat dangerous function; it's not - // suggested to Stop() threads a lot. - - return TerminateThread((HANDLE)th->fHandle,0) ? 0 : EINVAL; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::CleanUpPush(void **main, void *free,void *arg) -{ - if (!free) fprintf(stderr, "CleanUpPush ***ERROR*** Routine=0\n"); - new TWin32ThreadCleanUp(main,free,arg); - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::CleanUpPop(void **main,Int_t exe) -{ - if (!*main) return 1; - TWin32ThreadCleanUp *l = (TWin32ThreadCleanUp*)(*main); - if (!l->fRoutine) fprintf(stderr,"CleanUpPop ***ERROR*** Routine=0\n"); - if (exe && l->fRoutine) ((void (*)(void*))(l->fRoutine))(l->fArgument); - *main = l->fNext; delete l; - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::CleanUp(void **main) -{ - fprintf(stderr," CleanUp %lx\n",(ULong_t)*main); - while(!CleanUpPop(main,1)) { } - return 0; -} - -//______________________________________________________________________________ -Long_t TWin32Thread::SelfId() -{ - // Return the current thread's ID. - - return (Long_t)::GetCurrentThreadId(); -} - -//______________________________________________________________________________ -Int_t TWin32Thread::SetCancelOff() -{ - if (gDebug) - Warning("SetCancelOff", "Not implemented on Win32"); - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::SetCancelOn() -{ - if (gDebug) - Warning("SetCancelOn", "Not implemented on Win32"); - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::SetCancelAsynchronous() -{ - if (gDebug) - Warning("SetCancelAsynchronous", "Not implemented on Win32"); - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::SetCancelDeferred() -{ - if (gDebug) - Warning("SetCancelDeferred", "Not implemented on Win32"); - return 0; -} - -//______________________________________________________________________________ -Int_t TWin32Thread::CancelPoint() -{ - if (gDebug) - Warning("CancelPoint", "Not implemented on Win32"); - return 0; -} - -// Clean Up section. PTHREAD implementations of cleanup after cancel are -// too different and often too bad. Temporary I invent my own bicycle. -// V.Perev. - -//______________________________________________________________________________ -TWin32ThreadCleanUp::TWin32ThreadCleanUp(void **main, void *routine, void *arg) -{ - fNext = (TWin32ThreadCleanUp*)*main; - fRoutine = routine; fArgument = arg; - *main = this; -} +// @(#)root/thread:$Name: $:$Id: TWin32Thread.cxx,v 1.3 2004/12/14 15:06:18 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32Thread // +// // +// This class provides an interface to the win32 thread routines. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TWin32Thread.h" +#include <process.h> + +ClassImp(TWin32Thread) + +//______________________________________________________________________________ +Int_t TWin32Thread::Run(TThread *th) +{ + // Win32 threads -- spawn new thread (like pthread_create). + // Win32 has a thread handle in addition to the thread ID. + + DWORD dwThreadId; + HANDLE hHandle = CreateThread(0, 0, + (LPTHREAD_START_ROUTINE)&TThread::Function, + th, 0, (DWORD*)&dwThreadId); + if (th->fDetached) { + ::CloseHandle(hHandle); + th->fHandle = 0L; + } else + th->fHandle = (Long_t)hHandle; + + th->fId = dwThreadId; + + return hHandle ? 0 : EINVAL; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::Join(TThread *th, void **ret) +{ + // Wait for specified thread execution (if any) to complete + // (like pthread_join). + + DWORD R = WaitForSingleObject((HANDLE)th->fHandle, INFINITE); + + if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) ) { + //::CloseHandle((HANDLE)th->fHandle); + return 0; + } + if ( R == WAIT_TIMEOUT ) + return EAGAIN; + return EINVAL; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::Exit(void *ret) +{ + // Exit the thread. + + ExitThread(0); + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::Kill(TThread *th) +{ + // This is a somewhat dangerous function; it's not + // suggested to Stop() threads a lot. + + return TerminateThread((HANDLE)th->fHandle,0) ? 0 : EINVAL; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::CleanUpPush(void **main, void *free,void *arg) +{ + if (!free) fprintf(stderr, "CleanUpPush ***ERROR*** Routine=0\n"); + new TWin32ThreadCleanUp(main,free,arg); + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::CleanUpPop(void **main,Int_t exe) +{ + if (!*main) return 1; + TWin32ThreadCleanUp *l = (TWin32ThreadCleanUp*)(*main); + if (!l->fRoutine) fprintf(stderr,"CleanUpPop ***ERROR*** Routine=0\n"); + if (exe && l->fRoutine) ((void (*)(void*))(l->fRoutine))(l->fArgument); + *main = l->fNext; delete l; + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::CleanUp(void **main) +{ + fprintf(stderr," CleanUp %lx\n",(ULong_t)*main); + while(!CleanUpPop(main,1)) { } + return 0; +} + +//______________________________________________________________________________ +Long_t TWin32Thread::SelfId() +{ + // Return the current thread's ID. + + return (Long_t)::GetCurrentThreadId(); +} + +//______________________________________________________________________________ +Int_t TWin32Thread::SetCancelOff() +{ + if (gDebug) + Warning("SetCancelOff", "Not implemented on Win32"); + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::SetCancelOn() +{ + if (gDebug) + Warning("SetCancelOn", "Not implemented on Win32"); + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::SetCancelAsynchronous() +{ + if (gDebug) + Warning("SetCancelAsynchronous", "Not implemented on Win32"); + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::SetCancelDeferred() +{ + if (gDebug) + Warning("SetCancelDeferred", "Not implemented on Win32"); + return 0; +} + +//______________________________________________________________________________ +Int_t TWin32Thread::CancelPoint() +{ + if (gDebug) + Warning("CancelPoint", "Not implemented on Win32"); + return 0; +} + +// Clean Up section. PTHREAD implementations of cleanup after cancel are +// too different and often too bad. Temporary I invent my own bicycle. +// V.Perev. + +//______________________________________________________________________________ +TWin32ThreadCleanUp::TWin32ThreadCleanUp(void **main, void *routine, void *arg) +{ + fNext = (TWin32ThreadCleanUp*)*main; + fRoutine = routine; fArgument = arg; + *main = this; +} diff --git a/thread/src/TWin32ThreadFactory.cxx b/thread/src/TWin32ThreadFactory.cxx index 88710adc4ed3f4c2ef99dbd2cca91663cb70fc01..fb9a601cc442ac01498e9755f18f2552f7138135 100644 --- a/thread/src/TWin32ThreadFactory.cxx +++ b/thread/src/TWin32ThreadFactory.cxx @@ -1,62 +1,62 @@ -// @(#)root/thread:$Name: $:$Id: TWin32ThreadFactory.cxx,v 1.1.1.1 2000/05/16 17:00:48 rdm Exp $ -// Author: Bertrand Bellenot 20/10/2004 - -/************************************************************************* - * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * - * All rights reserved. * - * * - * For the licensing terms see $ROOTSYS/LICENSE. * - * For the list of contributors see $ROOTSYS/README/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -// // -// TWin32ThreadFactory // -// // -// This is a factory for Win32 thread components. // -// // -////////////////////////////////////////////////////////////////////////// - -#include "TWin32ThreadFactory.h" -#include "TWin32Mutex.h" -#include "TWin32Condition.h" -#include "TWin32Thread.h" - -// Force creation of TWin32ThreadFactory when shared library will be loaded -// (don't explicitely create a TWin32ThreadFactory). -static TWin32ThreadFactory gWin32ThreadFactoryCreator; - -ClassImp(TWin32ThreadFactory) - -//______________________________________________________________________________ -TWin32ThreadFactory::TWin32ThreadFactory(const char *name, const char *title) : - TThreadFactory(name, title) -{ - // Create Win32 thread factory. Also sets global gThreadFactory to this. - - gThreadFactory = this; -} - -//______________________________________________________________________________ -TMutexImp *TWin32ThreadFactory::CreateMutexImp() -{ - // Return a Win32 Mutex. - - return new TWin32Mutex; -} - -//______________________________________________________________________________ -TThreadImp *TWin32ThreadFactory::CreateThreadImp() -{ - // Return a Win32 thread. - - return new TWin32Thread; -} - -//______________________________________________________________________________ -TConditionImp *TWin32ThreadFactory::CreateConditionImp(TMutexImp *m) -{ - // Return a Win32 condition variable. - - return new TWin32Condition(m); -} +// @(#)root/thread:$Name: $:$Id: TWin32ThreadFactory.cxx,v 1.1 2004/11/02 13:07:57 rdm Exp $ +// Author: Bertrand Bellenot 20/10/2004 + +/************************************************************************* + * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TWin32ThreadFactory // +// // +// This is a factory for Win32 thread components. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TWin32ThreadFactory.h" +#include "TWin32Mutex.h" +#include "TWin32Condition.h" +#include "TWin32Thread.h" + +// Force creation of TWin32ThreadFactory when shared library will be loaded +// (don't explicitely create a TWin32ThreadFactory). +static TWin32ThreadFactory gWin32ThreadFactoryCreator; + +ClassImp(TWin32ThreadFactory) + +//______________________________________________________________________________ +TWin32ThreadFactory::TWin32ThreadFactory(const char *name, const char *title) : + TThreadFactory(name, title) +{ + // Create Win32 thread factory. Also sets global gThreadFactory to this. + + gThreadFactory = this; +} + +//______________________________________________________________________________ +TMutexImp *TWin32ThreadFactory::CreateMutexImp() +{ + // Return a Win32 Mutex. + + return new TWin32Mutex; +} + +//______________________________________________________________________________ +TThreadImp *TWin32ThreadFactory::CreateThreadImp() +{ + // Return a Win32 thread. + + return new TWin32Thread; +} + +//______________________________________________________________________________ +TConditionImp *TWin32ThreadFactory::CreateConditionImp(TMutexImp *m) +{ + // Return a Win32 condition variable. + + return new TWin32Condition(m); +}