mutex_spinlock
This commit is contained in:
parent
84550f0527
commit
7986aaa0c3
|
|
@ -599,6 +599,14 @@
|
|||
// run-time overhead for these tests.
|
||||
#defer DEBUG_THREADS $[<= $[OPTIMIZE], 2]
|
||||
|
||||
// Define this true to implement mutexes and condition variables via
|
||||
// user-space spinlocks, instead of via OS-provided constructs. This
|
||||
// is almost never a good idea, except possibly in very specialized
|
||||
// cases when you are building Panda for a particular application, on
|
||||
// a particular platform, and you are sure you won't have more threads
|
||||
// than CPU's. Even then, OS-based locking is probably better.
|
||||
#define MUTEX_SPINLOCK
|
||||
|
||||
// Do you want to build the network interface? What additional libraries
|
||||
// are required? Currently, this requires NSPR.
|
||||
#define NET_IPATH
|
||||
|
|
|
|||
|
|
@ -235,6 +235,9 @@ $[cdefine HAVE_THREADS]
|
|||
/* Define to enable deadlock detection, mutex recursion checks, etc. */
|
||||
$[cdefine DEBUG_THREADS]
|
||||
|
||||
/* Define to implement mutexes and condition variables via a user-space spinlock. */
|
||||
$[cdefine MUTEX_SPINLOCK]
|
||||
|
||||
/* Define if we want to compile the net code. */
|
||||
$[cdefine HAVE_NET]
|
||||
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@
|
|||
|
||||
#set HAVE_THREADS $[HAVE_THREADS]
|
||||
#set DEBUG_THREADS $[DEBUG_THREADS]
|
||||
#set MUTEX_SPINLOCK $[MUTEX_SPINLOCK]
|
||||
|
||||
#set NET_IPATH $[unixfilename $[NET_IPATH]]
|
||||
#set NET_LPATH $[unixfilename $[NET_LPATH]]
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
mutexLinuxImpl.h mutexLinuxImpl.I \
|
||||
mutexPosixImpl.h mutexPosixImpl.I \
|
||||
mutexWin32Impl.h mutexWin32Impl.I \
|
||||
mutexSpinlockImpl.h mutexSpinlockImpl.I \
|
||||
nearly_zero.h \
|
||||
numeric_types.h \
|
||||
selectThreadImpl.h \
|
||||
|
|
@ -43,7 +44,8 @@
|
|||
mutexNsprImpl.cxx \
|
||||
mutexLinuxImpl.cxx \
|
||||
mutexPosixImpl.cxx \
|
||||
mutexWin32Impl.cxx
|
||||
mutexWin32Impl.cxx \
|
||||
mutexSpinlockImpl.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
atomicAdjust.h \
|
||||
|
|
@ -63,6 +65,7 @@
|
|||
mutexLinuxImpl.h mutexLinuxImpl.I \
|
||||
mutexPosixImpl.h mutexPosixImpl.I \
|
||||
mutexWin32Impl.h mutexWin32Impl.I \
|
||||
mutexSpinlockImpl.h mutexSpinlockImpl.I \
|
||||
nearly_zero.h \
|
||||
numeric_types.h \
|
||||
selectThreadImpl.h \
|
||||
|
|
|
|||
|
|
@ -35,11 +35,22 @@ typedef AtomicAdjustDummyImpl AtomicAdjust;
|
|||
#include "atomicAdjustI386Impl.h"
|
||||
typedef AtomicAdjustI386Impl AtomicAdjust;
|
||||
|
||||
// These symbols are defined if the compare_and_exchange() methods are
|
||||
// implemented natively, without recourse to external locks. If these
|
||||
// are not defined, users may elect to implement an operation with
|
||||
// some other method than compare_and_exchange(), which might be
|
||||
// faster.
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
|
||||
|
||||
#elif defined(THREAD_WIN32_IMPL)
|
||||
|
||||
#include "atomicAdjustWin32Impl.h"
|
||||
typedef AtomicAdjustWin32Impl AtomicAdjust;
|
||||
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
|
||||
|
||||
#elif defined(THREAD_LINUX_IMPL)
|
||||
|
||||
#error Linux native threads are currently implemented only for i386; use Posix threads instead.
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
// Description: Atomically increments the indicated variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AtomicAdjustDummyImpl::
|
||||
inc(PN_int32 &var) {
|
||||
inc(TVOLATILE PN_int32 &var) {
|
||||
++var;
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ inc(PN_int32 &var) {
|
|||
// is zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AtomicAdjustDummyImpl::
|
||||
dec(PN_int32 &var) {
|
||||
dec(TVOLATILE PN_int32 &var) {
|
||||
return (--var) != 0;
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ dec(PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustDummyImpl::
|
||||
set(PN_int32 &var, PN_int32 new_value) {
|
||||
set(TVOLATILE PN_int32 &var, PN_int32 new_value) {
|
||||
PN_int32 orig_value = var;
|
||||
var = new_value;
|
||||
return orig_value;
|
||||
|
|
@ -62,7 +62,7 @@ set(PN_int32 &var, PN_int32 new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustDummyImpl::
|
||||
get(const PN_int32 &var) {
|
||||
get(const TVOLATILE PN_int32 &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ get(const PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustDummyImpl::
|
||||
set_ptr(void *&var, void *new_value) {
|
||||
set_ptr(void * TVOLATILE &var, void *new_value) {
|
||||
void *orig_value = var;
|
||||
var = new_value;
|
||||
return orig_value;
|
||||
|
|
@ -89,7 +89,7 @@ set_ptr(void *&var, void *new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustDummyImpl::
|
||||
get_ptr(void * const &var) {
|
||||
get_ptr(void * const TVOLATILE &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ get_ptr(void * const &var) {
|
|||
// return_value == old_value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustDummyImpl::
|
||||
compare_and_exchange(PN_int32 &mem, PN_int32 old_value,
|
||||
compare_and_exchange(TVOLATILE PN_int32 &mem, PN_int32 old_value,
|
||||
PN_int32 new_value) {
|
||||
PN_int32 orig_value = mem;
|
||||
if (mem == old_value) {
|
||||
|
|
@ -121,7 +121,7 @@ compare_and_exchange(PN_int32 &mem, PN_int32 old_value,
|
|||
// As above, but works on pointers instead of integers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustDummyImpl::
|
||||
compare_and_exchange_ptr(void *&mem, void *old_value,
|
||||
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value,
|
||||
void *new_value) {
|
||||
void *orig_value = mem;
|
||||
if (mem == old_value) {
|
||||
|
|
|
|||
|
|
@ -17,9 +17,4 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_DUMMY_IMPL
|
||||
|
||||
#include "atomicAdjustDummyImpl.h"
|
||||
|
||||
#endif // THREAD_DUMMY_IMPL
|
||||
|
|
|
|||
|
|
@ -22,13 +22,8 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_DUMMY_IMPL
|
||||
|
||||
#include "numeric_types.h"
|
||||
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AtomicAdjustDummyImpl
|
||||
// Description : A trivial implementation for atomic adjustments for
|
||||
|
|
@ -37,25 +32,23 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL AtomicAdjustDummyImpl {
|
||||
public:
|
||||
INLINE static void inc(PN_int32 &var);
|
||||
INLINE static bool dec(PN_int32 &var);
|
||||
INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const PN_int32 &var);
|
||||
INLINE static void inc(TVOLATILE PN_int32 &var);
|
||||
INLINE static bool dec(TVOLATILE PN_int32 &var);
|
||||
INLINE static PN_int32 set(TVOLATILE PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const TVOLATILE PN_int32 &var);
|
||||
|
||||
INLINE static void *set_ptr(void *&var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const &var);
|
||||
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const TVOLATILE &var);
|
||||
|
||||
INLINE static PN_int32 compare_and_exchange(PN_int32 &mem,
|
||||
INLINE static PN_int32 compare_and_exchange(TVOLATILE PN_int32 &mem,
|
||||
PN_int32 old_value,
|
||||
PN_int32 new_value);
|
||||
|
||||
INLINE static void *compare_and_exchange_ptr(void *&mem,
|
||||
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem,
|
||||
void *old_value,
|
||||
void *new_value);
|
||||
};
|
||||
|
||||
#include "atomicAdjustDummyImpl.I"
|
||||
|
||||
#endif // THREAD_DUMMY_IMPL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@
|
|||
// Description: Atomically increments the indicated variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AtomicAdjustI386Impl::
|
||||
inc(volatile PN_int32 &var) {
|
||||
inc(TVOLATILE PN_int32 &var) {
|
||||
#ifdef _M_IX86
|
||||
// Windows case
|
||||
volatile PN_int32 *var_ptr = &var;
|
||||
TVOLATILE PN_int32 *var_ptr = &var;
|
||||
__asm {
|
||||
mov edx, var_ptr;
|
||||
lock inc dword ptr [edx];
|
||||
|
|
@ -47,11 +47,11 @@ inc(volatile PN_int32 &var) {
|
|||
// is zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AtomicAdjustI386Impl::
|
||||
dec(volatile PN_int32 &var) {
|
||||
dec(TVOLATILE PN_int32 &var) {
|
||||
unsigned char c;
|
||||
#ifdef _M_IX86
|
||||
// Windows case
|
||||
volatile PN_int32 *var_ptr = &var;
|
||||
TVOLATILE PN_int32 *var_ptr = &var;
|
||||
__asm {
|
||||
mov edx, var_ptr;
|
||||
lock dec dword ptr [edx];
|
||||
|
|
@ -73,7 +73,7 @@ dec(volatile PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustI386Impl::
|
||||
set(PN_int32 &var, PN_int32 new_value) {
|
||||
set(TVOLATILE PN_int32 &var, PN_int32 new_value) {
|
||||
PN_int32 orig_value = var;
|
||||
var = new_value;
|
||||
return orig_value;
|
||||
|
|
@ -89,7 +89,7 @@ set(PN_int32 &var, PN_int32 new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustI386Impl::
|
||||
get(const PN_int32 &var) {
|
||||
get(const TVOLATILE PN_int32 &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ get(const PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustI386Impl::
|
||||
set_ptr(void *&var, void *new_value) {
|
||||
set_ptr(void * TVOLATILE &var, void *new_value) {
|
||||
void *orig_value = var;
|
||||
var = new_value;
|
||||
return orig_value;
|
||||
|
|
@ -116,7 +116,7 @@ set_ptr(void *&var, void *new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustI386Impl::
|
||||
get_ptr(void * const &var) {
|
||||
get_ptr(void * const TVOLATILE &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -140,12 +140,12 @@ get_ptr(void * const &var) {
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustI386Impl::
|
||||
compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
|
||||
compare_and_exchange(TVOLATILE PN_int32 &mem, PN_int32 old_value,
|
||||
PN_int32 new_value) {
|
||||
PN_int32 prev;
|
||||
#ifdef _M_IX86
|
||||
// Windows case
|
||||
volatile PN_int32 *mem_ptr = &mem;
|
||||
TVOLATILE PN_int32 *mem_ptr = &mem;
|
||||
__asm {
|
||||
mov edx, mem_ptr;
|
||||
mov ecx, new_value;
|
||||
|
|
@ -171,12 +171,12 @@ compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
|
|||
// As above, but works on pointers instead of integers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustI386Impl::
|
||||
compare_and_exchange_ptr(void * volatile &mem, void *old_value,
|
||||
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value,
|
||||
void *new_value) {
|
||||
void *prev;
|
||||
#ifdef _M_IX86
|
||||
// Windows case
|
||||
void * volatile *mem_ptr = &mem;
|
||||
void * TVOLATILE *mem_ptr = &mem;
|
||||
__asm {
|
||||
mov edx, mem_ptr;
|
||||
mov ecx, new_value;
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@
|
|||
|
||||
#include "numeric_types.h"
|
||||
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AtomicAdjustI386Impl
|
||||
// Description : Uses assembly-language calls to atomically increment
|
||||
|
|
@ -38,19 +35,19 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL AtomicAdjustI386Impl {
|
||||
public:
|
||||
INLINE static void inc(volatile PN_int32 &var);
|
||||
INLINE static bool dec(volatile PN_int32 &var);
|
||||
INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const PN_int32 &var);
|
||||
INLINE static void inc(TVOLATILE PN_int32 &var);
|
||||
INLINE static bool dec(TVOLATILE PN_int32 &var);
|
||||
INLINE static PN_int32 set(TVOLATILE PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const TVOLATILE PN_int32 &var);
|
||||
|
||||
INLINE static void *set_ptr(void *&var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const &var);
|
||||
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const TVOLATILE &var);
|
||||
|
||||
INLINE static PN_int32 compare_and_exchange(volatile PN_int32 &mem,
|
||||
INLINE static PN_int32 compare_and_exchange(TVOLATILE PN_int32 &mem,
|
||||
PN_int32 old_value,
|
||||
PN_int32 new_value);
|
||||
|
||||
INLINE static void *compare_and_exchange_ptr(void * volatile &mem,
|
||||
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem,
|
||||
void *old_value,
|
||||
void *new_value);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@
|
|||
// Description: Atomically increments the indicated variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AtomicAdjustNsprImpl::
|
||||
inc(PN_int32 &var) {
|
||||
PR_AtomicIncrement(&var);
|
||||
inc(TVOLATILE PN_int32 &var) {
|
||||
PR_AtomicIncrement((PRInt32 *)&var);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -35,8 +35,8 @@ inc(PN_int32 &var) {
|
|||
// is zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AtomicAdjustNsprImpl::
|
||||
dec(PN_int32 &var) {
|
||||
return (PR_AtomicDecrement(&var) != 0);
|
||||
dec(TVOLATILE PN_int32 &var) {
|
||||
return (PR_AtomicDecrement((PRInt32 *)&var) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -46,8 +46,8 @@ dec(PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustNsprImpl::
|
||||
set(PN_int32 &var, PN_int32 new_value) {
|
||||
return PR_AtomicSet(&var, new_value);
|
||||
set(TVOLATILE PN_int32 &var, PN_int32 new_value) {
|
||||
return PR_AtomicSet((PRInt32 *)&var, new_value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -60,7 +60,7 @@ set(PN_int32 &var, PN_int32 new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustNsprImpl::
|
||||
get(const PN_int32 &var) {
|
||||
get(const TVOLATILE PN_int32 &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -71,8 +71,8 @@ get(const PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustNsprImpl::
|
||||
set_ptr(void *&var, void *new_value) {
|
||||
return PR_AtomicSet((PN_int32 *)&var, (PN_int32)new_value);
|
||||
set_ptr(void * TVOLATILE &var, void *new_value) {
|
||||
return (void *)PR_AtomicSet((PRInt32 *)&var, (PRInt32)new_value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -85,6 +85,56 @@ set_ptr(void *&var, void *new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustNsprImpl::
|
||||
get_ptr(void * const &var) {
|
||||
get_ptr(void * const TVOLATILE &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AtomicAdjustNsprImpl::compare_and_exchange
|
||||
// Access: Public, Static
|
||||
// Description: Atomic compare and exchange.
|
||||
//
|
||||
// If mem is equal to old_value, store new_value in mem.
|
||||
// In either case, return the original value of mem.
|
||||
// The caller can test for success by comparing
|
||||
// return_value == old_value.
|
||||
//
|
||||
// The atomic function expressed in pseudo-code:
|
||||
//
|
||||
// orig_value = mem;
|
||||
// if (mem == old_value) {
|
||||
// mem = new_value;
|
||||
// }
|
||||
// return orig_value;
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustNsprImpl::
|
||||
compare_and_exchange(TVOLATILE PN_int32 &mem, PN_int32 old_value,
|
||||
PN_int32 new_value) {
|
||||
PR_Lock(_mutex);
|
||||
PN_int32 orig_value = mem;
|
||||
if (mem == old_value) {
|
||||
mem = new_value;
|
||||
}
|
||||
PR_Unlock(_mutex);
|
||||
return orig_value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AtomicAdjustNsprImpl::compare_and_exchange_ptr
|
||||
// Access: Public, Static
|
||||
// Description: Atomic compare and exchange.
|
||||
//
|
||||
// As above, but works on pointers instead of integers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustNsprImpl::
|
||||
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value,
|
||||
void *new_value) {
|
||||
PR_Lock(_mutex);
|
||||
void *orig_value = mem;
|
||||
if (mem == old_value) {
|
||||
mem = new_value;
|
||||
}
|
||||
PR_Unlock(_mutex);
|
||||
return orig_value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_NSPR_IMPL
|
||||
#ifdef HAVE_NSPR
|
||||
|
||||
#include "atomicAdjustNsprImpl.h"
|
||||
|
||||
#endif // THREAD_NSPR_IMPL
|
||||
PRLock *AtomicAdjustNsprImpl::_mutex = PR_NewLock();
|
||||
|
||||
#endif // HAVE_NSPR
|
||||
|
|
|
|||
|
|
@ -22,11 +22,12 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_NSPR_IMPL
|
||||
#ifdef HAVE_NSPR
|
||||
|
||||
#include "numeric_types.h"
|
||||
|
||||
#include <pratom.h>
|
||||
#include <prlock.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AtomicAdjustNsprImpl
|
||||
|
|
@ -34,17 +35,28 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL AtomicAdjustNsprImpl {
|
||||
public:
|
||||
INLINE static void inc(PN_int32 &var);
|
||||
INLINE static bool dec(PN_int32 &var);
|
||||
INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const PN_int32 &var);
|
||||
INLINE static void inc(TVOLATILE PN_int32 &var);
|
||||
INLINE static bool dec(TVOLATILE PN_int32 &var);
|
||||
INLINE static PN_int32 set(TVOLATILE PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const TVOLATILE PN_int32 &var);
|
||||
|
||||
INLINE static void *set_ptr(void *&var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const &var);
|
||||
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const TVOLATILE &var);
|
||||
|
||||
INLINE static PN_int32 compare_and_exchange(TVOLATILE PN_int32 &mem,
|
||||
PN_int32 old_value,
|
||||
PN_int32 new_value);
|
||||
|
||||
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem,
|
||||
void *old_value,
|
||||
void *new_value);
|
||||
|
||||
private:
|
||||
static PRLock *_mutex;
|
||||
};
|
||||
|
||||
#include "atomicAdjustNsprImpl.I"
|
||||
|
||||
#endif // THREAD_NSPR_IMPL
|
||||
#endif // HAVE_NSPR
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
// Description: Atomically increments the indicated variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AtomicAdjustPosixImpl::
|
||||
inc(PN_int32 &var) {
|
||||
inc(TVOLATILE PN_int32 &var) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
++var;
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
|
|
@ -37,7 +37,7 @@ inc(PN_int32 &var) {
|
|||
// is zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AtomicAdjustPosixImpl::
|
||||
dec(PN_int32 &var) {
|
||||
dec(TVOLATILE PN_int32 &var) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
PN_int32 result = --var;
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
|
|
@ -51,7 +51,7 @@ dec(PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustPosixImpl::
|
||||
set(PN_int32 &var, PN_int32 new_value) {
|
||||
set(TVOLATILE PN_int32 &var, PN_int32 new_value) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
PN_int32 orig_value = var;
|
||||
var = new_value;
|
||||
|
|
@ -69,7 +69,7 @@ set(PN_int32 &var, PN_int32 new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustPosixImpl::
|
||||
get(const PN_int32 &var) {
|
||||
get(const TVOLATILE PN_int32 &var) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
PN_int32 orig_value = var;
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
|
|
@ -83,7 +83,7 @@ get(const PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustPosixImpl::
|
||||
set_ptr(void *&var, void *new_value) {
|
||||
set_ptr(void * TVOLATILE &var, void *new_value) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
void *orig_value = var;
|
||||
var = new_value;
|
||||
|
|
@ -101,9 +101,59 @@ set_ptr(void *&var, void *new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustPosixImpl::
|
||||
get_ptr(void * const &var) {
|
||||
get_ptr(void * const TVOLATILE &var) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
void *orig_value = var;
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
return orig_value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AtomicAdjustPosixImpl::compare_and_exchange
|
||||
// Access: Public, Static
|
||||
// Description: Atomic compare and exchange.
|
||||
//
|
||||
// If mem is equal to old_value, store new_value in mem.
|
||||
// In either case, return the original value of mem.
|
||||
// The caller can test for success by comparing
|
||||
// return_value == old_value.
|
||||
//
|
||||
// The atomic function expressed in pseudo-code:
|
||||
//
|
||||
// orig_value = mem;
|
||||
// if (mem == old_value) {
|
||||
// mem = new_value;
|
||||
// }
|
||||
// return orig_value;
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustPosixImpl::
|
||||
compare_and_exchange(TVOLATILE PN_int32 &mem, PN_int32 old_value,
|
||||
PN_int32 new_value) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
PN_int32 orig_value = mem;
|
||||
if (mem == old_value) {
|
||||
mem = new_value;
|
||||
}
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
return orig_value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AtomicAdjustPosixImpl::compare_and_exchange_ptr
|
||||
// Access: Public, Static
|
||||
// Description: Atomic compare and exchange.
|
||||
//
|
||||
// As above, but works on pointers instead of integers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustPosixImpl::
|
||||
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value,
|
||||
void *new_value) {
|
||||
pthread_mutex_lock(&_mutex);
|
||||
void *orig_value = mem;
|
||||
if (mem == old_value) {
|
||||
mem = new_value;
|
||||
}
|
||||
pthread_mutex_unlock(&_mutex);
|
||||
return orig_value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_POSIX_IMPL
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
||||
#include "atomicAdjustPosixImpl.h"
|
||||
|
||||
pthread_mutex_t AtomicAdjustPosixImpl::_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
#endif // THREAD_POSIX_IMPL
|
||||
#endif // HAVE_POSIX_THREADS
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_POSIX_IMPL
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
||||
#include "numeric_types.h"
|
||||
|
||||
|
|
@ -34,13 +34,21 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL AtomicAdjustPosixImpl {
|
||||
public:
|
||||
INLINE static void inc(PN_int32 &var);
|
||||
INLINE static bool dec(PN_int32 &var);
|
||||
INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const PN_int32 &var);
|
||||
INLINE static void inc(TVOLATILE PN_int32 &var);
|
||||
INLINE static bool dec(TVOLATILE PN_int32 &var);
|
||||
INLINE static PN_int32 set(TVOLATILE PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const TVOLATILE PN_int32 &var);
|
||||
|
||||
INLINE static void *set_ptr(void *&var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const &var);
|
||||
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const TVOLATILE &var);
|
||||
|
||||
INLINE static PN_int32 compare_and_exchange(TVOLATILE PN_int32 &mem,
|
||||
PN_int32 old_value,
|
||||
PN_int32 new_value);
|
||||
|
||||
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem,
|
||||
void *old_value,
|
||||
void *new_value);
|
||||
|
||||
private:
|
||||
static pthread_mutex_t _mutex;
|
||||
|
|
@ -48,6 +56,6 @@ private:
|
|||
|
||||
#include "atomicAdjustPosixImpl.I"
|
||||
|
||||
#endif // THREAD_POSIX_IMPL
|
||||
#endif // HAVE_POSIX_THREADS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
// Description: Atomically increments the indicated variable.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AtomicAdjustWin32Impl::
|
||||
inc(PN_int32 &var) {
|
||||
inc(TVOLATILE PN_int32 &var) {
|
||||
InterlockedIncrement((LONG *)&var);
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ inc(PN_int32 &var) {
|
|||
// is zero.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AtomicAdjustWin32Impl::
|
||||
dec(PN_int32 &var) {
|
||||
dec(TVOLATILE PN_int32 &var) {
|
||||
return (InterlockedDecrement((LONG *)&var) != 0);
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ dec(PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustWin32Impl::
|
||||
set(PN_int32 &var, PN_int32 new_value) {
|
||||
set(TVOLATILE PN_int32 &var, PN_int32 new_value) {
|
||||
return InterlockedExchange((LONG *)&var, new_value);
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ set(PN_int32 &var, PN_int32 new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustWin32Impl::
|
||||
get(const PN_int32 &var) {
|
||||
get(const TVOLATILE PN_int32 &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ get(const PN_int32 &var) {
|
|||
// returns the original value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustWin32Impl::
|
||||
set_ptr(void *&var, void *new_value) {
|
||||
set_ptr(void * TVOLATILE &var, void *new_value) {
|
||||
void *orig_value = var;
|
||||
var = new_value;
|
||||
return orig_value;
|
||||
|
|
@ -87,7 +87,7 @@ set_ptr(void *&var, void *new_value) {
|
|||
// (via other AtomicAjust methods).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustWin32Impl::
|
||||
get_ptr(void * const &var) {
|
||||
get_ptr(void * const TVOLATILE &var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
|
|
@ -111,11 +111,11 @@ get_ptr(void * const &var) {
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PN_int32 AtomicAdjustWin32Impl::
|
||||
compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
|
||||
compare_and_exchange(TVOLATILE PN_int32 &mem, PN_int32 old_value,
|
||||
PN_int32 new_value) {
|
||||
// Note that the AtomicAdjust parameter order is different from
|
||||
// Windows convention!
|
||||
return InterlockedCompareExchange((volatile LONG *)&mem, new_value, old_value);
|
||||
return InterlockedCompareExchange((TVOLATILE LONG *)&mem, new_value, old_value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -126,7 +126,7 @@ compare_and_exchange(volatile PN_int32 &mem, PN_int32 old_value,
|
|||
// As above, but works on pointers instead of integers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void *AtomicAdjustWin32Impl::
|
||||
compare_and_exchange_ptr(void * volatile &mem, void *old_value,
|
||||
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value,
|
||||
void *new_value) {
|
||||
// Note that the AtomicAdjust parameter order is different from
|
||||
// Windows convention!
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_WIN32_IMPL
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "atomicAdjustWin32Impl.h"
|
||||
|
||||
#endif // THREAD_WIN32_IMPL
|
||||
#endif // WIN32_VC
|
||||
|
|
|
|||
|
|
@ -22,15 +22,12 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_WIN32_IMPL
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "numeric_types.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
|
||||
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : AtomicAdjustWin32Impl
|
||||
// Description : Uses Windows native calls to implement atomic
|
||||
|
|
@ -38,25 +35,25 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL AtomicAdjustWin32Impl {
|
||||
public:
|
||||
INLINE static void inc(PN_int32 &var);
|
||||
INLINE static bool dec(PN_int32 &var);
|
||||
INLINE static PN_int32 set(PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const PN_int32 &var);
|
||||
INLINE static void inc(TVOLATILE PN_int32 &var);
|
||||
INLINE static bool dec(TVOLATILE PN_int32 &var);
|
||||
INLINE static PN_int32 set(TVOLATILE PN_int32 &var, PN_int32 new_value);
|
||||
INLINE static PN_int32 get(const TVOLATILE PN_int32 &var);
|
||||
|
||||
INLINE static void *set_ptr(void *&var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const &var);
|
||||
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value);
|
||||
INLINE static void *get_ptr(void * const TVOLATILE &var);
|
||||
|
||||
INLINE static PN_int32 compare_and_exchange(volatile PN_int32 &mem,
|
||||
INLINE static PN_int32 compare_and_exchange(TVOLATILE PN_int32 &mem,
|
||||
PN_int32 old_value,
|
||||
PN_int32 new_value);
|
||||
|
||||
INLINE static void *compare_and_exchange_ptr(void * volatile &mem,
|
||||
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem,
|
||||
void *old_value,
|
||||
void *new_value);
|
||||
};
|
||||
|
||||
#include "atomicAdjustWin32Impl.I"
|
||||
|
||||
#endif // THREAD_WIN32_IMPL
|
||||
#endif // WIN32_VC
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
#include "atomicAdjustNsprImpl.cxx"
|
||||
#include "atomicAdjustPosixImpl.cxx"
|
||||
#include "atomicAdjustWin32Impl.cxx"
|
||||
#include "dtoolbase.cxx"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "dtoolbase.cxx"
|
||||
#include "mutexDummyImpl.cxx"
|
||||
#include "mutexNsprImpl.cxx"
|
||||
#include "mutexLinuxImpl.cxx"
|
||||
#include "mutexPosixImpl.cxx"
|
||||
#include "mutexWin32Impl.cxx"
|
||||
#include "mutexSpinlockImpl.cxx"
|
||||
|
|
|
|||
|
|
@ -17,9 +17,4 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_DUMMY_IMPL
|
||||
|
||||
#include "mutexDummyImpl.h"
|
||||
|
||||
#endif // THREAD_DUMMY_IMPL
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_DUMMY_IMPL
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MutexDummyImpl
|
||||
// Description : A fake mutex implementation for single-threaded
|
||||
|
|
@ -41,6 +39,4 @@ public:
|
|||
|
||||
#include "mutexDummyImpl.I"
|
||||
|
||||
#endif // THREAD_DUMMY_IMPL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ typedef MutexDummyImpl MutexImpl;
|
|||
typedef MutexDummyImpl ReMutexImpl;
|
||||
#define HAVE_REMUTEXIMPL 1
|
||||
|
||||
#elif defined(MUTEX_SPINLOCK)
|
||||
|
||||
#include "mutexSpinlockImpl.h"
|
||||
typedef MutexSpinlockImpl MutexImpl;
|
||||
#undef HAVE_REMUTEXIMPL
|
||||
|
||||
#elif defined(THREAD_WIN32_IMPL)
|
||||
|
||||
#include "mutexWin32Impl.h"
|
||||
|
|
@ -53,7 +59,8 @@ typedef ReMutexPosixImpl ReMutexImpl;
|
|||
|
||||
#include "mutexNsprImpl.h"
|
||||
typedef MutexNsprImpl MutexImpl;
|
||||
#undef HAVE_REMUTEXIMPL // NSPR doesn't provide a reentrant mutex.
|
||||
typedef ReMutexNsprImpl ReMutexImpl;
|
||||
#define HAVE_REMUTEXIMPL 1
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -36,3 +36,15 @@ INLINE MutexLinuxImpl::
|
|||
~MutexLinuxImpl() {
|
||||
assert(_mode == M_unlocked);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexLinuxImpl::try_lock
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MutexLinuxImpl::
|
||||
try_lock() {
|
||||
// We haven't implemented try_lock(). We just report that it would
|
||||
// always block (since we don't know).
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_LINUX_IMPL
|
||||
#ifdef HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#include "mutexLinuxImpl.h"
|
||||
#include "atomicAdjust.h"
|
||||
|
|
@ -61,4 +61,4 @@ release() {
|
|||
}
|
||||
}
|
||||
|
||||
#endif // THREAD_LINUX_IMPL
|
||||
#endif // HAVE_LINUX_NATIVE_THREADS
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_LINUX_IMPL
|
||||
#ifdef HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#include "numeric_types.h"
|
||||
|
||||
#undef MUTEX_DEFINES_TRYLOCK
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MutexLinuxImpl
|
||||
// Description : Uses Linux threads to implement a mutex.
|
||||
|
|
@ -38,6 +36,7 @@ public:
|
|||
INLINE ~MutexLinuxImpl();
|
||||
|
||||
void lock();
|
||||
INLINE bool try_lock();
|
||||
void release();
|
||||
|
||||
private:
|
||||
|
|
@ -53,6 +52,6 @@ private:
|
|||
|
||||
#include "mutexLinuxImpl.I"
|
||||
|
||||
#endif // THREAD_LINUX_IMPL
|
||||
#endif // HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -70,3 +70,57 @@ release() {
|
|||
int status = PR_Unlock(_lock);
|
||||
assert(status == PR_SUCCESS);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReMutexNsprImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ReMutexNsprImpl::
|
||||
ReMutexNsprImpl() {
|
||||
_monitor = PR_NewMonitor();
|
||||
assert(_monitor != (PRMonitor *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReMutexNsprImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ReMutexNsprImpl::
|
||||
~ReMutexNsprImpl() {
|
||||
PR_DestroyMonitor(_monitor);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReMutexNsprImpl::lock
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ReMutexNsprImpl::
|
||||
lock() {
|
||||
PR_EnterMonitor(_monitor);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReMutexNsprImpl::try_lock
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ReMutexNsprImpl::
|
||||
try_lock() {
|
||||
// NSPR doesn't define a try_lock function. Too bad. We just
|
||||
// report that it would always block (since we don't know).
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ReMutexNsprImpl::release
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ReMutexNsprImpl::
|
||||
release() {
|
||||
int status = PR_ExitMonitor(_monitor);
|
||||
assert(status == PR_SUCCESS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_NSPR_IMPL
|
||||
#ifdef HAVE_NSPR
|
||||
|
||||
#include "mutexNsprImpl.h"
|
||||
|
||||
#endif // THREAD_NSPR_IMPL
|
||||
#endif // HAVE_NSPR
|
||||
|
|
|
|||
|
|
@ -22,11 +22,10 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_NSPR_IMPL
|
||||
#ifdef HAVE_NSPR
|
||||
|
||||
#include <prlock.h>
|
||||
|
||||
#undef MUTEX_DEFINES_TRYLOCK
|
||||
#include <prmon.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MutexNsprImpl
|
||||
|
|
@ -46,8 +45,25 @@ private:
|
|||
friend class ConditionVarNsprImpl;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ReMutexNsprImpl
|
||||
// Description : Uses NSPR to implement a reMutex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL ReMutexNsprImpl {
|
||||
public:
|
||||
INLINE ReMutexNsprImpl();
|
||||
INLINE ~ReMutexNsprImpl();
|
||||
|
||||
INLINE void lock();
|
||||
INLINE bool try_lock();
|
||||
INLINE void release();
|
||||
|
||||
private:
|
||||
PRMonitor *_monitor;
|
||||
};
|
||||
|
||||
#include "mutexNsprImpl.I"
|
||||
|
||||
#endif // THREAD_NSPR_IMPL
|
||||
#endif // HAVE_NSPR
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_POSIX_IMPL
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
||||
#include "mutexPosixImpl.h"
|
||||
|
||||
#endif // THREAD_POSIX_IMPL
|
||||
#endif // HAVE_POSIX_THREADS
|
||||
|
|
|
|||
|
|
@ -22,13 +22,11 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_POSIX_IMPL
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MUTEX_DEFINES_TRYLOCK 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MutexPosixImpl
|
||||
// Description : Uses Posix threads to implement a mutex.
|
||||
|
|
@ -66,6 +64,6 @@ private:
|
|||
|
||||
#include "mutexPosixImpl.I"
|
||||
|
||||
#endif // THREAD_POSIX_IMPL
|
||||
#endif // HAVE_POSIX_THREADS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
// Filename: mutexSpinlockImpl.I
|
||||
// Created by: drose (11Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexSpinlockImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MutexSpinlockImpl::
|
||||
MutexSpinlockImpl() {
|
||||
_lock = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexSpinlockImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE MutexSpinlockImpl::
|
||||
~MutexSpinlockImpl() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexSpinlockImpl::lock
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MutexSpinlockImpl::
|
||||
lock() {
|
||||
if (!try_lock()) {
|
||||
do_lock();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexSpinlockImpl::try_lock
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool MutexSpinlockImpl::
|
||||
try_lock() {
|
||||
return (AtomicAdjust::compare_and_exchange(_lock, 0, 1) == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexSpinlockImpl::release
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void MutexSpinlockImpl::
|
||||
release() {
|
||||
AtomicAdjust::set(_lock, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Filename: mutexSpinlockImpl.cxx
|
||||
// Created by: drose (11Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef MUTEX_SPINLOCK
|
||||
|
||||
#include "mutexSpinlockImpl.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MutexSpinlockImpl::do_lock
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MutexSpinlockImpl::
|
||||
do_lock() {
|
||||
while (AtomicAdjust::compare_and_exchange(_lock, 0, 1) != 0) {
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MUTEX_SPINLOCK
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// Filename: mutexSpinlockImpl.h
|
||||
// Created by: drose (11Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MUTEXSPINLOCKIMPL_H
|
||||
#define MUTEXSPINLOCKIMPL_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef MUTEX_SPINLOCK
|
||||
|
||||
#include "atomicAdjust.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MutexSpinlockImpl
|
||||
// Description : Uses Windows native calls to implement a mutex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DTOOL MutexSpinlockImpl {
|
||||
public:
|
||||
INLINE MutexSpinlockImpl();
|
||||
INLINE ~MutexSpinlockImpl();
|
||||
|
||||
INLINE void lock();
|
||||
INLINE bool try_lock();
|
||||
INLINE void release();
|
||||
|
||||
private:
|
||||
void do_lock();
|
||||
|
||||
volatile PN_int32 _lock;
|
||||
};
|
||||
|
||||
#include "mutexSpinlockImpl.I"
|
||||
|
||||
#endif // MUTEX_SPINLOCK
|
||||
|
||||
#endif
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_WIN32_IMPL
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "mutexWin32Impl.h"
|
||||
|
||||
#endif // THREAD_WIN32_IMPL
|
||||
#endif // WIN32_VC
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@
|
|||
#include "dtoolbase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_WIN32_IMPL
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define MUTEX_DEFINES_TRYLOCK 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MutexWin32Impl
|
||||
// Description : Uses Windows native calls to implement a mutex.
|
||||
|
|
@ -48,6 +46,6 @@ private:
|
|||
|
||||
#include "mutexWin32Impl.I"
|
||||
|
||||
#endif // THREAD_WIN32_IMPL
|
||||
#endif // WIN32_VC
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,11 +33,22 @@
|
|||
// synchronization classes are defined in panda/src/express.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This keyword should be used to mark any variable which is possibly
|
||||
// volatile because multiple threads might contend on it, unprotected
|
||||
// by a mutex. It will be defined out in the non-threaded case.
|
||||
// Other uses for volatile (dma buffers, for instance) should use the
|
||||
// regular volatile keyword.
|
||||
#define TVOLATILE volatile
|
||||
|
||||
#if !defined(HAVE_THREADS)
|
||||
|
||||
// With threading disabled, use the do-nothing implementation.
|
||||
#define THREAD_DUMMY_IMPL 1
|
||||
|
||||
// And the TVOLATILE keyword means nothing in the absence of threads.
|
||||
#undef TVOLATILE
|
||||
#define TVOLATILE
|
||||
|
||||
#elif defined(WIN32_VC)
|
||||
|
||||
// In Windows, use the native threading library.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
conditionVarLinuxImpl.h conditionVarLinuxImpl.I \
|
||||
conditionVarPosixImpl.h conditionVarPosixImpl.I \
|
||||
conditionVarWin32Impl.h conditionVarWin32Impl.I \
|
||||
conditionVarSpinlockImpl.h conditionVarSpinlockImpl.I \
|
||||
config_pipeline.h \
|
||||
cycleData.h cycleData.I \
|
||||
cycleDataReader.h cycleDataReader.I \
|
||||
|
|
@ -58,6 +59,7 @@
|
|||
conditionVarLinuxImpl.cxx \
|
||||
conditionVarPosixImpl.cxx \
|
||||
conditionVarWin32Impl.cxx \
|
||||
conditionVarSpinlockImpl.cxx \
|
||||
config_pipeline.cxx \
|
||||
cycleData.cxx \
|
||||
cycleDataReader.cxx \
|
||||
|
|
@ -95,6 +97,7 @@
|
|||
conditionVarLinuxImpl.h conditionVarLinuxImpl.I \
|
||||
conditionVarPosixImpl.h conditionVarPosixImpl.I \
|
||||
conditionVarWin32Impl.h conditionVarWin32Impl.I \
|
||||
conditionVarSpinlockImpl.h conditionVarSpinlockImpl.I \
|
||||
config_pipeline.h \
|
||||
cycleData.h cycleData.I \
|
||||
cycleDataReader.h cycleDataReader.I \
|
||||
|
|
|
|||
|
|
@ -17,9 +17,4 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_DUMMY_IMPL
|
||||
|
||||
#include "conditionVarDummyImpl.h"
|
||||
|
||||
#endif // THREAD_DUMMY_IMPL
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@
|
|||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_DUMMY_IMPL
|
||||
|
||||
#include "pnotify.h"
|
||||
|
||||
class MutexDummyImpl;
|
||||
|
|
@ -46,6 +44,4 @@ public:
|
|||
|
||||
#include "conditionVarDummyImpl.I"
|
||||
|
||||
#endif // THREAD_DUMMY_IMPL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,6 +27,11 @@
|
|||
#include "conditionVarDummyImpl.h"
|
||||
typedef ConditionVarDummyImpl ConditionVarImpl;
|
||||
|
||||
#elif defined(MUTEX_SPINLOCK)
|
||||
|
||||
#include "conditionVarSpinlockImpl.h"
|
||||
typedef ConditionVarSpinlockImpl ConditionVarImpl;
|
||||
|
||||
#elif defined(THREAD_WIN32_IMPL)
|
||||
|
||||
#include "conditionVarWin32Impl.h"
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_LINUX_IMPL
|
||||
#ifdef HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#include "conditionVarLinuxImpl.h"
|
||||
|
||||
|
|
@ -52,4 +52,4 @@ signal() {
|
|||
syscall(SYS_futex, &_counter, FUTEX_WAKE, 1);
|
||||
}
|
||||
|
||||
#endif // THREAD_LINUX_IMPL
|
||||
#endif // HAVE_LINUX_NATIVE_THREADS
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_LINUX_IMPL
|
||||
#ifdef HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#include "mutexLinuxImpl.h"
|
||||
#include "pnotify.h"
|
||||
|
|
@ -48,6 +48,6 @@ private:
|
|||
|
||||
#include "conditionVarLinuxImpl.I"
|
||||
|
||||
#endif // THREAD_LINUX_IMPL
|
||||
#endif // HAVE_LINUX_NATIVE_THREADS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_NSPR_IMPL
|
||||
#ifdef HAVE_NSPR
|
||||
|
||||
#include "conditionVarNsprImpl.h"
|
||||
|
||||
#endif // THREAD_NSPR_IMPL
|
||||
#endif // HAVE_NSPR
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_NSPR_IMPL
|
||||
#ifdef HAVE_NSPR
|
||||
|
||||
#include "mutexNsprImpl.h"
|
||||
#include "pnotify.h"
|
||||
|
|
@ -49,6 +49,6 @@ private:
|
|||
|
||||
#include "conditionVarNsprImpl.I"
|
||||
|
||||
#endif // THREAD_NSPR_IMPL
|
||||
#endif // HAVE_NSPR
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_POSIX_IMPL
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
||||
#include "conditionVarPosixImpl.h"
|
||||
|
||||
#endif // THREAD_POSIX_IMPL
|
||||
#endif // HAVE_POSIX_THREADS
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_POSIX_IMPL
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
||||
#include "mutexPosixImpl.h"
|
||||
#include "pnotify.h"
|
||||
|
|
@ -50,6 +50,6 @@ private:
|
|||
|
||||
#include "conditionVarPosixImpl.I"
|
||||
|
||||
#endif // THREAD_POSIX_IMPL
|
||||
#endif // HAVE_POSIX_THREADS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// Filename: conditionVarSpinlockImpl.I
|
||||
// Created by: drose (11Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarSpinlockImpl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarSpinlockImpl::
|
||||
ConditionVarSpinlockImpl(MutexSpinlockImpl &mutex) : _mutex(mutex) {
|
||||
_event = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarSpinlockImpl::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE ConditionVarSpinlockImpl::
|
||||
~ConditionVarSpinlockImpl() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarSpinlockImpl::signal
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void ConditionVarSpinlockImpl::
|
||||
signal() {
|
||||
// This will wake up all waiters on the lock. But that's allowed.
|
||||
AtomicAdjust::inc(_event);
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Filename: conditionVarSpinlockImpl.cxx
|
||||
// Created by: drose (11Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef MUTEX_SPINLOCK
|
||||
|
||||
#include "conditionVarSpinlockImpl.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ConditionVarSpinlockImpl::wait
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ConditionVarSpinlockImpl::
|
||||
wait() {
|
||||
PN_int32 current = _event;
|
||||
_mutex.release();
|
||||
|
||||
while (AtomicAdjust::get(_event) == current) {
|
||||
}
|
||||
|
||||
_mutex.lock();
|
||||
}
|
||||
|
||||
#endif // MUTEX_SPINLOCK
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// Filename: conditionVarSpinlockImpl.h
|
||||
// Created by: drose (11Apr06)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONDITIONVARSPINLOCKIMPL_H
|
||||
#define CONDITIONVARSPINLOCKIMPL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef MUTEX_SPINLOCK
|
||||
|
||||
#include "mutexSpinlockImpl.h"
|
||||
#include "pnotify.h"
|
||||
#include "atomicAdjust.h"
|
||||
|
||||
class MutexSpinlockImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ConditionVarSpinlockImpl
|
||||
// Description : Uses Windows native calls to implement a
|
||||
// conditionVar.
|
||||
//
|
||||
// The Windows native synchronization primitives don't
|
||||
// actually implement a full POSIX-style condition
|
||||
// variable, but the Event primitive does a fair job if
|
||||
// we disallow POSIX broadcast. See
|
||||
// http://www.cs.wustl.edu/~schmidt/spinlock-cv-1.html for
|
||||
// a full implementation that includes broadcast. This
|
||||
// class is much simpler than that full implementation,
|
||||
// so we can avoid the overhead require to support
|
||||
// broadcast.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA ConditionVarSpinlockImpl {
|
||||
public:
|
||||
INLINE ConditionVarSpinlockImpl(MutexSpinlockImpl &mutex);
|
||||
INLINE ~ConditionVarSpinlockImpl();
|
||||
|
||||
void wait();
|
||||
INLINE void signal();
|
||||
|
||||
private:
|
||||
MutexSpinlockImpl &_mutex;
|
||||
volatile PN_int32 _event;
|
||||
};
|
||||
|
||||
#include "conditionVarSpinlockImpl.I"
|
||||
|
||||
#endif // MUTEX_SPINLOCK
|
||||
|
||||
#endif
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_WIN32_IMPL
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "conditionVarWin32Impl.h"
|
||||
|
||||
#endif // THREAD_WIN32_IMPL
|
||||
#endif // WIN32_VC
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "pandabase.h"
|
||||
#include "selectThreadImpl.h"
|
||||
|
||||
#ifdef THREAD_WIN32_IMPL
|
||||
#ifdef WIN32_VC
|
||||
|
||||
#include "mutexWin32Impl.h"
|
||||
#include "pnotify.h"
|
||||
|
|
@ -61,6 +61,6 @@ private:
|
|||
|
||||
#include "conditionVarWin32Impl.I"
|
||||
|
||||
#endif // THREAD_WIN32_IMPL
|
||||
#endif // WIN32_VC
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ do_lock() {
|
|||
}
|
||||
while (_locking_thread != (Thread *)NULL) {
|
||||
_cvar.wait();
|
||||
thread_cat.spam()
|
||||
<< *this_thread << " wakeup\n";
|
||||
}
|
||||
|
||||
if (thread_cat.is_spam()) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "conditionVarLinuxImpl.cxx"
|
||||
#include "conditionVarPosixImpl.cxx"
|
||||
#include "conditionVarWin32Impl.cxx"
|
||||
#include "conditionVarSpinlockImpl.cxx"
|
||||
#include "config_pipeline.cxx"
|
||||
#include "cycleData.cxx"
|
||||
#include "cycleDataReader.cxx"
|
||||
|
|
|
|||
|
|
@ -34,10 +34,20 @@ static const double delay_between_threads = 2.0;
|
|||
static const double thread_run_time = 15.0;
|
||||
|
||||
// The number of threads to spawn.
|
||||
static const int number_of_threads = 5;
|
||||
static const int number_of_threads = 4;
|
||||
|
||||
// Number of bytes to reserve between writable memory pointers.
|
||||
static const int block_size = 64;
|
||||
|
||||
static Mutex _output_lock;
|
||||
|
||||
union MemBlock {
|
||||
char _pad[block_size];
|
||||
int _value;
|
||||
};
|
||||
|
||||
volatile MemBlock memblock[number_of_threads];
|
||||
|
||||
#define OUTPUT(stuff) { \
|
||||
MutexHolder holder(_output_lock); \
|
||||
stuff; \
|
||||
|
|
@ -45,8 +55,9 @@ static Mutex _output_lock;
|
|||
|
||||
class MyThread : public Thread {
|
||||
public:
|
||||
MyThread(const string &name) :
|
||||
Thread(name, name)
|
||||
MyThread(const string &name, int index) :
|
||||
Thread(name, name),
|
||||
_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -55,11 +66,13 @@ public:
|
|||
|
||||
double total_seconds = 0.0;
|
||||
TrueClock *clock = TrueClock::get_global_ptr();
|
||||
volatile int snarf;
|
||||
|
||||
while (total_seconds < thread_run_time) {
|
||||
double start_time = clock->get_short_time();
|
||||
|
||||
for (long long i = 0; i < iterations_per_output; ++i) {
|
||||
memblock[_index]._value = snarf;
|
||||
}
|
||||
|
||||
double end_time = clock->get_short_time();
|
||||
|
|
@ -75,6 +88,8 @@ public:
|
|||
|
||||
OUTPUT(nout << *this << " exiting.\n");
|
||||
}
|
||||
|
||||
int _index;
|
||||
};
|
||||
|
||||
int
|
||||
|
|
@ -84,14 +99,14 @@ main(int argc, char *argv[]) {
|
|||
typedef pvector< PT(MyThread) > Threads;
|
||||
Threads threads;
|
||||
|
||||
PT(MyThread) thread = new MyThread("a");
|
||||
PT(MyThread) thread = new MyThread("a", 0);
|
||||
threads.push_back(thread);
|
||||
thread->start(TP_normal, true, true);
|
||||
|
||||
for (int i = 1; i < number_of_threads; ++i) {
|
||||
char name = 'a' + i;
|
||||
Thread::sleep(delay_between_threads);
|
||||
PT(MyThread) thread = new MyThread(string(1, name));
|
||||
PT(MyThread) thread = new MyThread(string(1, name), i);
|
||||
threads.push_back(thread);
|
||||
thread->start(TP_normal, true, true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue