Merge branch 'develop' of https://github.com/DFHack/dfhack into Units
commit
4e97269312
@ -1,249 +0,0 @@
|
||||
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; -*-
|
||||
Copyright (c) 2010-2012 Marcus Geelnard
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*/
|
||||
|
||||
#ifndef _FAST_MUTEX_H_
|
||||
#define _FAST_MUTEX_H_
|
||||
|
||||
/// @file
|
||||
|
||||
// Which platform are we on?
|
||||
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
|
||||
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
|
||||
#define _TTHREAD_WIN32_
|
||||
#else
|
||||
#define _TTHREAD_POSIX_
|
||||
#endif
|
||||
#define _TTHREAD_PLATFORM_DEFINED_
|
||||
#endif
|
||||
|
||||
// Check if we can support the assembly language level implementation (otherwise
|
||||
// revert to the system API)
|
||||
#if (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))) || \
|
||||
(defined(_MSC_VER) && (defined(_M_IX86) /*|| defined(_M_X64)*/)) || \
|
||||
(defined(__GNUC__) && (defined(__ppc__)))
|
||||
#define _FAST_MUTEX_ASM_
|
||||
#else
|
||||
#define _FAST_MUTEX_SYS_
|
||||
#endif
|
||||
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
#define NOMINMAX
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#ifdef __UNDEF_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef __UNDEF_LEAN_AND_MEAN
|
||||
#endif
|
||||
#else
|
||||
#ifdef _FAST_MUTEX_ASM_
|
||||
#include <sched.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace tthread {
|
||||
|
||||
/// Fast mutex class.
|
||||
/// This is a mutual exclusion object for synchronizing access to shared
|
||||
/// memory areas for several threads. It is similar to the tthread::mutex class,
|
||||
/// but instead of using system level functions, it is implemented as an atomic
|
||||
/// spin lock with very low CPU overhead.
|
||||
///
|
||||
/// The \c fast_mutex class is NOT compatible with the \c condition_variable
|
||||
/// class (however, it IS compatible with the \c lock_guard class). It should
|
||||
/// also be noted that the \c fast_mutex class typically does not provide
|
||||
/// as accurate thread scheduling as a the standard \c mutex class does.
|
||||
///
|
||||
/// Because of the limitations of the class, it should only be used in
|
||||
/// situations where the mutex needs to be locked/unlocked very frequently.
|
||||
///
|
||||
/// @note The "fast" version of this class relies on inline assembler language,
|
||||
/// which is currently only supported for 32/64-bit Intel x86/AMD64 and
|
||||
/// PowerPC architectures on a limited number of compilers (GNU g++ and MS
|
||||
/// Visual C++).
|
||||
/// For other architectures/compilers, system functions are used instead.
|
||||
class fast_mutex {
|
||||
public:
|
||||
/// Constructor.
|
||||
#if defined(_FAST_MUTEX_ASM_)
|
||||
fast_mutex() : mLock(0) {}
|
||||
#else
|
||||
fast_mutex()
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
InitializeCriticalSection(&mHandle);
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
pthread_mutex_init(&mHandle, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_FAST_MUTEX_ASM_)
|
||||
/// Destructor.
|
||||
~fast_mutex()
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
DeleteCriticalSection(&mHandle);
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
pthread_mutex_destroy(&mHandle);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Lock the mutex.
|
||||
/// The method will block the calling thread until a lock on the mutex can
|
||||
/// be obtained. The mutex remains locked until \c unlock() is called.
|
||||
/// @see lock_guard
|
||||
inline void lock()
|
||||
{
|
||||
#if defined(_FAST_MUTEX_ASM_)
|
||||
bool gotLock;
|
||||
do {
|
||||
gotLock = try_lock();
|
||||
if(!gotLock)
|
||||
{
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
Sleep(0);
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
sched_yield();
|
||||
#endif
|
||||
}
|
||||
} while(!gotLock);
|
||||
#else
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
EnterCriticalSection(&mHandle);
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
pthread_mutex_lock(&mHandle);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Try to lock the mutex.
|
||||
/// The method will try to lock the mutex. If it fails, the function will
|
||||
/// return immediately (non-blocking).
|
||||
/// @return \c true if the lock was acquired, or \c false if the lock could
|
||||
/// not be acquired.
|
||||
inline bool try_lock()
|
||||
{
|
||||
#if defined(_FAST_MUTEX_ASM_)
|
||||
int oldLock;
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
asm volatile (
|
||||
"movl $1,%%eax\n\t"
|
||||
"xchg %%eax,%0\n\t"
|
||||
"movl %%eax,%1\n\t"
|
||||
: "=m" (mLock), "=m" (oldLock)
|
||||
:
|
||||
: "%eax", "memory"
|
||||
);
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
int *ptrLock = &mLock;
|
||||
__asm {
|
||||
mov eax,1
|
||||
mov ecx,ptrLock
|
||||
xchg eax,[ecx]
|
||||
mov oldLock,eax
|
||||
}
|
||||
#elif defined(__GNUC__) && (defined(__ppc__))
|
||||
int newLock = 1;
|
||||
asm volatile (
|
||||
"\n1:\n\t"
|
||||
"lwarx %0,0,%1\n\t"
|
||||
"cmpwi 0,%0,0\n\t"
|
||||
"bne- 2f\n\t"
|
||||
"stwcx. %2,0,%1\n\t"
|
||||
"bne- 1b\n\t"
|
||||
"isync\n"
|
||||
"2:\n\t"
|
||||
: "=&r" (oldLock)
|
||||
: "r" (&mLock), "r" (newLock)
|
||||
: "cr0", "memory"
|
||||
);
|
||||
#endif
|
||||
return (oldLock == 0);
|
||||
#else
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
return TryEnterCriticalSection(&mHandle) ? true : false;
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
return (pthread_mutex_trylock(&mHandle) == 0) ? true : false;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Unlock the mutex.
|
||||
/// If any threads are waiting for the lock on this mutex, one of them will
|
||||
/// be unblocked.
|
||||
inline void unlock()
|
||||
{
|
||||
#if defined(_FAST_MUTEX_ASM_)
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
asm volatile (
|
||||
"movl $0,%%eax\n\t"
|
||||
"xchg %%eax,%0\n\t"
|
||||
: "=m" (mLock)
|
||||
:
|
||||
: "%eax", "memory"
|
||||
);
|
||||
#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
int *ptrLock = &mLock;
|
||||
__asm {
|
||||
mov eax,0
|
||||
mov ecx,ptrLock
|
||||
xchg eax,[ecx]
|
||||
}
|
||||
#elif defined(__GNUC__) && (defined(__ppc__))
|
||||
asm volatile (
|
||||
"sync\n\t" // Replace with lwsync where possible?
|
||||
: : : "memory"
|
||||
);
|
||||
mLock = 0;
|
||||
#endif
|
||||
#else
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
LeaveCriticalSection(&mHandle);
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
pthread_mutex_unlock(&mHandle);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(_FAST_MUTEX_ASM_)
|
||||
int mLock;
|
||||
#else
|
||||
#if defined(_TTHREAD_WIN32_)
|
||||
CRITICAL_SECTION mHandle;
|
||||
#elif defined(_TTHREAD_POSIX_)
|
||||
pthread_mutex_t mHandle;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // _FAST_MUTEX_H_
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit b4dfab6d08635da8b01504a289e8cf4e62c859c5
|
||||
Subproject commit cbeed8b52482ce749fc2ff13a9db9733931e7da0
|
@ -1 +1 @@
|
||||
Subproject commit b9fc28836f34f7ce1be64de94afd90184a341c7d
|
||||
Subproject commit 5b7e7743a1372b929acb2ccb75080e139ac11691
|
Loading…
Reference in New Issue