Я строю кроссплатформенный слой атомной абстракции для поддержки 64-битных и 128-битных атомных операций для следующих типов: < /p>
- , uint64_t
Код: Выделить всё
int64_t - (на платформах Clang)
Код: Выделить всё
__int128 - Пользовательский myint128 struct (используется на MSVC для эмуляции 128-битных цетей в качестве двух int64_t s)
[*] Windows (x64, ARM64) Использование MSVC < /li>
Linux (x64) с использованием Clang < /li>
macOS (ARM64) с использованием Clang < /li>
< /ul>
. Кроссплатформенная поддержка 128-битных атомных операций в Clang < /p>
Я использую следующую настройку специфической для платформы: < /p>
msvc (x64 /arm64) < /p>
std :: atomic_ref
• Примечания: не без блокировки, но работает через запасную блокировку
clang (linux x64)
• Тип: __int128 , __int64 std :: atomic_ref
• Примечания: отлично работает
clang (macos arm64)
• Тип: __int128 , __int64
std :: atomic
• Примечания: std :: atomic_ref недоступен на этой платформе
Я выбираю std :: atomic_ref , где возможно, что:
copeially-copeibol Структы. -Для MSVC я понимаю, что 128-разрядные атомные операции не содержат блокировки, а отступление на внутренние замки. Я проверил std :: atomic_ref с двумя темами более 10 миллионов итераций, а цикла CAS завершен без проблем. - Ошибка, которую я получаю: Нет шаблона с именем «atomic_ref» в пространстве имен 'std' < /code>.
Мне не хватает включения? Или это известное ограничение в реализации Apple Libc ++? -myint128 -это тривиально-завариваемая 16-байтовая структура (два int64_t участники). Будут ли все атомные операции работать правильно (даже если не без блокировки)? - Я хочу избежать того, чтобы потребовать, чтобы все общие переменные в кодовой базе были объявлены как std :: atomic .Instead, я хочу написать общие атомные операции, которые принимают t & и используют атомику внутри.
Код: Выделить всё
template
T CompareAndSwap(T& dest, T desired, T expected)
{
static_assert(std::is_trivially_copyable_v);
static_assert(sizeof(T) == 8 || sizeof(T) == 16);
#if defined(__APPLE__) && defined(__aarch64__)
std::atomic* atomicPtr = reinterpret_cast(&dest);
atomicPtr->compare_exchange_strong(expected, desired);
#else
std::atomic_ref atomicRef(dest);
atomicRef.compare_exchange_strong(expected, desired);
#endif
return expected;
}
< /code>
испытательное наблюдение < /strong> < /p>
T = __int128Код: Выделить всё
T = MyInt128< /code> на msvc (windows) < /li>
В нескольких потоках, проходящих 10 миллионов итераций < /li>
< /ul>
Цель < /strong>
Я хочу проверить: < /p>
. - например, неверные предположения о компоновке структуры или скрытых ловушках с Atomic_ref [*] if std :: atomic_ref намеренно отсутствует в Apple Clang's Libc ++.
Подробнее здесь: https://stackoverflow.com/questions/797 ... on-clang-m
Мобильная версия