Namespaces
Variants

std:: counting_semaphore, std:: binary_semaphore

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
counting_semaphore binary_semaphore
(C++20) (C++20)
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
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
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)
1) Un 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.
2) binary_semaphore est un alias pour la spécialisation de std::counting_semaphore 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