Namespaces
Variants

std:: kill_dependency

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
kill_dependency
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
Определено в заголовочном файле <atomic>
template < class T >
T kill_dependency ( T y ) noexcept ;
(начиная с C++11)
(constexpr начиная с C++26)
(устарело в C++26)

Сообщает компилятору, что дерево зависимостей, начатое операцией атомарной загрузки std::memory_order_consume , не распространяется за пределы возвращаемого значения std::kill_dependency ; то есть аргумент не переносит зависимость в возвращаемое значение.

Это может использоваться для избежания ненужных барьеров std::memory_order_acquire , когда цепочка зависимостей покидает область видимости функции (и функция не имеет атрибута [[ carries_dependency ]] ).

(до C++26)

Просто возвращает y . Этот шаблон функции устарел.

(начиная с C++26)

Содержание

Параметры

y - выражение, возвращаемое значение которого должно быть удалено из дерева зависимостей

Возвращаемое значение

Возвращает y , больше не являющийся частью дерева зависимостей (до C++26) .

Примеры

file1.cpp:
struct Foo
{
    int* a;
    int* b;
};
std::atomic<Foo*> foo_head[10];
int foo_array[10][10];
// операция consume начинает цепочку зависимостей, которая выходит за пределы этой функции
[[carries_dependency]] Foo* f(int i)
{
    return foo_head[i].load(memory_order_consume);
}
// цепочка зависимостей входит в эту функцию через правый параметр и
// уничтожается до завершения функции (так что дополнительная операция acquire не выполняется)
int g(int* x, int* y [[carries_dependency]])
{
    return std::kill_dependency(foo_array[*x][*y]);
}
file2.cpp:
[[carries_dependency]] struct Foo* f(int i);
int g(int* x, int* y [[carries_dependency]]);
int c = 3;
void h(int i)
{
    Foo* p;
    p = f(i); // цепочка зависимостей, начатая внутри f, продолжается в p без избыточного захвата
    do_something_with(g(&c, p->a)); // p->b не загружается из кэша
    do_something_with(g(p->a, &c)); // левый аргумент не имеет атрибута carries_dependency
                                    // может быть установлен барьер захвата памяти
                                    // p->b становится видимым до входа в g()
}

Смотрите также

определяет ограничения упорядочения памяти для данной атомарной операции
(enum)
C documentation для kill_dependency