Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::atomic<uint_least8_t> behavior

Tags:

c++

c++17

On a system with:

typedef unsigned char      uint8_t;
typedef unsigned short     uint16_t;

std::atomic<uint8_t>::is_always_lock_free // => false
std::atomic<uint16_t>::is_always_lock_free // => true

From my understanding, the type

std::atomic<uint_least8_t>

will be 8 bits and not be lock free.

If so, what should I write if I want an atomic type that is at least 8 bits and always lock free? (assuming such type exists) Is there a better alternative than:

std::atomic<
    typename std::conditional<
        std::atomic<uint8_t>::is_always_lock_free, 
        uint8_t, 
        uint16_t
    >::type
>

(for simplicity, I did not include code if std::atomic&lt;uint16_t> isn't lock free)

like image 797
Benoit Avatar asked May 01 '18 16:05

Benoit


1 Answers

Well the template stuff is a bit messy, but the usage of it is quite intuitive:

#include <atomic>
#include <cstdint>
#include <iostream>

template <typename T, typename... others>
class first_lockfree
{
    // forward declare internal template
    template <bool, typename...> struct cond;

    // use this if is_always_lock_free == true
    template <typename condT, typename... condTs>
    struct cond<true, condT, condTs...>
    {
        // use first template argument as it is_always_lock_free
        using type = condT;
    };

    // use this if is_always_lock_free == false
    template <typename condT, typename... condTs>
    struct cond<false, condT, condTs...>
    {
        // use main template with first template parameter removed
        using type = typename first_lockfree<condTs...>::type;
    };

public:
    using type =typename cond<std::atomic<T>::is_always_lock_free, T, others...>::type;
};


int main(int, char**)
{
    using uint8_lockfree_t = first_lockfree<std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t>::type;

    std::cout <<  sizeof(uint8_lockfree_t) << std::endl;

    std::cout <<  std::atomic<std::uint8_t>::is_always_lock_free << std::endl;
    std::cout <<  std::atomic<std::uint16_t>::is_always_lock_free << std::endl;
    std::cout <<  std::atomic<std::uint32_t>::is_always_lock_free << std::endl;
    std::cout <<  std::atomic<std::uint64_t>::is_always_lock_free << std::endl;

    return 0;
}
like image 63
kiloalphaindia Avatar answered Sep 28 '22 02:09

kiloalphaindia