Skip to content

Commit

Permalink
Static functions for XS::Atomic< T > + unit tests...
Browse files Browse the repository at this point in the history
  • Loading branch information
macmade committed Mar 22, 2017
1 parent 6ceafba commit 4a20e90
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 4 deletions.
10 changes: 7 additions & 3 deletions CPPAtomic.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
05F58B281E81EB9D000D50A0 /* AtomicIncrement64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05F58B1E1E81EB9D000D50A0 /* AtomicIncrement64.cpp */; };
05F58B291E81EB9D000D50A0 /* MemoryBarrier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05F58B1F1E81EB9D000D50A0 /* MemoryBarrier.cpp */; };
05F58B2B1E81EDC3000D50A0 /* XS-Atomic-Functions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05F58B2A1E81EDC3000D50A0 /* XS-Atomic-Functions.cpp */; };
05FCF6E71E83073800D98BFC /* XS-Atomic-Static.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05FCF6E61E83073800D98BFC /* XS-Atomic-Static.cpp */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -123,6 +124,7 @@
05F58B1E1E81EB9D000D50A0 /* AtomicIncrement64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicIncrement64.cpp; sourceTree = "<group>"; };
05F58B1F1E81EB9D000D50A0 /* MemoryBarrier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryBarrier.cpp; sourceTree = "<group>"; };
05F58B2A1E81EDC3000D50A0 /* XS-Atomic-Functions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "XS-Atomic-Functions.cpp"; sourceTree = "<group>"; };
05FCF6E61E83073800D98BFC /* XS-Atomic-Static.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "XS-Atomic-Static.cpp"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -148,17 +150,18 @@
053BEDA51B8EFCB6007D82A4 /* Unit-Tests */ = {
isa = PBXGroup;
children = (
053BEDC71B8EFE1E007D82A4 /* Info.plist */,
053BEDF91B90B37E007D82A4 /* Prefix.pch */,
05F58B2A1E81EDC3000D50A0 /* XS-Atomic-Functions.cpp */,
051F9C771C19C3EE005D471A /* XS-Atomic-Non-Trivial.cpp */,
05FCF6E61E83073800D98BFC /* XS-Atomic-Static.cpp */,
051F9C841C19ECB4005D471A /* XS-Atomic-Trivial-Bitwise.cpp */,
051F9C781C19C3EE005D471A /* XS-Atomic-Trivial-Bool.cpp */,
051F9C791C19C3EE005D471A /* XS-Atomic-Trivial-Double.cpp */,
051F9C7A1C19C3EE005D471A /* XS-Atomic-Trivial-Integral.cpp */,
051F9C7B1C19C3EE005D471A /* XS-Atomic-Trivial-Pointer.cpp */,
051F9C7C1C19C3EE005D471A /* XS-Atomic-Trivial-Struct.cpp */,
05F58B2A1E81EDC3000D50A0 /* XS-Atomic-Functions.cpp */,
05CDB0381E81F85000DD9BB2 /* XS-Semaphore.cpp */,
053BEDC71B8EFE1E007D82A4 /* Info.plist */,
053BEDF91B90B37E007D82A4 /* Prefix.pch */,
);
path = "Unit-Tests";
sourceTree = "<group>";
Expand Down Expand Up @@ -456,6 +459,7 @@
051F9C7D1C19C3EE005D471A /* XS-Atomic-Non-Trivial.cpp in Sources */,
051F9C7E1C19C3EE005D471A /* XS-Atomic-Trivial-Bool.cpp in Sources */,
05CDB0391E81F85000DD9BB2 /* XS-Semaphore.cpp in Sources */,
05FCF6E71E83073800D98BFC /* XS-Atomic-Static.cpp in Sources */,
051F9C7F1C19C3EE005D471A /* XS-Atomic-Trivial-Double.cpp in Sources */,
05F58B2B1E81EDC3000D50A0 /* XS-Atomic-Functions.cpp in Sources */,
051F9C811C19C3EE005D471A /* XS-Atomic-Trivial-Pointer.cpp in Sources */,
Expand Down
61 changes: 60 additions & 1 deletion CPPAtomic/include/XS/Atomic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#endif

#include <XS/TypeTraits.hpp>
#include <XS/Atomic-Functions.hpp>

namespace XS
{
Expand Down Expand Up @@ -96,7 +97,65 @@ namespace XS
template< class _U_ > struct HasGreaterThanOrEqualToOperator: public std::integral_constant< bool, ( TrivialValueIsArithmetic< _U_ >::value || XS::TypeTraits::HasGreaterThanOrEqualToOperator< _U_, bool, const _U_ & >::value ) > {};

public:


/*******************************************************************
* Static functions
******************************************************************/

template< typename _U_ = _T_ >
static _U_ Increment( volatile typename std::enable_if< sizeof( _U_ ) == 4, _U_ >::type * value )
{
return static_cast< _U_ >( AtomicIncrement32( reinterpret_cast< volatile int32_t * >( value ) ) );
}

template< typename _U_ = _T_ >
static _U_ Increment( volatile typename std::enable_if< sizeof( _U_ ) == 8, _U_ >::type * value )
{
return static_cast< _U_ >( AtomicIncrement64( reinterpret_cast< volatile int64_t * >( value ) ) );
}

template< typename _U_ = _T_ >
static _U_ Decrement( volatile typename std::enable_if< sizeof( _U_ ) == 4, _U_ >::type * value )
{
return static_cast< _U_ >( AtomicDecrement32( reinterpret_cast< volatile int32_t * >( value ) ) );
}

template< typename _U_ = _T_ >
static _U_ Decrement( volatile typename std::enable_if< sizeof( _U_ ) == 8, _U_ >::type * value )
{
return static_cast< _U_ >( AtomicDecrement64( reinterpret_cast< volatile int64_t * >( value ) ) );
}

template< typename _U_ = _T_ >
static _U_ Add( typename std::enable_if< sizeof( _U_ ) == 4, _U_ >::type amount, volatile _U_ * value )
{
return static_cast< _U_ >( AtomicAdd32( static_cast< int32_t >( amount ), reinterpret_cast< volatile int32_t * >( value ) ) );
}

template< typename _U_ = _T_ >
static _U_ Add( typename std::enable_if< sizeof( _U_ ) == 8, _U_ >::type amount, volatile _U_ * value )
{
return static_cast< _U_ >( AtomicAdd64( static_cast< int64_t >( amount ), reinterpret_cast< volatile int64_t * >( value ) ) );
}

template< typename _U_ = _T_ >
static bool CompareAndSwap( typename std::enable_if< ( sizeof( _U_ ) == 4 ) && !std::is_pointer< _U_ >::value, _U_ >::type oldValue, typename std::enable_if< ( sizeof( _U_ ) == 4 && !std::is_pointer< _U_ >::value ), _U_ >::type newValue, volatile _U_ * value )
{
return AtomicCompareAndSwap32( static_cast< int32_t >( oldValue ), static_cast< int32_t >( newValue ), reinterpret_cast< volatile int32_t * >( value ) );
}

template< typename _U_ = _T_ >
static bool CompareAndSwap( typename std::enable_if< ( sizeof( _U_ ) == 8 ) && !std::is_pointer< _U_ >::value, _U_ >::type oldValue, typename std::enable_if< ( sizeof( _U_ ) == 8 && !std::is_pointer< _U_ >::value ), _U_ >::type newValue, volatile _U_ * value )
{
return AtomicCompareAndSwap64( static_cast< int64_t >( oldValue ), static_cast< int64_t >( newValue ), reinterpret_cast< volatile int64_t * >( value ) );
}

template< typename _U_ = _T_ >
static bool CompareAndSwap( typename std::enable_if< std::is_pointer< _U_ >::value, _U_ >::type oldValue, typename std::enable_if< std::is_pointer< _U_ >::value, _U_ >::type newValue, _U_ volatile * value )
{
return AtomicCompareAndSwapPointer( reinterpret_cast< void * >( oldValue ), reinterpret_cast< void * >( newValue ), reinterpret_cast< void * volatile * >( value ) );
}

/*******************************************************************
* Common definitions
******************************************************************/
Expand Down
133 changes: 133 additions & 0 deletions Unit-Tests/XS-Atomic-Static.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015 Jean-David Gadina - www.xs-labs.com / www.digidna.net
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/

/*!
* @copyright (c) 2015 - Jean-David Gadina - www.xs-labs.com / www.digidna.net
* @brief ...
*/

/* Disabled warnings for GoogleMock */
#ifdef __clang__
#pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wpadded"
#pragma clang diagnostic push
#if __clang_major__ >= 7
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#endif
#pragma clang diagnostic ignored "-Wmissing-noreturn"
#pragma clang diagnostic ignored "-Wpadded"
#pragma clang diagnostic ignored "-Wused-but-marked-unused"
#pragma clang diagnostic ignored "-Wdeprecated"
#endif

#include <GoogleMock/GoogleMock.h>

#ifdef __clang__
#pragma clang diagnostic pop
#endif

#include <XS/Atomic.hpp>

using namespace testing;

TEST( XS_Atomic_Static, Increment )
{
int32_t i32 = 0;
uint32_t u32 = 0;
int64_t i64 = 0;
uint64_t u64 = 0;

ASSERT_EQ( XS::Atomic< int32_t >::Increment( &i32 ), static_cast< int32_t >( 1 ) );
ASSERT_EQ( XS::Atomic< uint32_t >::Increment( &u32 ), static_cast< uint32_t >( 1 ) );
ASSERT_EQ( XS::Atomic< int64_t >::Increment( &i64 ), static_cast< int64_t >( 1 ) );
ASSERT_EQ( XS::Atomic< uint64_t >::Increment( &u64 ), static_cast< uint64_t >( 1 ) );

ASSERT_EQ( i32, static_cast< int32_t >( 1 ) );
ASSERT_EQ( u32, static_cast< uint32_t >( 1 ) );
ASSERT_EQ( i64, static_cast< int64_t >( 1 ) );
ASSERT_EQ( u64, static_cast< uint64_t >( 1 ) );
}

TEST( XS_Atomic_Static, Decrement )
{
int32_t i32 = 0;
uint32_t u32 = 0;
int64_t i64 = 0;
uint64_t u64 = 0;

ASSERT_EQ( XS::Atomic< int32_t >::Decrement( &i32 ), static_cast< int32_t >( -1 ) );
ASSERT_EQ( XS::Atomic< uint32_t >::Decrement( &u32 ), static_cast< uint32_t >( -1 ) );
ASSERT_EQ( XS::Atomic< int64_t >::Decrement( &i64 ), static_cast< int64_t >( -1 ) );
ASSERT_EQ( XS::Atomic< uint64_t >::Decrement( &u64 ), static_cast< uint64_t >( -1 ) );

ASSERT_EQ( i32, static_cast< int32_t >( -1 ) );
ASSERT_EQ( u32, static_cast< uint32_t >( -1 ) );
ASSERT_EQ( i64, static_cast< int64_t >( -1 ) );
ASSERT_EQ( u64, static_cast< uint64_t >( -1 ) );
}

TEST( XS_Atomic_Static, Add )
{
int32_t i32 = 0;
uint32_t u32 = 0;
int64_t i64 = 0;
uint64_t u64 = 0;

ASSERT_EQ( XS::Atomic< int32_t >::Add( 2, &i32 ), static_cast< int32_t >( 2 ) );
ASSERT_EQ( XS::Atomic< uint32_t >::Add( 2, &u32 ), static_cast< uint32_t >( 2 ) );
ASSERT_EQ( XS::Atomic< int64_t >::Add( 2, &i64 ), static_cast< int64_t >( 2 ) );
ASSERT_EQ( XS::Atomic< uint64_t >::Add( 2, &u64 ), static_cast< uint64_t >( 2 ) );

ASSERT_EQ( i32, static_cast< int32_t >( 2 ) );
ASSERT_EQ( u32, static_cast< uint32_t >( 2 ) );
ASSERT_EQ( i64, static_cast< int64_t >( 2 ) );
ASSERT_EQ( u64, static_cast< uint64_t >( 2 ) );
}

TEST( XS_Atomic_Static, CompareAndSwap )
{
int32_t i32 = 0;
uint32_t u32 = 0;
int64_t i64 = 0;
uint64_t u64 = 0;
void * p = nullptr;

ASSERT_FALSE( XS::Atomic< int32_t >::CompareAndSwap( 1, 2, &i32 ) );
ASSERT_FALSE( XS::Atomic< uint32_t >::CompareAndSwap( 1, 2, &u32 ) );
ASSERT_FALSE( XS::Atomic< int64_t >::CompareAndSwap( 1, 2, &i64 ) );
ASSERT_FALSE( XS::Atomic< uint64_t >::CompareAndSwap( 1, 2, &u64 ) );
ASSERT_FALSE( XS::Atomic< void * >::CompareAndSwap( reinterpret_cast< void * >( 1 ), reinterpret_cast< void * >( 2 ), reinterpret_cast< void * volatile * >( &p ) ) );

ASSERT_TRUE( XS::Atomic< int32_t >::CompareAndSwap( 0, 2, &i32 ) );
ASSERT_TRUE( XS::Atomic< uint32_t >::CompareAndSwap( 0, 2, &u32 ) );
ASSERT_TRUE( XS::Atomic< int64_t >::CompareAndSwap( 0, 2, &i64 ) );
ASSERT_TRUE( XS::Atomic< uint64_t >::CompareAndSwap( 0, 2, &u64 ) );
ASSERT_TRUE( XS::Atomic< void * >::CompareAndSwap( reinterpret_cast< void * >( 0 ), reinterpret_cast< void * >( 2 ), reinterpret_cast< void * volatile * >( &p ) ) );

ASSERT_EQ( i32, static_cast< int32_t >( 2 ) );
ASSERT_EQ( u32, static_cast< uint32_t >( 2 ) );
ASSERT_EQ( i64, static_cast< int64_t >( 2 ) );
ASSERT_EQ( u64, static_cast< uint64_t >( 2 ) );
ASSERT_EQ( p, reinterpret_cast< void * >( 2 ) );
}

0 comments on commit 4a20e90

Please sign in to comment.