Browse Source

Add atomics for 64-bit integers

Pedro J. Estébanez 8 years ago
parent
commit
0b776f9a30
2 changed files with 71 additions and 0 deletions
  1. 67 0
      core/safe_refcount.cpp
  2. 4 0
      core/safe_refcount.h

+ 67 - 0
core/safe_refcount.cpp

@@ -57,6 +57,30 @@ uint32_t atomic_decrement(register uint32_t *pw) {
 	return *pw;
 }
 
+uint64_t atomic_conditional_increment(register uint64_t *pw) {
+
+	if (*pw == 0)
+		return 0;
+
+	(*pw)++;
+
+	return *pw;
+}
+
+uint64_t atomic_increment(register uint64_t *pw) {
+
+	(*pw)++;
+
+	return *pw;
+}
+
+uint64_t atomic_decrement(register uint64_t *pw) {
+
+	(*pw)--;
+
+	return *pw;
+}
+
 #else
 
 #ifdef _MSC_VER
@@ -84,6 +108,28 @@ uint32_t atomic_decrement(register uint32_t *pw) {
 uint32_t atomic_increment(register uint32_t *pw) {
 	return InterlockedIncrement((LONG volatile *)pw);
 }
+
+uint64_t atomic_conditional_increment(register uint64_t *pw) {
+
+	/* try to increment until it actually works */
+	// taken from boost
+
+	while (true) {
+		uint64_t tmp = static_cast<uint64_t const volatile &>(*pw);
+		if (tmp == 0)
+			return 0; // if zero, can't add to it anymore
+		if (InterlockedCompareExchange64((LONGLONG volatile *)pw, tmp + 1, tmp) == tmp)
+			return tmp + 1;
+	}
+}
+
+uint64_t atomic_decrement(register uint64_t *pw) {
+	return InterlockedDecrement64((LONGLONG volatile *)pw);
+}
+
+uint64_t atomic_increment(register uint64_t *pw) {
+	return InterlockedIncrement64((LONGLONG volatile *)pw);
+}
 #elif defined(__GNUC__)
 
 uint32_t atomic_conditional_increment(register uint32_t *pw) {
@@ -107,6 +153,27 @@ uint32_t atomic_increment(register uint32_t *pw) {
 	return __sync_add_and_fetch(pw, 1);
 }
 
+uint64_t atomic_conditional_increment(register uint64_t *pw) {
+
+	while (true) {
+		uint64_t tmp = static_cast<uint64_t const volatile &>(*pw);
+		if (tmp == 0)
+			return 0; // if zero, can't add to it anymore
+		if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
+			return tmp + 1;
+	}
+}
+
+uint64_t atomic_decrement(register uint64_t *pw) {
+
+	return __sync_sub_and_fetch(pw, 1);
+}
+
+uint64_t atomic_increment(register uint64_t *pw) {
+
+	return __sync_add_and_fetch(pw, 1);
+}
+
 #else
 //no threads supported?
 #error Must provide atomic functions for this platform or compiler!

+ 4 - 0
core/safe_refcount.h

@@ -40,6 +40,10 @@ uint32_t atomic_conditional_increment(register uint32_t *counter);
 uint32_t atomic_decrement(register uint32_t *pw);
 uint32_t atomic_increment(register uint32_t *pw);
 
+uint64_t atomic_conditional_increment(register uint64_t *counter);
+uint64_t atomic_decrement(register uint64_t *pw);
+uint64_t atomic_increment(register uint64_t *pw);
+
 struct SafeRefCount {
 
 	uint32_t count;