Std :: atomic <uint_least8_t> поведение

В системе с:

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

Насколько я понимаю, тип

std::atomic<uint_least8_t>

будет 8 бит и не будет блокироваться.

Если да, то что мне писать, если я хочу, чтобы атомарный тип состоял не менее чем из 8 бит и всегда был свободен от блокировки? (при условии, что такой тип существует) Есть ли лучшая альтернатива, чем:

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

(для простоты я не включил код if std::atomic&lt;uint16_t> не блокируется)

На самом деле, я ожидал бы, что uint_fast8_t будет typedef для некоторого типа lock-free. Это тоже не гарантируется, но вы можете проверить, достаточно ли это для вас.

user743382 01.05.2018 18:26

Также нет абсолютного требования, чтобы atomic<x> действительно хранил x. Таким образом, в довольно странном случае, когда 16-битные данные свободны от блокировки, я ожидал бы, что 8-битные типы будут использовать 16-битное хранилище.

Bo Persson 01.05.2018 18:34

IMO решение, которое вы предоставили, достаточно простое. Очевидно, вы хотите где-нибудь указать псевдоним типа, но на этом все готово. Работа с поведением, зависящим от платформы, всегда была сложной задачей

Passer By 01.05.2018 18:46

@hvd Чем больше я об этом думаю, тем больше мне нравится ваше предложение. Я думаю, что это хороший компромисс между удобочитаемостью / обслуживанием и оптимизацией. Пуленепробиваемое метапрограммирование для поиска лучшего типа без блокировок оказывается довольно тяжелым и трудным для чтения.

Benoit 02.05.2018 14:15
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
4
255
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Что ж, шаблон немного запутан, но его использование довольно интуитивно понятно:

#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;
}

Другие вопросы по теме