guarantee word alignment for AtomicAdjust stuff

This commit is contained in:
David Rose 2011-11-17 23:31:31 +00:00
parent 078ddc7c27
commit 539b61571c
19 changed files with 165 additions and 108 deletions

View File

@ -79,9 +79,10 @@ get(const TVOLATILE AtomicAdjustDummyImpl::Integer &var) {
// Description: Atomically changes the indicated variable and // Description: Atomically changes the indicated variable and
// returns the original value. // returns the original value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustDummyImpl:: INLINE AtomicAdjustDummyImpl::Pointer AtomicAdjustDummyImpl::
set_ptr(void * TVOLATILE &var, void *new_value) { set_ptr(TVOLATILE AtomicAdjustDummyImpl::Pointer &var,
void *orig_value = var; AtomicAdjustDummyImpl::Pointer new_value) {
Pointer orig_value = var;
var = new_value; var = new_value;
return orig_value; return orig_value;
} }
@ -95,8 +96,8 @@ set_ptr(void * TVOLATILE &var, void *new_value) {
// asynchronously setting, incrementing, or decrementing // asynchronously setting, incrementing, or decrementing
// (via other AtomicAjust methods). // (via other AtomicAjust methods).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustDummyImpl:: INLINE AtomicAdjustDummyImpl::Pointer AtomicAdjustDummyImpl::
get_ptr(void * const TVOLATILE &var) { get_ptr(const TVOLATILE AtomicAdjustDummyImpl::Pointer &var) {
return var; return var;
} }
@ -111,7 +112,8 @@ get_ptr(void * const TVOLATILE &var) {
// return_value == old_value. // return_value == old_value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustDummyImpl::Integer AtomicAdjustDummyImpl:: INLINE AtomicAdjustDummyImpl::Integer AtomicAdjustDummyImpl::
compare_and_exchange(TVOLATILE AtomicAdjustDummyImpl::Integer &mem, AtomicAdjustDummyImpl::Integer old_value, compare_and_exchange(TVOLATILE AtomicAdjustDummyImpl::Integer &mem,
AtomicAdjustDummyImpl::Integer old_value,
AtomicAdjustDummyImpl::Integer new_value) { AtomicAdjustDummyImpl::Integer new_value) {
Integer orig_value = mem; Integer orig_value = mem;
if (mem == old_value) { if (mem == old_value) {
@ -127,10 +129,11 @@ compare_and_exchange(TVOLATILE AtomicAdjustDummyImpl::Integer &mem, AtomicAdjust
// //
// As above, but works on pointers instead of integers. // As above, but works on pointers instead of integers.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustDummyImpl:: INLINE AtomicAdjustDummyImpl::Pointer AtomicAdjustDummyImpl::
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value, compare_and_exchange_ptr(TVOLATILE AtomicAdjustDummyImpl::Pointer &mem,
void *new_value) { AtomicAdjustDummyImpl::Pointer old_value,
void *orig_value = mem; AtomicAdjustDummyImpl::Pointer new_value) {
Pointer orig_value = mem;
if (mem == old_value) { if (mem == old_value) {
mem = new_value; mem = new_value;
} }

View File

@ -29,6 +29,7 @@
class EXPCL_DTOOL AtomicAdjustDummyImpl { class EXPCL_DTOOL AtomicAdjustDummyImpl {
public: public:
typedef long Integer; typedef long Integer;
typedef void *Pointer;
INLINE static void inc(TVOLATILE Integer &var); INLINE static void inc(TVOLATILE Integer &var);
INLINE static bool dec(TVOLATILE Integer &var); INLINE static bool dec(TVOLATILE Integer &var);
@ -36,16 +37,16 @@ public:
INLINE static Integer set(TVOLATILE Integer &var, Integer new_value); INLINE static Integer set(TVOLATILE Integer &var, Integer new_value);
INLINE static Integer get(const TVOLATILE Integer &var); INLINE static Integer get(const TVOLATILE Integer &var);
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value); INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value);
INLINE static void *get_ptr(void * const TVOLATILE &var); INLINE static Pointer get_ptr(const TVOLATILE Pointer &var);
INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem, INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem,
Integer old_value, Integer old_value,
Integer new_value); Integer new_value);
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem, INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem,
void *old_value, Pointer old_value,
void *new_value); Pointer new_value);
}; };
#include "atomicAdjustDummyImpl.I" #include "atomicAdjustDummyImpl.I"

View File

@ -20,6 +20,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void AtomicAdjustI386Impl:: INLINE void AtomicAdjustI386Impl::
inc(TVOLATILE AtomicAdjustI386Impl::Integer &var) { inc(TVOLATILE AtomicAdjustI386Impl::Integer &var) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
#ifdef _M_IX86 #ifdef _M_IX86
// Windows case // Windows case
TVOLATILE Integer *var_ptr = &var; TVOLATILE Integer *var_ptr = &var;
@ -44,6 +45,7 @@ inc(TVOLATILE AtomicAdjustI386Impl::Integer &var) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool AtomicAdjustI386Impl:: INLINE bool AtomicAdjustI386Impl::
dec(TVOLATILE AtomicAdjustI386Impl::Integer &var) { dec(TVOLATILE AtomicAdjustI386Impl::Integer &var) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
unsigned char c; unsigned char c;
#ifdef _M_IX86 #ifdef _M_IX86
// Windows case // Windows case
@ -70,6 +72,7 @@ dec(TVOLATILE AtomicAdjustI386Impl::Integer &var) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void AtomicAdjustI386Impl:: INLINE void AtomicAdjustI386Impl::
add(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer delta) { add(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer delta) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
Integer orig_value = var; Integer orig_value = var;
while (compare_and_exchange(var, orig_value, orig_value + delta) != orig_value) { while (compare_and_exchange(var, orig_value, orig_value + delta) != orig_value) {
orig_value = var; orig_value = var;
@ -83,7 +86,9 @@ add(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer
// returns the original value. // returns the original value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl:: INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl::
set(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer new_value) { set(TVOLATILE AtomicAdjustI386Impl::Integer &var,
AtomicAdjustI386Impl::Integer new_value) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
Integer orig_value = var; Integer orig_value = var;
var = new_value; var = new_value;
return orig_value; return orig_value;
@ -100,6 +105,7 @@ set(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl:: INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl::
get(const TVOLATILE AtomicAdjustI386Impl::Integer &var) { get(const TVOLATILE AtomicAdjustI386Impl::Integer &var) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
return var; return var;
} }
@ -109,9 +115,11 @@ get(const TVOLATILE AtomicAdjustI386Impl::Integer &var) {
// Description: Atomically changes the indicated variable and // Description: Atomically changes the indicated variable and
// returns the original value. // returns the original value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustI386Impl:: INLINE AtomicAdjustI386Impl::Pointer AtomicAdjustI386Impl::
set_ptr(void * TVOLATILE &var, void *new_value) { set_ptr(TVOLATILE AtomicAdjustI386Impl::Pointer &var,
void *orig_value = var; AtomicAdjustI386Impl::Pointer new_value) {
assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0);
Pointer orig_value = var;
var = new_value; var = new_value;
return orig_value; return orig_value;
} }
@ -125,8 +133,9 @@ set_ptr(void * TVOLATILE &var, void *new_value) {
// asynchronously setting, incrementing, or decrementing // asynchronously setting, incrementing, or decrementing
// (via other AtomicAjust methods). // (via other AtomicAjust methods).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustI386Impl:: INLINE AtomicAdjustI386Impl::Pointer AtomicAdjustI386Impl::
get_ptr(void * const TVOLATILE &var) { get_ptr(const TVOLATILE AtomicAdjustI386Impl::Pointer &var) {
assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0);
return var; return var;
} }
@ -150,8 +159,10 @@ get_ptr(void * const TVOLATILE &var) {
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl:: INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl::
compare_and_exchange(TVOLATILE AtomicAdjustI386Impl::Integer &mem, AtomicAdjustI386Impl::Integer old_value, compare_and_exchange(TVOLATILE AtomicAdjustI386Impl::Integer &mem,
AtomicAdjustI386Impl::Integer old_value,
AtomicAdjustI386Impl::Integer new_value) { AtomicAdjustI386Impl::Integer new_value) {
assert((((size_t)&mem) & (sizeof(Integer) - 1)) == 0);
Integer prev; Integer prev;
#ifdef _M_IX86 #ifdef _M_IX86
// Windows case // Windows case
@ -180,13 +191,15 @@ compare_and_exchange(TVOLATILE AtomicAdjustI386Impl::Integer &mem, AtomicAdjustI
// //
// As above, but works on pointers instead of integers. // As above, but works on pointers instead of integers.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustI386Impl:: INLINE AtomicAdjustI386Impl::Pointer AtomicAdjustI386Impl::
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value, compare_and_exchange_ptr(TVOLATILE AtomicAdjustI386Impl::Pointer &mem,
void *new_value) { AtomicAdjustI386Impl::Pointer old_value,
void *prev; AtomicAdjustI386Impl::Pointer new_value) {
assert((((size_t)&mem) & (sizeof(Pointer) - 1)) == 0);
Pointer prev;
#ifdef _M_IX86 #ifdef _M_IX86
// Windows case // Windows case
void * TVOLATILE *mem_ptr = &mem; TVOLATILE Pointer *mem_ptr = &mem;
__asm { __asm {
mov edx, mem_ptr; mov edx, mem_ptr;
mov ecx, new_value; mov ecx, new_value;

View File

@ -31,7 +31,9 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
class EXPCL_DTOOL AtomicAdjustI386Impl { class EXPCL_DTOOL AtomicAdjustI386Impl {
public: public:
typedef PN_int32 Integer; typedef ALIGN_4BYTE PN_int32 Integer;
typedef void *UnalignedPointer;
typedef ALIGN_4BYTE UnalignedPointer Pointer;
INLINE static void inc(TVOLATILE Integer &var); INLINE static void inc(TVOLATILE Integer &var);
INLINE static bool dec(TVOLATILE Integer &var); INLINE static bool dec(TVOLATILE Integer &var);
@ -39,16 +41,16 @@ public:
INLINE static Integer set(TVOLATILE Integer &var, Integer new_value); INLINE static Integer set(TVOLATILE Integer &var, Integer new_value);
INLINE static Integer get(const TVOLATILE Integer &var); INLINE static Integer get(const TVOLATILE Integer &var);
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value); INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value);
INLINE static void *get_ptr(void * const TVOLATILE &var); INLINE static Pointer get_ptr(const TVOLATILE Pointer &var);
INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem, INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem,
Integer old_value, Integer old_value,
Integer new_value); Integer new_value);
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem, INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem,
void *old_value, Pointer old_value,
void *new_value); Pointer new_value);
}; };
#include "atomicAdjustI386Impl.I" #include "atomicAdjustI386Impl.I"

View File

@ -91,10 +91,10 @@ get(const TVOLATILE AtomicAdjustPosixImpl::Integer &var) {
// Description: Atomically changes the indicated variable and // Description: Atomically changes the indicated variable and
// returns the original value. // returns the original value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustPosixImpl:: INLINE Pointer AtomicAdjustPosixImpl::
set_ptr(void * TVOLATILE &var, void *new_value) { set_ptr(TVOLATILE Pointer &var, Pointer new_value) {
pthread_mutex_lock(&_mutex); pthread_mutex_lock(&_mutex);
void *orig_value = var; Pointer orig_value = var;
var = new_value; var = new_value;
pthread_mutex_unlock(&_mutex); pthread_mutex_unlock(&_mutex);
return orig_value; return orig_value;
@ -109,10 +109,10 @@ set_ptr(void * TVOLATILE &var, void *new_value) {
// asynchronously setting, incrementing, or decrementing // asynchronously setting, incrementing, or decrementing
// (via other AtomicAjust methods). // (via other AtomicAjust methods).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustPosixImpl:: INLINE Pointer AtomicAdjustPosixImpl::
get_ptr(void * const TVOLATILE &var) { get_ptr(const TVOLATILE Pointer &var) {
pthread_mutex_lock(&_mutex); pthread_mutex_lock(&_mutex);
void *orig_value = var; Pointer orig_value = var;
pthread_mutex_unlock(&_mutex); pthread_mutex_unlock(&_mutex);
return orig_value; return orig_value;
} }
@ -155,11 +155,11 @@ compare_and_exchange(TVOLATILE AtomicAdjustPosixImpl::Integer &mem, AtomicAdjust
// //
// As above, but works on pointers instead of integers. // As above, but works on pointers instead of integers.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustPosixImpl:: INLINE Pointer AtomicAdjustPosixImpl::
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value, compare_and_exchange_ptr(TVOLATILE Pointer &mem, Pointer old_value,
void *new_value) { Pointer new_value) {
pthread_mutex_lock(&_mutex); pthread_mutex_lock(&_mutex);
void *orig_value = mem; Pointer orig_value = mem;
if (mem == old_value) { if (mem == old_value) {
mem = new_value; mem = new_value;
} }

View File

@ -33,6 +33,7 @@ public:
// In Posix, "long" is generally the native word size (32- or // In Posix, "long" is generally the native word size (32- or
// 64-bit), which is what we'd prefer. // 64-bit), which is what we'd prefer.
typedef long Integer; typedef long Integer;
typedef void *Pointer;
INLINE static void inc(TVOLATILE Integer &var); INLINE static void inc(TVOLATILE Integer &var);
INLINE static bool dec(TVOLATILE Integer &var); INLINE static bool dec(TVOLATILE Integer &var);
@ -40,16 +41,16 @@ public:
INLINE static Integer set(TVOLATILE Integer &var, Integer new_value); INLINE static Integer set(TVOLATILE Integer &var, Integer new_value);
INLINE static Integer get(const TVOLATILE Integer &var); INLINE static Integer get(const TVOLATILE Integer &var);
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value); INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value);
INLINE static void *get_ptr(void * const TVOLATILE &var); INLINE static Pointer get_ptr(const TVOLATILE Pointer &var);
INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem, INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem,
Integer old_value, Integer old_value,
Integer new_value); Integer new_value);
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem, INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem,
void *old_value, Pointer old_value,
void *new_value); Pointer new_value);
private: private:
static pthread_mutex_t _mutex; static pthread_mutex_t _mutex;

View File

@ -20,6 +20,7 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void AtomicAdjustWin32Impl:: INLINE void AtomicAdjustWin32Impl::
inc(TVOLATILE AtomicAdjustWin32Impl::Integer &var) { inc(TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
#ifdef _WIN64 #ifdef _WIN64
InterlockedIncrement64(&var); InterlockedIncrement64(&var);
#else #else
@ -36,6 +37,7 @@ inc(TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool AtomicAdjustWin32Impl:: INLINE bool AtomicAdjustWin32Impl::
dec(TVOLATILE AtomicAdjustWin32Impl::Integer &var) { dec(TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
#ifdef _WIN64 #ifdef _WIN64
return (InterlockedDecrement64(&var) != 0); return (InterlockedDecrement64(&var) != 0);
#else #else
@ -64,7 +66,9 @@ add(TVOLATILE AtomicAdjustWin32Impl::Integer &var, AtomicAdjustWin32Impl::Intege
// returns the original value. // returns the original value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl:: INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl::
set(TVOLATILE AtomicAdjustWin32Impl::Integer &var, AtomicAdjustWin32Impl::Integer new_value) { set(TVOLATILE AtomicAdjustWin32Impl::Integer &var,
AtomicAdjustWin32Impl::Integer new_value) {
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
#ifdef _WIN64 #ifdef _WIN64
return InterlockedExchange64(&var, new_value); return InterlockedExchange64(&var, new_value);
#else #else
@ -83,6 +87,12 @@ set(TVOLATILE AtomicAdjustWin32Impl::Integer &var, AtomicAdjustWin32Impl::Intege
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl:: INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl::
get(const TVOLATILE AtomicAdjustWin32Impl::Integer &var) { get(const TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
// On Intel platforms, word-aligned loads are atomic (if performed
// in a single instruction). We can't guarantee the compiler will
// generate a single instruction to load this value, but it
// certainly won't happen if its address isn't word-aligned, so make
// sure that's the case.
assert((((size_t)&var) & (sizeof(Integer) - 1)) == 0);
return var; return var;
} }
@ -92,11 +102,11 @@ get(const TVOLATILE AtomicAdjustWin32Impl::Integer &var) {
// Description: Atomically changes the indicated variable and // Description: Atomically changes the indicated variable and
// returns the original value. // returns the original value.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustWin32Impl:: INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl::
set_ptr(void * TVOLATILE &var, void *new_value) { set_ptr(TVOLATILE AtomicAdjustWin32Impl::Pointer &var,
void *orig_value = var; AtomicAdjustWin32Impl::Pointer new_value) {
var = new_value; assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0);
return orig_value; return InterlockedExchangePointer(&var, new_value);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -108,8 +118,10 @@ set_ptr(void * TVOLATILE &var, void *new_value) {
// asynchronously setting, incrementing, or decrementing // asynchronously setting, incrementing, or decrementing
// (via other AtomicAjust methods). // (via other AtomicAjust methods).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustWin32Impl:: INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl::
get_ptr(void * const TVOLATILE &var) { get_ptr(const TVOLATILE AtomicAdjustWin32Impl::Pointer &var) {
// As in get(), make sure the address is word-aligned.
assert((((size_t)&var) & (sizeof(Pointer) - 1)) == 0);
return var; return var;
} }
@ -133,8 +145,10 @@ get_ptr(void * const TVOLATILE &var) {
// //
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl:: INLINE AtomicAdjustWin32Impl::Integer AtomicAdjustWin32Impl::
compare_and_exchange(TVOLATILE AtomicAdjustWin32Impl::Integer &mem, AtomicAdjustWin32Impl::Integer old_value, compare_and_exchange(TVOLATILE AtomicAdjustWin32Impl::Integer &mem,
AtomicAdjustWin32Impl::Integer old_value,
AtomicAdjustWin32Impl::Integer new_value) { AtomicAdjustWin32Impl::Integer new_value) {
assert((((size_t)&mem) & (sizeof(Integer) - 1)) == 0);
// Note that the AtomicAdjust parameter order is different from // Note that the AtomicAdjust parameter order is different from
// Windows convention! // Windows convention!
#ifdef _WIN64 #ifdef _WIN64
@ -151,9 +165,11 @@ compare_and_exchange(TVOLATILE AtomicAdjustWin32Impl::Integer &mem, AtomicAdjust
// //
// As above, but works on pointers instead of integers. // As above, but works on pointers instead of integers.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE void *AtomicAdjustWin32Impl:: INLINE AtomicAdjustWin32Impl::Pointer AtomicAdjustWin32Impl::
compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value, compare_and_exchange_ptr(TVOLATILE AtomicAdjustWin32Impl::Pointer &mem,
void *new_value) { AtomicAdjustWin32Impl::Pointer old_value,
AtomicAdjustWin32Impl::Pointer new_value) {
assert((((size_t)&mem) & (sizeof(Pointer) - 1)) == 0);
// Note that the AtomicAdjust parameter order is different from // Note that the AtomicAdjust parameter order is different from
// Windows convention! // Windows convention!
return InterlockedCompareExchangePointer(&mem, new_value, old_value); return InterlockedCompareExchangePointer(&mem, new_value, old_value);

View File

@ -33,9 +33,13 @@ class EXPCL_DTOOL AtomicAdjustWin32Impl {
public: public:
#ifdef _WIN64 #ifdef _WIN64
// For 64-bit builds, we'd prefer to use a 64-bit integer. // For 64-bit builds, we'd prefer to use a 64-bit integer.
typedef LONGLONG Integer; typedef ALIGN_8BYTE LONGLONG Integer;
typedef void *UnalignedPointer;
typedef ALIGN_8BYTE UnalignedPointer Pointer;
#else #else
typedef LONG Integer; typedef ALIGN_4BYTE LONG Integer;
typedef void *UnalignedPointer;
typedef ALIGN_4BYTE UnalignedPointer Pointer;
#endif // _WIN64 #endif // _WIN64
INLINE static void inc(TVOLATILE Integer &var); INLINE static void inc(TVOLATILE Integer &var);
@ -44,16 +48,16 @@ public:
INLINE static Integer set(TVOLATILE Integer &var, Integer new_value); INLINE static Integer set(TVOLATILE Integer &var, Integer new_value);
INLINE static Integer get(const TVOLATILE Integer &var); INLINE static Integer get(const TVOLATILE Integer &var);
INLINE static void *set_ptr(void * TVOLATILE &var, void *new_value); INLINE static Pointer set_ptr(TVOLATILE Pointer &var, Pointer new_value);
INLINE static void *get_ptr(void * const TVOLATILE &var); INLINE static Pointer get_ptr(const TVOLATILE Pointer &var);
INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem, INLINE static Integer compare_and_exchange(TVOLATILE Integer &mem,
Integer old_value, Integer old_value,
Integer new_value); Integer new_value);
INLINE static void *compare_and_exchange_ptr(void * TVOLATILE &mem, INLINE static Pointer compare_and_exchange_ptr(TVOLATILE Pointer &mem,
void *old_value, Pointer old_value,
void *new_value); Pointer new_value);
}; };
#include "atomicAdjustWin32Impl.I" #include "atomicAdjustWin32Impl.I"

View File

@ -312,6 +312,21 @@
#define NATIVE_WORDSIZE 32 #define NATIVE_WORDSIZE 32
#endif #endif
/* Some byte-alignment macros. */
#ifdef CPPPARSER
#define ALIGN_4BYTE
#define ALIGN_8BYTE
#elif defined(WIN32_VC)
#define ALIGN_4BYTE __declspec(align(4))
#define ALIGN_8BYTE __declspec(align(8))
#elif defined(__GNUC__)
#define ALIGN_4BYTE __attribute__ ((aligned (4)))
#define ALIGN_8BYTE __attribute__ ((aligned (8)))
#else
#define ALIGN_4BYTE
#define ALIGN_8BYTE
#endif
/* /*
We define the macros BEGIN_PUBLISH and END_PUBLISH to bracket We define the macros BEGIN_PUBLISH and END_PUBLISH to bracket

View File

@ -27,7 +27,7 @@ static const size_t min_page_size = 128 * 1024; // 128K
// We always allocate integer multiples of this many bytes, to // We always allocate integer multiples of this many bytes, to
// guarantee this minimum alignment. // guarantee this minimum alignment.
static const size_t alignment_size = sizeof(long); static const size_t alignment_size = sizeof(void *);
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NeverFreeMemory::Constructor // Function: NeverFreeMemory::Constructor

View File

@ -51,10 +51,10 @@
TextEncoder::Encoding Filename::_filesystem_encoding = TextEncoder::E_utf8; TextEncoder::Encoding Filename::_filesystem_encoding = TextEncoder::E_utf8;
Filename *Filename::_home_directory; TVOLATILE AtomicAdjust::Pointer Filename::_home_directory;
Filename *Filename::_temp_directory; TVOLATILE AtomicAdjust::Pointer Filename::_temp_directory;
Filename *Filename::_user_appdata_directory; TVOLATILE AtomicAdjust::Pointer Filename::_user_appdata_directory;
Filename *Filename::_common_appdata_directory; TVOLATILE AtomicAdjust::Pointer Filename::_common_appdata_directory;
TypeHandle Filename::_type_handle; TypeHandle Filename::_type_handle;
#ifdef WIN32 #ifdef WIN32
@ -506,7 +506,7 @@ temporary(const string &dirname, const string &prefix, const string &suffix,
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_home_directory() { get_home_directory() {
if (AtomicAdjust::get_ptr((void * TVOLATILE &)_home_directory) == NULL) { if (AtomicAdjust::get_ptr(_home_directory) == NULL) {
Filename home_directory; Filename home_directory;
// In all environments, check $HOME first. // In all environments, check $HOME first.
@ -549,14 +549,14 @@ get_home_directory() {
} }
Filename *newdir = new Filename(home_directory); Filename *newdir = new Filename(home_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_home_directory, NULL, newdir) != NULL) { if (AtomicAdjust::compare_and_exchange_ptr(_home_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else. // Didn't store it. Must have been stored by someone else.
assert(_home_directory != NULL); assert(_home_directory != NULL);
delete newdir; delete newdir;
} }
} }
return (*_home_directory); return (*(Filename *)_home_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -567,7 +567,7 @@ get_home_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_temp_directory() { get_temp_directory() {
if (AtomicAdjust::get_ptr((void * TVOLATILE &)_temp_directory) == NULL) { if (AtomicAdjust::get_ptr(_temp_directory) == NULL) {
Filename temp_directory; Filename temp_directory;
#ifdef WIN32 #ifdef WIN32
@ -596,14 +596,14 @@ get_temp_directory() {
} }
Filename *newdir = new Filename(temp_directory); Filename *newdir = new Filename(temp_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_temp_directory, NULL, newdir) != NULL) { if (AtomicAdjust::compare_and_exchange_ptr(_temp_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else. // Didn't store it. Must have been stored by someone else.
assert(_temp_directory != NULL); assert(_temp_directory != NULL);
delete newdir; delete newdir;
} }
} }
return (*_temp_directory); return (*(Filename *)_temp_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -616,7 +616,7 @@ get_temp_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_user_appdata_directory() { get_user_appdata_directory() {
if (AtomicAdjust::get_ptr((void * TVOLATILE &)_user_appdata_directory) == NULL) { if (AtomicAdjust::get_ptr(_user_appdata_directory) == NULL) {
Filename user_appdata_directory; Filename user_appdata_directory;
#ifdef WIN32 #ifdef WIN32
@ -646,14 +646,14 @@ get_user_appdata_directory() {
} }
Filename *newdir = new Filename(user_appdata_directory); Filename *newdir = new Filename(user_appdata_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_user_appdata_directory, NULL, newdir) != NULL) { if (AtomicAdjust::compare_and_exchange_ptr(_user_appdata_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else. // Didn't store it. Must have been stored by someone else.
assert(_user_appdata_directory != NULL); assert(_user_appdata_directory != NULL);
delete newdir; delete newdir;
} }
} }
return (*_user_appdata_directory); return (*(Filename *)_user_appdata_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -665,7 +665,7 @@ get_user_appdata_directory() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
const Filename &Filename:: const Filename &Filename::
get_common_appdata_directory() { get_common_appdata_directory() {
if (AtomicAdjust::get_ptr((void * TVOLATILE &)_common_appdata_directory) == NULL) { if (AtomicAdjust::get_ptr(_common_appdata_directory) == NULL) {
Filename common_appdata_directory; Filename common_appdata_directory;
#ifdef WIN32 #ifdef WIN32
@ -694,14 +694,14 @@ get_common_appdata_directory() {
} }
Filename *newdir = new Filename(common_appdata_directory); Filename *newdir = new Filename(common_appdata_directory);
if (AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_common_appdata_directory, NULL, newdir) != NULL) { if (AtomicAdjust::compare_and_exchange_ptr(_common_appdata_directory, NULL, newdir) != NULL) {
// Didn't store it. Must have been stored by someone else. // Didn't store it. Must have been stored by someone else.
assert(_common_appdata_directory != NULL); assert(_common_appdata_directory != NULL);
delete newdir; delete newdir;
} }
} }
return (*_common_appdata_directory); return (*(Filename *)_common_appdata_directory);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -256,10 +256,10 @@ protected:
int _flags; int _flags;
static TextEncoder::Encoding _filesystem_encoding; static TextEncoder::Encoding _filesystem_encoding;
static Filename *_home_directory; static TVOLATILE AtomicAdjust::Pointer _home_directory;
static Filename *_temp_directory; static TVOLATILE AtomicAdjust::Pointer _temp_directory;
static Filename *_user_appdata_directory; static TVOLATILE AtomicAdjust::Pointer _user_appdata_directory;
static Filename *_common_appdata_directory; static TVOLATILE AtomicAdjust::Pointer _common_appdata_directory;
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {

View File

@ -106,7 +106,7 @@ PT(AudioManager) AudioManager::create_AudioManager() {
AudioManager:: AudioManager::
~AudioManager() { ~AudioManager() {
if (_null_sound != (AudioSound *)NULL) { if (_null_sound != (AudioSound *)NULL) {
unref_delete(_null_sound); unref_delete((AudioSound *)_null_sound);
} }
} }
@ -146,7 +146,7 @@ get_null_sound() {
if (_null_sound == (AudioSound *)NULL) { if (_null_sound == (AudioSound *)NULL) {
AudioSound *new_sound = new NullAudioSound; AudioSound *new_sound = new NullAudioSound;
new_sound->ref(); new_sound->ref();
void *result = AtomicAdjust::compare_and_exchange_ptr((void * TVOLATILE &)_null_sound, (void *)NULL, (void *)new_sound); void *result = AtomicAdjust::compare_and_exchange_ptr(_null_sound, (void *)NULL, (void *)new_sound);
if (result != NULL) { if (result != NULL) {
// Someone else must have assigned the AudioSound first. OK. // Someone else must have assigned the AudioSound first. OK.
nassertr(_null_sound != new_sound, NULL); nassertr(_null_sound != new_sound, NULL);
@ -155,7 +155,7 @@ get_null_sound() {
nassertr(_null_sound != NULL, NULL); nassertr(_null_sound != NULL, NULL);
} }
return _null_sound; return (AudioSound *)_null_sound;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -21,6 +21,7 @@
#include "lvecBase3.h" #include "lvecBase3.h"
#include "filterProperties.h" #include "filterProperties.h"
#include "movieAudio.h" #include "movieAudio.h"
#include "atomicAdjust.h"
typedef AudioManager *Create_AudioManager_proc(); typedef AudioManager *Create_AudioManager_proc();
@ -205,7 +206,7 @@ protected:
// best flexibility. // best flexibility.
static Create_AudioManager_proc* _create_AudioManager; static Create_AudioManager_proc* _create_AudioManager;
AudioSound *_null_sound; AtomicAdjust::Pointer _null_sound;
AudioManager(); AudioManager();

View File

@ -18,6 +18,7 @@
#include "pandabase.h" #include "pandabase.h"
#include "pnotify.h" #include "pnotify.h"
#include "memoryBase.h" #include "memoryBase.h"
#include "atomicAdjust.h"
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : PointerToVoid // Class : PointerToVoid
@ -62,7 +63,7 @@ protected:
// from ReferenceCount. (You can't downcast past a virtual // from ReferenceCount. (You can't downcast past a virtual
// inheritance level, but you can always cross-cast from a void // inheritance level, but you can always cross-cast from a void
// pointer.) // pointer.)
void *_void_ptr; AtomicAdjust::Pointer _void_ptr;
}; };
#include "pointerToVoid.I" #include "pointerToVoid.I"

View File

@ -130,7 +130,7 @@ ReferenceCount::
// Tell our weak reference holders that we're going away now. // Tell our weak reference holders that we're going away now.
if (_weak_list != (WeakReferenceList *)NULL) { if (_weak_list != (WeakReferenceList *)NULL) {
delete _weak_list; delete (WeakReferenceList *)_weak_list;
_weak_list = (WeakReferenceList *)NULL; _weak_list = (WeakReferenceList *)NULL;
} }
@ -305,10 +305,10 @@ has_weak_list() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE WeakReferenceList *ReferenceCount:: INLINE WeakReferenceList *ReferenceCount::
get_weak_list() const { get_weak_list() const {
if (_weak_list == (WeakReferenceList *)NULL) { if (AtomicAdjust::get_ptr(_weak_list) == (WeakReferenceList *)NULL) {
((ReferenceCount *)this)->create_weak_list(); ((ReferenceCount *)this)->create_weak_list();
} }
return _weak_list; return (WeakReferenceList *)AtomicAdjust::get_ptr(_weak_list);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -334,7 +334,7 @@ INLINE void ReferenceCount::
weak_unref(WeakPointerToVoid *ptv) { weak_unref(WeakPointerToVoid *ptv) {
TAU_PROFILE("void ReferenceCount::weak_unref()", " ", TAU_USER); TAU_PROFILE("void ReferenceCount::weak_unref()", " ", TAU_USER);
nassertv(has_weak_list()); nassertv(has_weak_list());
_weak_list->clear_reference(ptv); ((WeakReferenceList *)_weak_list)->clear_reference(ptv);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -70,7 +70,7 @@ void ReferenceCount::
create_weak_list() { create_weak_list() {
WeakReferenceList *weak_list = new WeakReferenceList; WeakReferenceList *weak_list = new WeakReferenceList;
void *orig = void *orig =
AtomicAdjust::compare_and_exchange_ptr((void *&)_weak_list, NULL, weak_list); AtomicAdjust::compare_and_exchange_ptr(_weak_list, NULL, weak_list);
if (orig != (void *)NULL) { if (orig != (void *)NULL) {
// Someone else created it first. // Someone else created it first.
delete weak_list; delete weak_list;

View File

@ -88,7 +88,7 @@ private:
}; };
AtomicAdjust::Integer _ref_count; AtomicAdjust::Integer _ref_count;
WeakReferenceList *_weak_list; AtomicAdjust::Pointer _weak_list; // WeakReferenceList *
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {

View File

@ -191,7 +191,7 @@ private:
PerThread _per_thread; PerThread _per_thread;
}; };
typedef Collector *CollectorPointer; typedef Collector *CollectorPointer;
void *_collectors; // CollectorPointer *_collectors; AtomicAdjust::Pointer _collectors; // CollectorPointer *_collectors;
AtomicAdjust::Integer _collectors_size; // size of the allocated array AtomicAdjust::Integer _collectors_size; // size of the allocated array
AtomicAdjust::Integer _num_collectors; // number of in-use elements within the array AtomicAdjust::Integer _num_collectors; // number of in-use elements within the array
@ -219,7 +219,7 @@ private:
LightMutex _thread_lock; LightMutex _thread_lock;
}; };
typedef InternalThread *ThreadPointer; typedef InternalThread *ThreadPointer;
void *_threads; // ThreadPointer *_threads; AtomicAdjust::Pointer _threads; // ThreadPointer *_threads;
AtomicAdjust::Integer _threads_size; // size of the allocated array AtomicAdjust::Integer _threads_size; // size of the allocated array
AtomicAdjust::Integer _num_threads; // number of in-use elements within the array AtomicAdjust::Integer _num_threads; // number of in-use elements within the array