std:: counting_semaphore, std:: binary_semaphore
|
Definiert in Header
<semaphore>
|
||
|
template
<
std::
ptrdiff_t
LeastMaxValue
=
/* implementation-defined */
>
class counting_semaphore ; |
(1) | (seit C++20) |
|
using
binary_semaphore
=
std
::
counting_semaphore
<
1
>
;
|
(2) | (seit C++20) |
counting_semaphore
ist ein leichtgewichtiges Synchronisationsprimitive, das den Zugriff auf eine gemeinsam genutzte Ressource steuern kann. Im Gegensatz zu einem
std::mutex
erlaubt ein
counting_semaphore
mehr als einen gleichzeitigen Zugriff auf dieselbe Ressource, für mindestens
LeastMaxValue
gleichzeitige Zugreifer. Das Programm ist fehlerhaft, wenn
LeastMaxValue
negativ ist.
binary_semaphore
ist ein Alias für die Spezialisierung von
std::counting_semaphore
mit
LeastMaxValue
gleich
1
. Implementierungen können
binary_semaphore
effizienter implementieren als die Standardimplementierung von
std::counting_semaphore
.
Ein
counting_semaphore
enthält einen internen Zähler, der durch den Konstruktor initialisiert wird. Dieser Zähler wird durch Aufrufe von
acquire()
und verwandten Methoden dekrementiert und durch Aufrufe von
release()
inkrementiert. Wenn der Zähler null ist, blockiert
acquire()
, bis der Zähler inkrementiert wird, aber
try_acquire()
blockiert nicht;
try_acquire_for()
und
try_acquire_until()
blockieren, bis der Zähler inkrementiert wird oder ein Timeout erreicht ist.
Ähnlich wie
std::condition_variable::wait()
,
kann
counting_semaphore
's
try_acquire()
sporadisch fehlschlagen.
Spezialisierungen von
std::counting_semaphore
sind nicht
DefaultConstructible
,
CopyConstructible
,
MoveConstructible
,
CopyAssignable
oder
MoveAssignable
.
Inhaltsverzeichnis |
Datenmitglieder
| Mitgliedername | Definition |
counter
(privat)
|
Der interne Zähler vom Typ
std::ptrdiff_t
.
( Nur zur Darstellung verwendetes Mitgliedsobjekt* ) |
Memberfunktionen
konstruiert einen
counting_semaphore
(öffentliche Elementfunktion) |
|
zerstört den
counting_semaphore
(öffentliche Elementfunktion) |
|
|
operator=
[deleted]
|
counting_semaphore
ist nicht zuweisbar
(öffentliche Elementfunktion) |
Operationen |
|
|
erhöht den internen Zähler und entblockiert Akquisiteure
(öffentliche Elementfunktion) |
|
|
dekrementiert den internen Zähler oder blockiert, bis dies möglich ist
(öffentliche Elementfunktion) |
|
|
versucht, den internen Zähler ohne Blockierung zu dekrementieren
(öffentliche Elementfunktion) |
|
|
versucht, den internen Zähler zu dekrementieren, blockiert für maximal eine Zeitdauer
(öffentliche Elementfunktion) |
|
|
versucht, den internen Zähler zu dekrementieren, blockiert bis zu einem Zeitpunkt
(öffentliche Elementfunktion) |
|
Konstanten |
|
|
[static]
|
gibt den maximal möglichen Wert des internen Zählers zurück
(öffentliche statische Elementfunktion) |
Hinweise
Wie der Name andeutet, ist der
LeastMaxValue
der
minimale
Maximalwert, nicht der
tatsächliche
Maximalwert. Daher kann
max()
eine größere Zahl liefern als
LeastMaxValue
.
Im Gegensatz zu
std::mutex
ist ein
counting_semaphore
nicht an Ausführungsthreads gebunden - das Erlangen eines Semaphors kann beispielsweise in einem anderen Thread erfolgen als das Freigeben des Semaphors. Alle Operationen auf
counting_semaphore
können gleichzeitig und ohne Bezug zu bestimmten Ausführungsthreads durchgeführt werden, mit Ausnahme des Destruktors, der nicht gleichzeitig ausgeführt werden kann, aber in einem anderen Thread erfolgen darf.
Semaphore werden auch häufig für die Semantik von Signalisierung/Benachrichtigung verwendet, anstatt für gegenseitigen Ausschluss, indem das Semaphor mit 0 initialisiert wird und somit der/die Empfänger blockiert wird/werden, die versuchen acquire() , bis der Benachrichtiger durch Aufruf von release ( n ) "signalisert". In dieser Hinsicht können Semaphore als Alternativen zu std::condition_variable s betrachtet werden, oft mit besserer Leistung.
| Feature-Test Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_semaphore
|
201907L
|
(C++20) |
std::counting_semaphore
,
std::binary_semaphore
|
Beispiel
#include <chrono> #include <iostream> #include <semaphore> #include <thread> // globale binäre Semaphor-Instanzen // Objektzähler sind auf null gesetzt // Objekte befinden sich im nicht-signalisierten Zustand std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // Warte auf ein Signal vom Hauptprozess // durch Versuch, den Semaphor zu dekrementieren smphSignalMainToThread.acquire(); // Dieser Aufruf blockiert, bis der Semaphor-Zähler // vom Hauptprozess erhöht wird std::cout << "[thread] Got the signal\n"; // Antwortnachricht // Warte 3 Sekunden, um Arbeit zu simulieren // die vom Thread ausgeführt wird using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // Nachricht // Signalisiere zurück an den Hauptprozess smphSignalThreadToMain.release(); } int main() { // Erstelle einen Worker-Thread std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // Nachricht // Signalisiere dem Worker-Thread zu starten // durch Erhöhung des Semaphor-Zählers smphSignalMainToThread.release(); // Warte bis der Worker-Thread die Arbeit abgeschlossen hat // durch Versuch, den Semaphor-Zähler zu dekrementieren smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // Antwortnachricht thrWorker.join(); }
Ausgabe:
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal