Bonita Montero
unread,Jun 15, 2020, 11:44:25 AM6/15/20You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to
I've developed a little DCAS-specialization of std::atomic. It it uses
pair<uintptr_t, uintptr_t> as its atomic datatype. I've not implemented
the volatile methods as well as the compare-exchange-methods that accept
only one memory-consistency-parameter.
Here it is:
#pragma once
#include <cstdint>
#include <utility>
#include <atomic>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
#include <type_traits>
template<>
struct std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>
{
using pair_t = std::pair<std::uintptr_t, std::uintptr_t>;
using mo_t = std::memory_order;
atomic() = default;
atomic( pair_t desired );
atomic( const atomic & ) = delete;
atomic &operator =( pair_t desired );
atomic &operator =( pair_t const &desired ) = delete;
bool is_lock_free() const;
void store( pair_t desired, mo_t mo = std::memory_order_seq_cst );
pair_t load( mo_t mo = std::memory_order_seq_cst );
operator pair_t();
pair_t exchange( pair_t desired, mo_t mo = std::memory_order_seq_cst );
bool compare_exchange_weak( pair_t &expected, pair_t desired, mo_t
success, mo_t failure );
bool compare_exchange_strong( pair_t &expected, pair_t desired, mo_t
success, mo_t failure );
private:
alignas(2 * sizeof(uintptr_t))
pair_t m_pair;
static
bool cmpxchgPair( pair_t &dst, pair_t &expected, pair_t const &desired );
};
inline
std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>::atomic( pair_t
desired )
{
m_pair = desired;
}
inline
typename std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>
&std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>::operator =(
pair_t desired )
{
store( desired );
return *this;
}
inline
bool std::atomic<std::pair<std::uintptr_t,
std::uintptr_t>>::is_lock_free() const
{
return true;
}
inline
void std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>::store(
pair_t desired, mo_t mo )
{
pair_t cmp = m_pair;
while( !cmpxchgPair( m_pair, cmp, desired ) );
atomic_thread_fence( mo );
}
inline
std::pair<std::uintptr_t, std::uintptr_t>
std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>::load( mo_t mo )
{
pair_t cmp = m_pair;
cmpxchgPair( m_pair, cmp, cmp );
atomic_thread_fence( mo );
return cmp;
}
inline
std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>::operator pair_t()
{
return load();
}
inline
std::pair<std::uintptr_t, std::uintptr_t>
std::atomic<std::pair<std::uintptr_t, std::uintptr_t>>::exchange( pair_t
desired, mo_t mo )
{
pair_t cmp = m_pair;
while( !cmpxchgPair( m_pair, cmp, desired ) );
atomic_thread_fence( mo );
return cmp;
}
bool std::atomic<std::pair<std::uintptr_t,
std::uintptr_t>>::compare_exchange_weak( pair_t &expected, pair_t
desired, mo_t success, mo_t failure )
{
bool succ = cmpxchgPair( m_pair, expected, desired );
atomic_thread_fence( succ ? success : failure );
return succ;
}
bool std::atomic<std::pair<std::uintptr_t,
std::uintptr_t>>::compare_exchange_strong( pair_t &expected, pair_t
desired, mo_t success, mo_t failure )
{
bool succ = cmpxchgPair( m_pair, expected, desired );
atomic_thread_fence( succ ? success : failure );
return succ;
}
inline
bool std::atomic<std::pair<std::uintptr_t,
std::uintptr_t>>::cmpxchgPair( pair_t &dst, pair_t &expected, pair_t
const &desired )
{
#if defined(_MSC_VER)
return _InterlockedCompareExchange128( &(__int64 &)dst, desired.second,
desired.first, &(__int64 &)expected );
#elif defined(__GNUC__)
return __sync_bool_compare_and_swap( &(__int128 &)dst, &(__int128
&)expected, &(__int128 &)desired );
#endif
}
Unfortunately __sync_bool_compare_and_swap maps to a sympbol called
__sync_bool_compare_and_swap_16 and my linker can't find it:
"undefined reference to `__sync_bool_compare_and_swap_16'"
Any ideas ?