Jelajahi Sumber

Added atomicFetchAndAddsat/Subsat.

Branimir Karadžić 8 tahun lalu
induk
melakukan
b6a01bf42c
6 mengubah file dengan 104 tambahan dan 6 penghapusan
  1. 8 0
      include/bx/bx.h
  2. 8 0
      include/bx/cpu.h
  3. 12 0
      include/bx/inline/bx.inl
  4. 30 0
      include/bx/inline/cpu.inl
  5. 0 6
      src/string.cpp
  6. 46 0
      tests/atomic_test.cpp

+ 8 - 0
include/bx/bx.h

@@ -44,6 +44,14 @@ namespace bx
 	///
 	void xchg(void* _a, void* _b, size_t _numBytes);
 
+	///
+	template<typename Ty>
+	Ty min(const Ty& _a, const Ty& _b);
+
+	///
+	template<typename Ty>
+	Ty max(const Ty& _a, const Ty& _b);
+
 	// http://cnicholson.net/2011/01/stupid-c-tricks-a-better-sizeof_array/
 	template<typename T, size_t N>
 	char (&COUNTOF_REQUIRES_ARRAY_ARGUMENT(const T(&)[N]) )[N];

+ 8 - 0
include/bx/cpu.h

@@ -50,6 +50,14 @@ namespace bx
 	template<typename Ty>
 	Ty atomicFetchTestAndSub(volatile Ty* _ptr, Ty _test, Ty _value);
 
+	///
+	template<typename Ty>
+	Ty atomicFetchAndAddsat(volatile Ty* _ptr, Ty _value, Ty _max);
+
+	///
+	template<typename Ty>
+	Ty atomicFetchAndSubsat(volatile Ty* _ptr, Ty _value, Ty _min);
+
 	///
 	void* atomicExchangePtr(void** _ptr, void* _new);
 

+ 12 - 0
include/bx/inline/bx.inl

@@ -32,4 +32,16 @@ namespace bx
 		Ty tmp = _a; _a = _b; _b = tmp;
 	}
 
+	template<typename Ty>
+	inline Ty min(const Ty& _a, const Ty& _b)
+	{
+		return _a < _b ? _a : _b;
+	}
+
+	template<typename Ty>
+	inline Ty max(const Ty& _a, const Ty& _b)
+	{
+		return _a > _b ? _a : _b;
+	}
+
 } // namespace bx

+ 30 - 0
include/bx/inline/cpu.inl

@@ -290,6 +290,36 @@ namespace bx
 		return oldVal;
 	}
 
+	template<typename Ty>
+	Ty atomicFetchAndAddsat(volatile Ty* _ptr, Ty _value, Ty _max)
+	{
+		Ty oldVal;
+		Ty newVal = *_ptr;
+		do
+		{
+			oldVal = newVal;
+			newVal = atomicCompareAndSwap<Ty>(_ptr, oldVal, newVal >= _max ? _max : min(_max, newVal+_value) );
+
+		} while (oldVal != newVal && oldVal != _max);
+
+		return oldVal;
+	}
+
+	template<typename Ty>
+	Ty atomicFetchAndSubsat(volatile Ty* _ptr, Ty _value, Ty _min)
+	{
+		Ty oldVal;
+		Ty newVal = *_ptr;
+		do
+		{
+			oldVal = newVal;
+			newVal = atomicCompareAndSwap<Ty>(_ptr, oldVal, newVal <= _min ? _min : max(_min, newVal-_value) );
+
+		} while (oldVal != newVal && oldVal != _min);
+
+		return oldVal;
+	}
+
 	inline void* atomicExchangePtr(void** _ptr, void* _new)
 	{
 #if BX_COMPILER_MSVC

+ 0 - 6
src/string.cpp

@@ -165,12 +165,6 @@ namespace bx
 		return _ch;
 	}
 
-	template<typename Ty>
-	inline Ty min(Ty _a, Ty _b)
-	{
-		return _a > _b ? _b : _a;
-	}
-
 	template<CharFn fn>
 	inline int32_t strCmp(const char* _lhs, int32_t _lhsMax, const char* _rhs, int32_t _rhsMax)
 	{

+ 46 - 0
tests/atomic_test.cpp

@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2017 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
+ */
+
+#include "test.h"
+#include <bx/cpu.h>
+
+TEST_CASE("atomic", "")
+{
+	uint32_t test = 1337;
+	uint32_t fetched;
+
+	fetched = bx::atomicFetchAndAdd(&test, 52u);
+	REQUIRE(fetched == 1337);
+	REQUIRE(test == 1389);
+
+	fetched = bx::atomicAddAndFetch(&test, 64u);
+	REQUIRE(fetched == 1453);
+	REQUIRE(test == 1453);
+
+	fetched = bx::atomicFetchAndSub(&test, 64u);
+	REQUIRE(fetched == 1453);
+	REQUIRE(test == 1389);
+
+	fetched = bx::atomicSubAndFetch(&test, 52u);
+	REQUIRE(fetched == 1337);
+	REQUIRE(test == 1337);
+
+	fetched = bx::atomicFetchAndAddsat(&test, 52u, 1453u);
+	REQUIRE(fetched == 1337);
+	REQUIRE(test == 1389);
+
+	fetched = bx::atomicFetchAndAddsat(&test, 1000u, 1453u);
+	REQUIRE(fetched == 1389);
+	REQUIRE(test == 1453);
+
+	fetched = bx::atomicFetchAndSubsat(&test, 64u, 1337u);
+	REQUIRE(fetched == 1453);
+	REQUIRE(test == 1389);
+
+	fetched = bx::atomicFetchAndSubsat(&test, 1000u, 1337u);
+	REQUIRE(fetched == 1389);
+	REQUIRE(test == 1337);
+
+}