diff options
Diffstat (limited to 'fltk/fltk/Threads.h')
-rw-r--r-- | fltk/fltk/Threads.h | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/fltk/fltk/Threads.h b/fltk/fltk/Threads.h deleted file mode 100644 index 879d189..0000000 --- a/fltk/fltk/Threads.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef fltk_Threads_h -#define fltk_Threads_h -#include <fltk/FL_API.h> - -#if !defined( _WIN32) || defined(__CYGWIN__) -// pthreads: - -#include <pthread.h> - -namespace fltk { - -/// \name fltk/Threads.h -//@{ - -/** Hides whatever the system uses to identify a thread. Used so - the "toy" interface is portable. */ -typedef pthread_t Thread; - -/** Fork a new thread and make it run \a f(p). Returns negative number - on error, otherwise \a t is set to the new thread. */ -inline int create_thread(Thread& t, void *(*f) (void *), void* p) { - return pthread_create((pthread_t*)&t, 0, f, p); -} - -/** - "Mutual-exclusion lock" for simple multithreaded programs. Calling - lock() will wait until nobody else has the lock and then will - return. <i>Calling lock() more than once will "deadlock"!</i> - To avoid this, use RecursiveMutex. -*/ -class Mutex { - friend class SignalMutex; - pthread_mutex_t mutex; - Mutex(const Mutex&); - Mutex& operator=(const Mutex&); -protected: - Mutex(const pthread_mutexattr_t* a) {pthread_mutex_init(&mutex, a);} -public: - Mutex() {pthread_mutex_init(&mutex, 0);} - void lock() {pthread_mutex_lock(&mutex);} - void unlock() {pthread_mutex_unlock(&mutex);} - bool trylock() {return pthread_mutex_trylock(&mutex) == 0;} - ~Mutex() {pthread_mutex_destroy(&mutex);} -}; - -/** - A portable "semaphore". A thread that holds this lock() can call - wait(), which will unlock it, then wait for another thread to - call signal(), then lock() it again. - - The other thread can call signal() at any time, though usually - it will have called lock() as well, as the lock can be used to - protect the data that is actually being shared between the threads. - - If more than one thread is in wait(), then calling signal_one() - will only wake one of them up. This may be more efficient, and - can be done safely if all threads that call wait() also call - signal_one() just before calling unlock(). - - Warning: wait() can return even if signal() was not called. You - must then check other data (protected by the lock()) to see if - the condition really is fulfilled. In many cases this is the - best implementation, it is also necessary to work around design - errors in Windows, where always returns after 1/2 second to - avoid a deadlock due to the non-atomic nature of Windows calls. -*/ -class SignalMutex : public Mutex { - pthread_cond_t cond; -public: - SignalMutex() : Mutex() {pthread_cond_init(&cond, 0);} - void signal() {pthread_cond_broadcast(&cond);} - void signal_one() {pthread_cond_signal(&cond);} - void wait() {pthread_cond_wait(&cond, &mutex);} -}; - -// Linux supports recursive locks, use them directly, with some cheating: -#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) || defined(PTHREAD_MUTEX_RECURSIVE) - -class RecursiveMutex : public Mutex { -public: - RecursiveMutex(); -}; - -#else // standard pthread mutexes need a bit of work to be recursive: - -/** - "Mutual exclusion lock" to protect data in multithreaded programs. - This is a "recursive lock". Calling lock() will wait until nobody - else has the lock and then will take it. Calling lock() multiple - times by the same thread is allowed, and unlock() must then be - called the same number of times before another thread can get the - lock. -*/ -class RecursiveMutex : public Mutex { - pthread_t owner; - int counter; -public: - RecursiveMutex() : Mutex(), counter(0) {} - void lock() { - if (!counter || owner != pthread_self()) { - Mutex::lock(); - owner = pthread_self(); - counter = 1; - } else { - ++counter; - } - } - bool trylock() { - if (!counter || owner != pthread_self()) { - if (!Mutex::trylock()) return false; - owner = pthread_self(); - } - counter++; - return true; - } - void unlock() {if (!--counter) Mutex::unlock();} -}; - -#endif - -#else // _WIN32: - -# define _WIN32_WINNT 0x0500 -# include <windows.h> -# include <process.h> -// undefine some of the more annoying crap: -# undef DELETE -# undef ERROR -# undef IN -# undef OUT -# undef POINT -# undef far -# undef max -# undef min -# undef near - -namespace fltk { - -typedef unsigned long Thread; - -inline int create_thread(Thread& t, void *(*f) (void *), void* p) { - return t = (Thread)_beginthread((void( __cdecl * )( void * ))f, 0, p); -} - -class FL_API Mutex { - CRITICAL_SECTION cs; - Mutex(const Mutex&); - Mutex& operator=(const Mutex&); -public: - Mutex() {InitializeCriticalSection(&cs);} - void lock() {while (!TryEnterCriticalSection(&cs)) SwitchToThread();} - void unlock() {LeaveCriticalSection(&cs);} - bool trylock() {return TryEnterCriticalSection(&cs);} - ~Mutex() {DeleteCriticalSection(&cs);} -}; - -// After many experiments we have determined that this very stupid -// implementation has the lowest overhead: -class FL_API SignalMutex : public Mutex { -public: - SignalMutex() : Mutex() {} - void signal() {} - void signal_one() {} - void wait() { - // the following three calls should be atomic, sigh... - unlock(); - SwitchToThread(); - lock(); - } -}; - -typedef Mutex RecursiveMutex; - -#endif - -/** - C++ convienence object for locking a Mutex. - Creating a local one of these will lock() the mutex and it means - unlock() will be called no matter how a function exits, because - the destructor ~Guard() does an unlock(). - -\code - static fltk::Mutex mutex; - function() { - fltk::Guard guard(mutex); - do_stuff; - throw_exceptions; - if (test()) return; - etc; - } -\endcode - -*/ -class FL_API Guard { - Mutex& lock; - public: - Guard(Mutex& m) : lock(m) {lock.lock();} - Guard(Mutex* m) : lock(*m) {lock.lock();} - ~Guard() {lock.unlock();} -}; - -//@} - -} - -#endif |