Remove ancient trunk folder from svn repository
[synfig.git] / ETL / ETL / _thread.h
diff --git a/ETL/ETL/_thread.h b/ETL/ETL/_thread.h
new file mode 100644 (file)
index 0000000..8f70be8
--- /dev/null
@@ -0,0 +1,515 @@
+/*! ========================================================================
+** Extended Template and Library
+** Thread Abstraction Class Implementation
+** $Id$
+**
+** Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**
+** This package is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 2 of
+** the License, or (at your option) any later version.
+**
+** This package is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** General Public License for more details.
+**
+** === N O T E S ===========================================================
+**
+** This is an internal header file, included by other ETL headers.
+** You should not attempt to use it directly.
+**
+** ========================================================================= */
+
+/* === S T A R T =========================================================== */
+
+#ifndef __ETL__THREAD_H_
+#define __ETL__THREAD_H_
+
+/* === H E A D E R S ======================================================= */
+
+#define __USE_GNU
+
+#ifdef HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#ifdef HAVE_SCHED_H
+# include <sched.h>
+#endif
+
+#ifdef HAVE_CREATETHREAD
+# include <windows.h>
+#endif
+
+/* === M A C R O S ========================================================= */
+
+#if ( defined (HAVE_PTHREAD_CREATE) || defined (HAVE_CLONE) || defined (HAVE_CREATETHREAD) ) && !defined (NO_THREADS)
+# define CALLISTO_THREADS
+#endif
+
+#define THREAD_ENTRYPOINT
+
+/* === C L A S S E S & S T R U C T S ======================================= */
+
+#if defined(CALLISTO_THREADS) && defined(HAVE_PTHREAD_CREATE)
+static inline void Yield(void)
+{
+       sched_yield();
+       pthread_testcancel();
+}
+#else
+#ifdef Yield
+       #undef Yield
+#endif
+inline void Yield(void) { }
+#endif
+
+#ifdef CALLISTO_THREADS
+
+#ifdef HAVE_PTHREAD_CREATE
+
+class Thread
+{
+public:
+       typedef void* entrypoint_return;
+private:
+
+       pthread_t thread;
+       int *references;
+       entrypoint_return (*entrypoint)(void *);
+       void *context;
+public:
+       Thread(void *(*ep)(void *)=NULL,void *context=NULL):
+               references(NULL),entrypoint(ep),context(context) { }
+       Thread(const Thread &t)
+       {
+               thread=t.thread;
+               references=t.references;
+               entrypoint=t.entrypoint;
+               context=t.context;
+               if(references)
+                       (*references)++;
+       }
+       const Thread &operator=(const Thread &rhs)
+       {
+               if(references)
+               {
+                       (*references)--;
+                       if(*references==0)
+                               stop();
+               }
+               thread=rhs.thread;
+               references=rhs.references;
+               entrypoint=rhs.entrypoint;
+               context=rhs.context;
+               if(references)
+                       (*references)++;
+               return *this;
+       }
+
+       void start(void)
+       {
+               references = new int;
+               *references = 1;
+               pthread_create(&thread,NULL,entrypoint,context);
+//             pthread_detach(thread);
+       }
+
+       void stop(void)
+       {
+               delete references;
+               references=NULL;
+               void *exit_status;
+               pthread_cancel(thread);
+               pthread_join(thread,&exit_status);
+       }
+
+       static void TestStop()
+       {
+               pthread_testcancel();
+       }
+
+       static void SyncStop()
+       {
+               int i;
+               pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,&i);
+       }
+
+       static void AsyncStop()
+       {
+               int i;
+               pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&i);
+       }
+
+       ~Thread()
+       {
+               if(references)
+               {
+                       (*references)--;
+                       if(*references==0)
+                               stop();
+               }
+       }
+};
+
+class Mutex
+{
+       pthread_mutex_t mutex;
+       pthread_t locker;
+       int depth;
+public:
+
+       Mutex()
+       {
+               pthread_mutexattr_t attr;
+               pthread_mutexattr_init(&attr);
+               //#ifdef PTHREAD_PRIO_INHERIT
+               //pthread_mutexattr_setprioceiling(&attr,PTHREAD_PRIO_INHERIT);
+               //#endif
+               #ifdef PTHREAD_MUTEX_RECURSIVE
+               pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
+               #endif
+               pthread_mutex_init(&mutex,&attr);
+               pthread_mutexattr_destroy(&attr);
+               locker=0;
+               depth=0;
+       }
+
+       ~Mutex()
+       { pthread_mutex_destroy(&mutex); }
+
+       void Lock(void)
+       {
+               if(!locker || locker!=pthread_self())
+               {
+                       pthread_mutex_lock(&mutex);
+                       locker=pthread_self();
+                       depth=0;
+                       return;
+               }
+               depth++;
+       }
+
+       bool TryLock(void)
+       { return !(bool) pthread_mutex_trylock(&mutex); }
+
+       void UnLock(void)
+       {
+               if(depth)
+               {
+                       depth--;
+                       return;
+               }
+               pthread_mutex_unlock(&mutex);
+               locker=0;
+       }
+};
+
+#ifdef HAVE_PTHREAD_RW_LOCK_INIT
+class ReadWriteLock
+{
+       pthread_rwlock_t rwlock;
+public:
+
+       ReadWriteLock()
+       { pthread_rwlock_init(&rwlock,NULL); }
+
+       ~ReadWriteLock()
+       { pthread_rwlock_destroy(&rwlock); }
+
+       void LockRead(void)
+       { pthread_rwlock_rdlock(&rwlock); }
+
+       void LockWrite(void)
+       { pthread_rwlock_wrlock(&rwlock); }
+
+       bool TryLockRead(void)
+       { return !(bool)pthread_rwlock_tryrdlock(&rwlock); }
+
+       bool TryLockWrite(void)
+       { return !(bool)pthread_rwlock_trywrlock(&rwlock); }
+
+       void UnLockWrite(void)
+       { pthread_rwlock_unlock(&rwlock); }
+
+       void UnLockRead(void)
+       { pthread_rwlock_unlock(&rwlock); }
+};
+#else
+//*
+class ReadWriteLock : public Mutex
+{
+public:
+
+       ReadWriteLock()
+       {  }
+
+       ~ReadWriteLock()
+       {  }
+
+       void LockRead(void)
+       { Lock(); }
+
+       void LockWrite(void)
+       { Lock(); }
+
+       bool TryLockRead(void)
+       { return TryLock(); }
+
+       bool TryLockWrite(void)
+       { return TryLock(); }
+
+       void UnLockWrite(void)
+       { UnLock(); }
+
+       void UnLockRead(void)
+       { UnLock(); }
+};
+#endif
+
+/*
+class Condition
+{
+       pthread_cond_t cond;
+       pthread_mutex_t mutex;
+public:
+       Condition()
+       { pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,NULL); }
+       ~Condition()
+       { pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex);}
+       void operator()(void)
+       { pthread_cond_signal(&cond); }
+       void Wait(void)
+       {
+               pthread_mutex_lock(&mutex);
+               pthread_cond_wait(&cond,&mutex);
+               pthread_mutex_unlock(&mutex);
+       }
+};
+*/
+
+#else // if defined HAVE_PTHREAD
+#ifdef HAVE_CREATETHREAD
+
+
+#ifdef THREAD_ENTRYPOINT
+#undef THREAD_ENTRYPOINT
+#endif
+#define THREAD_ENTRYPOINT      __stdcall
+class Thread
+{
+public:
+       typedef unsigned long entrypoint_return;
+private:
+
+       unsigned long thread;
+       HANDLE handle;
+       int *references;
+
+       entrypoint_return  (THREAD_ENTRYPOINT *entrypoint)(void *);
+
+       void *context;
+
+       HDC hdc;
+       HGLRC hglrc;
+
+       static entrypoint_return THREAD_ENTRYPOINT thread_prefix(void*data)
+       {
+               Thread *thread=(Thread *)data;
+
+               if(thread->hglrc)
+                       wglMakeCurrent(thread->hdc, thread->hglrc);
+
+               return thread->entrypoint(thread->context);
+       }
+
+public:
+       Thread(entrypoint_return  (THREAD_ENTRYPOINT *ep)(void *)=NULL,void *context=NULL):
+               references(NULL),entrypoint(ep),context(context) { }
+       Thread(const Thread &t)
+       {
+               thread=t.thread;
+               handle=t.handle;
+               references=t.references;
+               entrypoint=t.entrypoint;
+               context=t.context;
+               handle=NULL;
+               if(references)
+                       (*references)++;
+       }
+       const Thread &operator=(const Thread &rhs)
+       {
+               if(references)
+               {
+                       (*references)--;
+                       if(*references==0)
+                               stop();
+               }
+               thread=rhs.thread;
+               handle=rhs.handle;
+               references=rhs.references;
+               entrypoint=rhs.entrypoint;
+               context=rhs.context;
+               if(references)
+                       (*references)++;
+               return *this;
+       }
+
+       void start(void)
+       {
+               references = new int;
+               *references = 1;
+
+               hglrc=wglGetCurrentContext();
+               hdc=wglGetCurrentDC();
+
+               handle=CreateThread(
+                       NULL,           // Security stuff
+                       0,      // STACK
+                       thread_prefix,    // thread function
+                       (void*)this,                       // thread argument
+                       0,                    // creation option
+                       &thread                        // thread identifier
+               );
+       }
+
+       void stop(void)
+       {
+               delete references;
+               references=NULL;
+
+               TerminateThread(handle, FALSE);
+       }
+
+       int wait(void)
+       {
+               if(handle)
+               {
+                       WaitForSingleObject(handle, INFINITE);
+                       CloseHandle(handle);
+               }
+               return 0;
+       }
+
+       static void TestStop()
+       {
+       }
+
+       static void SyncStop()
+       {
+       }
+
+       static void AsyncStop()
+       {
+       }
+
+       ~Thread()
+       {
+               if(references)
+               {
+                       (*references)--;
+                       if(*references==0)
+                               stop();
+               }
+       }
+};
+
+class Mutex
+{
+       HANDLE handle;
+public:
+
+       Mutex()
+       {
+               handle = CreateMutex(NULL, FALSE, NULL);
+       }
+
+       ~Mutex()
+       {
+               CloseHandle(handle);
+       }
+
+       void Lock(void)
+       {
+               WaitForSingleObject(handle, INFINITE);
+       }
+
+       bool TryLock(void)
+       {
+               return WaitForSingleObject(handle, INFINITE)==WAIT_FAILED;
+       }
+
+       void UnLock(void)
+       {
+               ReleaseMutex(handle);
+       }
+};
+
+
+#endif // if defined HAVE_CREATETHREAD
+#endif // if defined HAVE_PTHREAD_CREATE
+#endif // if defined CALLISTO_THREADS
+
+
+#if !defined(CALLISTO_THREADS)
+// Dummy object used when not threading
+class ReadWriteLock
+{
+public:
+
+       ReadWriteLock() {}
+       ~ReadWriteLock() {}
+       void LockRead(void) {}
+       void LockWrite(void) {}
+       bool TryLockRead(void) {return true;}
+       bool TryLockWrite(void) {return true;}
+       void UnLockRead(void) {}
+       void UnLockWrite(void) {}
+};
+
+class Mutex
+{
+public:
+
+       Mutex(){}
+       ~Mutex(){}
+       void Lock(void){}
+       bool TryLock(void){return true;}
+       void UnLock(void){}
+};
+
+#endif
+
+class Condition : private Mutex
+{
+       bool flag;
+public:
+       Condition()
+       { flag=false; }
+       ~Condition()
+       { }
+       void operator()(void)
+       { flag=true; }
+       void Wait(void)
+       {
+               Lock();
+               while(!flag)Yield();
+               flag=false;
+               UnLock();
+       }
+       void WaitNext(void)
+       {
+               Lock();
+               flag=false;
+               while(!flag)Yield();
+               UnLock();
+       }
+};
+
+/* === E X T E R N S ======================================================= */
+
+/* === E N D =============================================================== */
+
+#endif