Nach dem Blick auf ein Bündel von anderen Fragen und ihre Antworten , habe ich den Eindruck , dass es auf das, was die „flüchtig“ Schlüsselwort in C genau bedeutet keine weitgehende Übereinstimmung ist.
Selbst der Standard selbst scheint nicht klar genug zu sein, damit sich alle einig sind was er bedeutet .
Unter anderem:
- Es scheint je nach Hardware und Compiler unterschiedliche Garantien zu bieten.
- Dies wirkt sich auf Compiler-Optimierungen aus, nicht jedoch auf Hardware-Optimierungen. Bei einem erweiterten Prozessor, der seine eigenen Laufzeitoptimierungen durchführt, ist nicht einmal klar, ob der Compiler die von Ihnen gewünschte Optimierung verhindern kann. (Einige Compiler generieren Anweisungen, um einige Hardwareoptimierungen auf einigen Systemen zu verhindern. Dies scheint jedoch in keiner Weise standardisiert zu sein.)
Um das Problem zusammenzufassen, scheint (nach vielem Lesen) "volatile" etwas zu garantieren wie: Der Wert wird nicht nur aus / in ein Register, sondern zumindest in den L1-Cache des Kerns in derselben Reihenfolge gelesen / geschrieben Die Lese- / Schreibvorgänge werden im Code angezeigt. Dies scheint jedoch nutzlos zu sein, da das Lesen / Schreiben von / in ein Register innerhalb desselben Threads bereits ausreicht, während die Koordination mit dem L1-Cache keine weiteren Garantien hinsichtlich der Koordination mit anderen Threads garantiert. Ich kann mir nicht vorstellen, wann es jemals wichtig sein könnte, nur mit dem L1-Cache zu synchronisieren.
VERWENDE 1
Die einzige allgemein vereinbarte Verwendung von flüchtig scheint für alte oder eingebettete Systeme zu sein, bei denen bestimmte Speicherorte Hardware-E / A-Funktionen zugeordnet sind, wie z. B. ein Bit im Speicher, das (direkt in der Hardware) ein Licht steuert oder ein bisschen im Speicher, das Ihnen sagt, ob eine Tastaturtaste gedrückt ist oder nicht (weil sie von der Hardware direkt mit der Taste verbunden ist).
Es scheint, dass "use 1" nicht in portablem Code vorkommt, dessen Ziele Mehrkernsysteme umfassen.
USE 2
Nicht zu verschieden von "use 1" ist der Speicher, der jederzeit von einem Interrupt-Handler gelesen oder geschrieben werden kann (der möglicherweise ein Licht steuert oder Informationen von einem Schlüssel speichert). Aber schon deshalb haben wir das Problem, dass der Interrupt-Handler je nach System auf einem anderen Kern mit eigenem Speicher-Cache ausgeführt wird und "volatile" nicht die Cache-Kohärenz auf allen Systemen garantiert.
So „use 2“ scheint jenseits dessen, was „flüchtig“ liefern zu können.
VERWENDUNG 3
Die einzige andere unbestrittene Verwendung, die ich sehe, besteht darin, eine Fehloptimierung von Zugriffen über verschiedene Variablen zu verhindern, die auf denselben Speicher verweisen, von dem der Compiler nicht erkennt, dass er denselben Speicher hat. Aber das ist wahrscheinlich nur unbestritten, weil die Leute nicht darüber reden - ich habe nur eine Erwähnung davon gesehen. Und ich dachte, der C-Standard hat bereits erkannt, dass "verschiedene" Zeiger (wie verschiedene Argumente auf eine Funktion) auf dasselbe Element oder auf Elemente in der Nähe verweisen können, und bereits angegeben, dass der Compiler Code erzeugen muss, der auch in solchen Fällen funktioniert. Ich konnte dieses Thema jedoch im neuesten Standard (500 Seiten!) Nicht schnell finden.
Also "use 3" gibt es vielleicht gar nicht ?
Daher meine Frage:
Garantiert "flüchtig" überhaupt etwas im tragbaren C-Code für Mehrkernsysteme?
EDIT - Update
Nach dem Durchsuchen des neuesten Standards sieht es so aus, als ob die Antwort zumindest ein sehr begrenztes Ja ist:
1. Der Standard legt wiederholt eine spezielle Behandlung für den spezifischen Typ "volatile sig_atomic_t" fest. Der Standard besagt jedoch auch, dass die Verwendung der Signalfunktion in einem Multithread-Programm zu undefiniertem Verhalten führt. Daher scheint dieser Anwendungsfall auf die Kommunikation zwischen einem Single-Thread-Programm und seinem Signalhandler beschränkt zu sein.
2. Der Standard gibt auch eine klare Bedeutung für "flüchtig" in Bezug auf setjmp / longjmp an. (Beispielcode, wo es darauf ankommt, ist in anderen Fragen und Antworten angegeben .)
Die genauere Frage lautet also:
Garantiert "flüchtig" überhaupt etwas im tragbaren C-Code für Mehrkernsysteme, abgesehen von (1) dem Empfangen von Informationen von einem Single-Thread-Programm von seinem Signalhandler oder (2) dem Zulassen von setjmp Code, um Variablen zu sehen, die zwischen setjmp und longjmp geändert wurden?
Dies ist immer noch eine Ja / Nein-Frage.
Wenn "Ja", wäre es großartig, wenn Sie ein Beispiel für fehlerfreien tragbaren Code zeigen könnten, der fehlerhaft wird, wenn "flüchtig" weggelassen wird. Wenn "nein", kann ein Compiler "volatile" außerhalb dieser beiden sehr spezifischen Fälle für Multi-Core-Ziele ignorieren.
volatile
speziell um das, was ich für notwendig halte.
volatile
, um das Programm darüber zu informieren, dass es sich asynchron ändern kann.