Strict memory order check in compile time

konyuchenko.nikita
konyuchenko.nikita

Проблема: 

#include <atomic>
#include <cstdio>
void f()
{
  std::atomic<int> a;
  a.store(11, std::memory_order_release);
  a.store(10, std::memory_order_acquire);
  std::printf("%d\n", (int)a);
}

Данный код компилится VC++ и GCC/Clang и дает весьма странные результаты (при этом нет варнингов).

msvc вообще делает nop в релизной сборке.

Недопустимые значения memory_order должны приводить к ошибке компиляции. 

0
рейтинг
5 комментариев
yndx-antoshkka
Подобные вещи в стандарте не прописываются. Единственное что можно сделать - завести feature request в GCC и CLANG, чтобы выдавались предупреждения в случае неверного использования std::memory_order. При этом стоит продумать какие комбинации "сомнительны".

Если заведёте feature request - скиньте сюда пожалуйста ссылку.
yndx-antoshkka
konyuchenko.nikita
yndx-antoshkka, А если изменить суть memory_order?
Вот примерно так:
1 #include <iostream>
2
3 #define UNUSED(a) do {(void)(a);}while(false);
4
5 namespace my {
6 struct memory_order_aquire{};
7 struct memory_order_relaxed{};
8 struct memory_order_consume{};
9 struct memory_order_acquire{};
10 struct memory_order_release{};
11 struct memory_order_acq_rel{};
12 struct memory_order_seq_cst{};
13
14 template <typename Type, typename MemoryOrder>
15 void store(const Type& val, MemoryOrder&&);
16
17 template <typename Type>
18 void store(const Type&, memory_order_acquire&&){
>> 19 static_assert(false, "memory_order_acquire is not supported for the store operation");
20 }
21
22 template <typename Type>
23 void store(const Type&, memory_order_release&& ){
24 std::cout << "valid store" << std::endl;
25 }
26
27
28 template <typename Type>
29 struct atomic{
30 template <typename MemoryOrder> void store(const Type& value){
31 my::store(value, MemoryOrder());
32 }
33 };
34 }
35
36 int main() {
37 using namespace my;
38 atomic<int> ai{};
39 ai.store<memory_order_acquire>(10);
40 ai.store<memory_order_release>(11);
41 return 0;
42 }
konyuchenko.nikita
konyuchenko.nikita
konyuchenko.nikita
yndx-antoshkka
Менять существующие интерфейсы - нельзя. Это гарантированно не пройдёт голосование.

> ai.store<memory_order_release>(11);

Люди в комитете стараются избегать ситуаций, когда пользователю придётся писать template при вызове функций. В вашем случае:

template <class T>
void foo(T& ai) {
ai.template store<memory_order_acquire>(10);
}
yndx-antoshkka
Иван Куш
yndx-antoshkka, чем шаблоны плохи? Ведь, действительно, здесь лучше бы в шаблон

Хижинский пишет, что habrahabr.ru/post/197520
"Единственное объяснение C++11 подхода, которое приходит мне на ум, — пресловутая совместимость с C. Ведь помимо класса std::atomic стандарт C++11 вводит свободные C-шные атомарные функции atomic_load, atomic_store и пр."
Иван Куш
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).