Namespaces
Variants

std::counting_semaphore<LeastMaxValue>:: acquire

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
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
void acquire ( ) ;
(depuis C++20)

Décrémente atomiquement le compteur interne de 1 s'il est supérieur à 0 ; sinon se bloque jusqu'à ce qu'il soit supérieur à 0 et puisse décrémenter avec succès le compteur interne.

Table des matières

Préconditions

(aucun)

Paramètres

(aucun)

Exceptions

Peut lever std::system_error .

Exemple

L'exemple visualise le travail concurrent de plusieurs threads randomisés lorsque pas plus de N (N est la valeur desired du sémaphore) des fonctions-thread sont actives, tandis que les autres peuvent attendre sur le sémaphore.

#include <array>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <new>
#include <random>
#include <semaphore>
#include <thread>
#include <vector>
using namespace std::literals;
constexpr std::size_t max_threads{10U}; // modifiez et observez l'effet
constexpr std::ptrdiff_t max_sema_threads{3}; // {1} pour sémaphore binaire
std::counting_semaphore semaphore{max_sema_threads};
constexpr auto time_tick{10ms};
unsigned rnd()
{
    static std::uniform_int_distribution<unsigned> distribution{2U, 9U}; // [delais]
    static std::random_device engine;
    static std::mt19937 noise{engine()};
    return distribution(noise);
}
class alignas(std::hardware_destructive_interference_size) Guide
{
    inline static std::mutex cout_mutex;
    inline static std::chrono::time_point<std::chrono::high_resolution_clock> started_at;
    unsigned delay{rnd()}, occupy{rnd()}, wait_on_sema{};
public:
    static void start_time() { started_at = std::chrono::high_resolution_clock::now(); }
    void initial_delay() { std::this_thread::sleep_for(delay * time_tick); }
    void occupy_sema()
    {
        wait_on_sema =
            static_cast<unsigned>(std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::high_resolution_clock::now() - started_at -
                delay * time_tick).count() / time_tick.count());
        std::this_thread::sleep_for(occupy * time_tick);
    }
    void visualize(unsigned id, unsigned x_scale = 2) const
    {
        auto cout_n = [=](auto str, unsigned n)
        {
            for (n *= x_scale; n-- > 0; std::cout << str)
                ;
        };
        std::lock_guard lk{cout_mutex};
        std::cout << '#' << std::setw(2) << id << ' ';
        cout_n("░", delay);
        cout_n("▒", wait_on_sema);
        cout_n("█", occupy);
        std::cout << '\n';
    }
    static void show_info()
    {
        std::cout << "\nThreads: " << max_threads << ", Débit: " << max_sema_threads
                  << " │ Légende : délai initial ░░ │ état d'attente ▒▒ │ occupation du sémaphore ██ \n"
                  << std::endl;
    }
};
std::array<Guide, max_threads> guides;
void workerThread(unsigned id)
{
    guides[id].initial_delay(); // simuler un travail avant l'acquisition du sémaphore
    semaphore.acquire();        // attendre qu'un emplacement de sémaphore libre soit disponible
    guides[id].occupy_sema();   // simuler un travail pendant que le sémaphore est acquis
    semaphore.release();
    guides[id].visualiser(id);
}
int main()
{
    std::vector<std::jthread> threads;
    threads.reserve(max_threads);
    Guide::show_info();
    Guide::start_time();
    for (auto id{0U}; id != max_threads; ++id)
        threads.push_back(std::jthread(workerThread, id));
}

Sortie possible :

Cas par défaut : max_threads{10U}, max_sema_threads{3}
Threads : 10, Débit : 3 │ Légende : délai initial ░░ │ état d'attente ▒▒ │ occupation du sémaphore ██
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Cas "Assez pour tout le monde" (pas d'états d'attente !) : max_threads{10U}, max_sema_threads{10}
Threads : 10, Débit : 10 │ Légende : délai initial ░░ │ état d'attente ▒▒ │ occupation du sémaphore ██
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Cas du sémaphore binaire : max_threads{10U}, max_sema_threads{1}
Threads : 10, Débit : 1 │ Légende : délai initial ░░ │ état d'attente ▒▒ │ occupation du sémaphore ██
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████

Voir aussi

incrémente le compteur interne et débloque les acquéreurs
(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)