std:: counting_semaphore, std:: binary_semaphore
|
Défini dans l'en-tête
<semaphore>
|
||
|
template
<
std::
ptrdiff_t
LeastMaxValue
=
/* implementation-defined */
>
class counting_semaphore ; |
(1) | (depuis C++20) |
|
using
binary_semaphore
=
std
::
counting_semaphore
<
1
>
;
|
(2) | (depuis C++20) |
counting_semaphore
est une primitive de synchronisation légère qui peut contrôler l'accès à une ressource partagée. Contrairement à un
std::mutex
, un
counting_semaphore
permet plus d'un accès concurrent à la même ressource, pour au moins
LeastMaxValue
accédants concurrents. Le programme est mal formé si
LeastMaxValue
est négatif.
binary_semaphore
est un alias pour la spécialisation de
std::counting_semaphore
où
LeastMaxValue
vaut
1
. Les implémentations peuvent implémenter
binary_semaphore
de manière plus efficace que l'implémentation par défaut de
std::counting_semaphore
.
Un
counting_semaphore
contient un compteur interne initialisé par le constructeur. Ce compteur est décrémenté par les appels à
acquire()
et les méthodes associées, et est incrémenté par les appels à
release()
. Lorsque le compteur est à zéro,
acquire()
bloque jusqu'à ce que le compteur soit incrémenté, mais
try_acquire()
ne bloque pas ;
try_acquire_for()
et
try_acquire_until()
bloquent jusqu'à ce que le compteur soit incrémenté ou qu'un délai d'attente soit atteint.
Similaire à
std::condition_variable::wait()
,
counting_semaphore
's
try_acquire()
peut échouer de manière sporadique.
Les spécialisations de
std::counting_semaphore
ne sont pas
DefaultConstructible
,
CopyConstructible
,
MoveConstructible
,
CopyAssignable
, ni
MoveAssignable
.
Table des matières |
Membres de Données
| Nom du membre | Définition |
counter
(privé)
|
Le compteur interne de type
std::ptrdiff_t
.
( objet membre d'exposition uniquement* ) |
Fonctions membres
construit un
counting_semaphore
(fonction membre publique) |
|
détruit le
counting_semaphore
(fonction membre publique) |
|
|
operator=
[deleted]
|
counting_semaphore
n'est pas assignable
(fonction membre publique) |
Opérations |
|
|
incrémente le compteur interne et débloque les acquéreurs
(fonction membre publique) |
|
|
décrémente le compteur interne ou bloque jusqu'à ce qu'il soit possible
(fonction membre publique) |
|
|
tente de décrémenter le compteur interne sans bloquer
(fonction membre publique) |
|
|
tente de décrémenter le compteur interne, en bloquant pendant une durée maximale
(fonction membre publique) |
|
|
tente de décrémenter le compteur interne, en bloquant jusqu'à un instant donné
(fonction membre publique) |
|
Constantes |
|
|
[static]
|
retourne la valeur maximale possible du compteur interne
(fonction membre statique publique) |
Notes
Comme son nom l'indique, le
LeastMaxValue
est la valeur maximale
minimale
, et non la valeur maximale
réelle
. Par conséquent,
max()
peut produire un nombre supérieur à
LeastMaxValue
.
Contrairement au
std::mutex
, un
counting_semaphore
n'est pas lié aux threads d'exécution - l'acquisition d'un sémaphore peut s'effectuer sur un thread différent de celui qui libère le sémaphore, par exemple. Toutes les opérations sur
counting_semaphore
peuvent être réalisées concurremment et sans aucune relation avec des threads d'exécution spécifiques, à l'exception du destructeur qui ne peut pas être exécuté concurremment mais peut être réalisé sur un thread différent.
Les sémaphores sont également souvent utilisés pour la sémantique de signalisation/notification plutôt que pour l'exclusion mutuelle, en initialisant le sémaphore avec 0 et ainsi bloquant le(s) récepteur(s) qui tentent de acquire() , jusqu'à ce que le notificateur "signale" en invoquant release ( n ) . À cet égard, les sémaphores peuvent être considérés comme des alternatives aux std::condition_variable , souvent avec de meilleures performances.
| Macro de test de fonctionnalité | Valeur | Norme | Fonctionnalité |
|---|---|---|---|
__cpp_lib_semaphore
|
201907L
|
(C++20) |
std::counting_semaphore
,
std::binary_semaphore
|
Exemple
#include <chrono> #include <iostream> #include <semaphore> #include <thread> // instances globales de sémaphores binaires // les compteurs d'objets sont initialisés à zéro // les objets sont dans un état non signalé std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // attendre un signal du processus principal // en tentant de décrémenter le sémaphore smphSignalMainToThread.acquire(); // cet appel bloque jusqu'à ce que le compteur du sémaphore // soit incrémenté depuis le processus principal std::cout << "[thread] Got the signal\n"; // message de réponse // attendre 3 secondes pour imiter un travail // effectué par le thread using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // message // signaler en retour le processus principal smphSignalThreadToMain.release(); } int main() { // créer un thread de travail std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // message // signaler au thread de travail de commencer // en incrémentant le compteur du sémaphore smphSignalMainToThread.release(); // attendre que le thread de travail ait terminé // en tentant de décrémenter le compteur du sémaphore smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // message de réponse thrWorker.join(); }
Sortie :
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal