[[carries_dependency]]
wird verwendet, um Abhängigkeiten über Funktionsaufrufe hinweg zu übertragen. Auf diese Weise kann der Compiler möglicherweise besseren Code generieren, wenn er std::memory_order_consume
zum Übertragen von Werten zwischen Threads auf Plattformen mit schwach geordneten Architekturen wie der POWER-Architektur von IBM verwendet wird.
Insbesondere wenn ein mit gelesener Wert memory_order_consume
an eine Funktion übergeben wird [[carries_dependency]]
, muss der Compiler möglicherweise einen Speicherzaunbefehl ausgeben, um sicherzustellen, dass die entsprechende Semantik der Speicherreihenfolge eingehalten wird. Wenn der Parameter mit kommentiert [[carries_dependency]]
ist, kann der Compiler davon ausgehen, dass der Funktionskörper die Abhängigkeit korrekt trägt, und dieser Zaun ist möglicherweise nicht mehr erforderlich.
Wenn eine Funktion einen mit memory_order_consume
einem solchen Wert geladenen oder von einem solchen Wert abgeleiteten Wert zurückgibt , muss [[carries_dependency]]
der Compiler möglicherweise auch einen Zaunbefehl einfügen, um sicherzustellen, dass die entsprechende Semantik der Speicherreihenfolge eingehalten wird. Mit der [[carries_dependency]]
Annotation ist dieser Zaun möglicherweise nicht mehr erforderlich, da der Aufrufer nun für die Pflege des Abhängigkeitsbaums verantwortlich ist.
z.B
void print(int * val)
{
std::cout<<*val<<std::endl;
}
void print2(int * [[carries_dependency]] val)
{
std::cout<<*val<<std::endl;
}
std::atomic<int*> p;
int* local=p.load(std::memory_order_consume);
if(local)
std::cout<<*local<<std::endl;
if(local)
print(local);
if(local)
print2(local);
In Zeile (1) ist die Abhängigkeit explizit, sodass der Compiler weiß, dass sie local
dereferenziert ist, und dass er sicherstellen muss, dass die Abhängigkeitskette erhalten bleibt, um einen Zaun auf POWER zu vermeiden.
In Zeile (2), von der Definition print
ist undurchsichtig (vorausgesetzt , es nicht inlined ist), so dass der Compiler einen Zaun um ausstellen muss , dass das Lesen , um sicherzustellen , *p
in print
gibt den richtigen Wert.
In Zeile (3) kann der Compiler davon ausgehen, dass print2
die Abhängigkeit vom Parameter zum dereferenzierten Wert im Befehlsstrom erhalten bleibt , obwohl sie ebenfalls undurchsichtig ist, und dass für POWER kein Zaun erforderlich ist. Offensichtlich muss die Definition von print2
diese Abhängigkeit tatsächlich beibehalten, sodass sich das Attribut auch auf den generierten Code für auswirkt print2
.