Added atomicFetchAndAddsat/Subsat.

This commit is contained in:
Branimir Karadžić
2017-10-23 08:27:03 -07:00
parent 0a2c440a77
commit b6a01bf42c
6 changed files with 104 additions and 6 deletions

View File

@@ -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];

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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
tests/atomic_test.cpp Normal file
View File

@@ -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);
}