Permalink
Browse files

The flags used for call_once need to be declared volatile *every time*,

so let's make that part of the typedef.

Also, on Win32 and Linux, CAS operations return the old value, not a
boolean flag.
  • Loading branch information...
1 parent 606e58f commit a32a2759e890fa927effe5538087bf14d5709284 @jfinkhaeuser jfinkhaeuser committed Mar 28, 2012
Showing with 11 additions and 10 deletions.
  1. +7 −6 thirdparty/tinythread/1_0/source/once.cpp
  2. +4 −4 thirdparty/tinythread/1_0/source/once.h
@@ -10,26 +10,27 @@ namespace tthread {
bool __atomic_cas(once_flag old_value,
once_flag new_value,
- volatile once_flag& ref)
+ once_flag& ref)
{
#if ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= MAC_OS_X_VERSION_10_5) || (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= __IPHONE_2_0))
-
+ // OSAtomicCompareAndSwap returns true/false if the new value could be set.
+ // On other OSes, the value *before* the swap is returned.
return OSAtomicCompareAndSwapInt(old_value,
new_value,
&ref);
#elif (defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN2K) || (defined(WINVER) && WINVER >= _WIN32_WINNT_WIN2K)
- return InterlockedCompareExchange(&ref,
+ return (old_value == InterlockedCompareExchange(&ref,
new_value,
- old_value);
+ old_value));
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
- return __sync_val_compare_and_swap(&ref,
+ return (old_value == __sync_val_compare_and_swap(&ref,
old_value,
- new_value);
+ new_value));
#else
@@ -7,16 +7,16 @@
namespace tthread
{
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= MAC_OS_X_VERSION_10_5 || __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= __IPHONE_2_0)
- typedef int32_t once_flag;
+ typedef volatile int32_t once_flag;
#elif (defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN2K) || (defined(WINVER) && WINVER >= _WIN32_WINNT_WIN2K)
- typedef long once_flag;
+ typedef volatile long once_flag;
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
- typedef long once_flag;
+ typedef volatile long once_flag;
#endif
bool __atomic_cas(once_flag old_value,
once_flag new_value,
- volatile once_flag& ref);
+ once_flag& ref);
inline void call_once(void(*f)(), once_flag& flag) {
if (__atomic_cas(TTHREAD_ONCE_INIT, TTHREAD_ONCE_FINAL, flag)) {

0 comments on commit a32a275

Please sign in to comment.