Changeset: 819615f16909 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=819615f16909 Modified Files: gdk/gdk_atomic.h Branch: default Log Message:
Introduce ATOMIC_CAS (compare and set) macro/function. diffs (98 lines): diff --git a/gdk/gdk_atomic.h b/gdk/gdk_atomic.h --- a/gdk/gdk_atomic.h +++ b/gdk/gdk_atomic.h @@ -17,6 +17,7 @@ * ATOMIC_GET -- return the value of a variable; * ATOMIC_SET -- set the value of a variable; * ATOMIC_XCG -- set the value of a variable, return original value; + * ATOMIC_CAS -- compare-and-set (see below) * ATOMIC_ADD -- add a value to a variable, return original value; * ATOMIC_SUB -- subtract a value from a variable, return original value; * ATOMIC_INC -- increment a variable's value, return new value; @@ -24,6 +25,12 @@ * These interfaces work on variables of type ATOMIC_TYPE * (int or int64_t depending on architecture). * + * The compare-and-set operation is based on the C11 standard: if the + * atomic variable equals the expected value, the atomic variable is + * replaced by the desired value and true is returned. Otherwise, the + * expected value is replaced by the current value of the atomic + * variable and false is returned. + * * Some of these are also available for pointers: * ATOMIC_PTR_INIT * ATOMIC_GET_PTR @@ -79,6 +86,7 @@ typedef unsigned long long ATOMIC_BASE_T #define ATOMIC_GET(var) atomic_load(var) #define ATOMIC_SET(var, val) atomic_store(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_XCG(var, val) atomic_exchange(var, (ATOMIC_BASE_TYPE) (val)) +#define ATOMIC_CAS(var, exp, des) atomic_compare_exchange_strong(var, exp, (ATOMIC_BASE_TYPE) (des)) #define ATOMIC_ADD(var, val) atomic_fetch_add(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_SUB(var, val) atomic_fetch_sub(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_INC(var) (atomic_fetch_add(var, 1) + 1) @@ -129,6 +137,16 @@ typedef int64_t ATOMIC_BASE_TYPE; #endif #define ATOMIC_SET(var, val) _InterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_XCG(var, val) _InterlockedExchange64(var, (ATOMIC_BASE_TYPE) (val)) +static inline bool +ATOMIC_CAS(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE *exp, ATOMIC_BASE_TYPE des) +{ + ATOMIC_BASE_TYPE old; + old = _InterlockedCompareExchange64(var, des, *exp); + if (old == *exp) + return true; + *exp = old; + return false; +} #define ATOMIC_ADD(var, val) _InterlockedExchangeAdd64(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_SUB(var, val) _InterlockedExchangeAdd64(var, -(ATOMIC_BASE_TYPE) (val)) #define ATOMIC_INC(var) _InterlockedIncrement64(var) @@ -155,6 +173,16 @@ typedef int ATOMIC_BASE_TYPE; #endif #define ATOMIC_SET(var, val) _InterlockedExchange(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_XCG(var, val) _InterlockedExchange(var, (ATOMIC_BASE_TYPE) (val)) +static inline bool +ATOMIC_CAS(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE *exp, ATOMIC_BASE_TYPE des) +{ + ATOMIC_BASE_TYPE old; + old = _InterlockedCompareExchange(var, des, *exp); + if (old == *exp) + return true; + *exp = old; + return false; +} #define ATOMIC_ADD(var, val) _InterlockedExchangeAdd(var, (ATOMIC_BASE_TYPE) (val)) #define ATOMIC_SUB(var, val) _InterlockedExchangeAdd(var, -(ATOMIC_BASE_TYPE) (val)) #define ATOMIC_INC(var) _InterlockedIncrement(var) @@ -195,6 +223,7 @@ typedef int ATOMIC_TYPE; #define ATOMIC_GET(var) __atomic_load_n(var, __ATOMIC_SEQ_CST) #define ATOMIC_SET(var, val) __atomic_store_n(var, (ATOMIC_TYPE) (val), __ATOMIC_SEQ_CST) #define ATOMIC_XCG(var, val) __atomic_exchange_n(var, (ATOMIC_TYPE) (val), __ATOMIC_SEQ_CST +#define ATOMIC_CAS(var, exp, des) __atomic_compare_exchange_n(var, exp, (ATOMIC_TYPE) (des), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) #define ATOMIC_ADD(var, val) __atomic_fetch_add(var, (ATOMIC_TYPE) (val), __ATOMIC_SEQ_CST) #define ATOMIC_SUB(var, val) __atomic_fetch_sub(var, (ATOMIC_TYPE) (val), __ATOMIC_SEQ_CST) #define ATOMIC_INC(var) __atomic_add_fetch(var, 1, __ATOMIC_SEQ_CST) @@ -260,6 +289,23 @@ ATOMIC_XCG(ATOMIC_TYPE *var, ATOMIC_BASE } #define ATOMIC_XCG(var, val) ATOMIC_XCG(var, (ATOMIC_BASE_TYPE) (val)) +static inline bool +ATOMIC_CAS(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE *exp, ATOMIC_BASE_TYPE des) +{ + bool ret; + pthread_mutex_lock(&var->lck); + if (var->val == *exp) { + var->val = des; + ret = true; + } else { + *exp = var->val; + ret = false; + } + pthread_mutex_unlock(&var->lck); + return ret; +} +#define ATOMIC_CAS(var, exp, des) ATOMIC_CAS(var, exp, (ATOMIC_BASE_TYPE) (des)) + static inline ATOMIC_BASE_TYPE ATOMIC_ADD(ATOMIC_TYPE *var, ATOMIC_BASE_TYPE val) { _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list