diff options
Diffstat (limited to 'src/shared/Mthread.cpp')
-rw-r--r-- | src/shared/Mthread.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/shared/Mthread.cpp b/src/shared/Mthread.cpp new file mode 100644 index 00000000000..0dfaac4fcf7 --- /dev/null +++ b/src/shared/Mthread.cpp @@ -0,0 +1,205 @@ +/* + Cross-platform thread handling + Copyright (C) 2005 Andrew Zabolotny + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "Mthread.h" + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE_CC__) +# define MANGOS_PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE +#else +# define MANGOS_PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP +#endif + +#if PLATFORM != PLATFORM_WINDOWS + +MThread::MThread () +{ + tid = 0; +} + +MThread::~MThread () +{ + /* Kill thread if this is not the current thread */ + if (tid && (pthread_self () != tid)) + { + pthread_cancel (tid); + pthread_join (tid, NULL); + } +} + +static void *thread_start_routine (void *arg) +{ + MThread *newthr = (MThread *)arg; + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + newthr->routine (newthr->arg); + return NULL; +} + +MThread *MThread::Start (void (*routine) (void *arg), void *arg) +{ + MThread *newthr = new MThread (); + newthr->routine = routine; + newthr->arg = arg; + int rc = pthread_create (&newthr->tid, NULL, thread_start_routine, newthr); + if (rc) + { + newthr->DecRef (); + return NULL; + } + + return newthr; +} + +pthread_mutexattr_t MMutex::attr; +int MMutex::attr_refcount = 0; + +MMutex::MMutex () +{ + if (!attr_refcount++) + { + pthread_mutexattr_init (&attr); + pthread_mutexattr_settype (&attr, MANGOS_PTHREAD_MUTEX_RECURSIVE); + } + + pthread_mutex_init (&mutex, &attr); +} + +MMutex::~MMutex () +{ + pthread_mutex_destroy (&mutex); + if (!--attr_refcount) + pthread_mutexattr_destroy (&attr); +} + +bool MMutex::Lock () +{ + return (pthread_mutex_lock (&mutex) == 0); +} + +bool MMutex::TryLock () +{ + return (pthread_mutex_trylock (&mutex) == 0); +} + +void MMutex::Unlock () +{ + pthread_mutex_unlock (&mutex); +} + +MMutex *MMutex::Create () +{ + return new MMutex (); +} + +#else //windows + +MThread::MThread() +{ + th = NULL; +} + +MThread::~MThread () +{ + /* Kill thread if this is not current thread */ + if (th && (GetCurrentThreadId () != id)) + { + TerminateThread (th, 0); + WaitForSingleObject (th, INFINITE); + CloseHandle (th); + } +} + +bool MThread::SetPriority (ThreadPriority prio) +{ + int p; + switch (prio) + { + case IDLE: p = THREAD_PRIORITY_IDLE; break; + case LOWER: p = THREAD_PRIORITY_LOWEST; break; + case LOW: p = THREAD_PRIORITY_BELOW_NORMAL; break; + case NORMAL: p = THREAD_PRIORITY_NORMAL; break; + case HIGH: p = THREAD_PRIORITY_ABOVE_NORMAL; break; + case HIGHER: p = THREAD_PRIORITY_HIGHEST; break; + case REALTIME: p = THREAD_PRIORITY_TIME_CRITICAL; break; + default: p = THREAD_PRIORITY_NORMAL; break; + } + return SetThreadPriority (th, p); +} + +static DWORD WINAPI thread_start_routine (void *arg) +//static void thread_start_routine (void *arg) +{ + MThread *newthr = (MThread *)arg; + newthr->id = GetCurrentThreadId (); + newthr->routine (newthr->arg); + return 0; +} + +MThread *MThread::Start (void (*routine) (void *arg), void *arg) +{ + DWORD dwtid; + MThread *newthr = new MThread (); + newthr->routine = routine; + newthr->arg = arg; + newthr->th = CreateThread (NULL, WIN32_THREAD_STACK_SIZE, thread_start_routine, newthr, 0, &dwtid); + //newthr->th = (HANDLE)_beginthread(thread_start_routine, 0, newthr); + if (!newthr->th) + { + newthr->DecRef (); + return NULL; + } + return newthr; +} + +MMutex::MMutex () +{ + sem = CreateMutex (NULL, FALSE, NULL); +} + +MMutex::~MMutex () +{ + CloseHandle (sem); +} + +bool MMutex::Lock () +{ + return (WaitForSingleObject (sem, INFINITE) != WAIT_FAILED); +} + +bool MMutex::TryLock () +{ + DWORD state = WaitForSingleObject (sem, 0); + return (state == WAIT_OBJECT_0) && (state != WAIT_ABANDONED); +} + +void MMutex::Unlock () +{ + ReleaseMutex (sem); +} + +MMutex *MMutex::Create () +{ + MMutex *mutex = new MMutex (); + if (!mutex->sem) + { + mutex->DecRef (); + return NULL; + } + return mutex; +} +#endif |