Espacios de nombres
Variantes
Acciones

std::counting_semaphore<LeastMaxValue>::acquire

De cppreference.com
 
 
Biblioteca de apoyo de concurrencia
Hilos
(C++11)
(C++20)
Espacio de nombres this_thread
(C++11)
(C++11)
(C++11)
Cancelación cooperativa
Exclusión mutua
(C++11)
Gestión genérica de bloqueo
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Variables de condición
(C++11)
Semáforos
Pestillos y barreras
(C++20)
(C++20)
Futuros
(C++11)
(C++11)
(C++11)
(C++11)
Recuperación segura
(C++26)
Punteros de riesgo
Tipos atómicos
(C++11)
(C++20)
Inicialización de tipos atómicos
(C++11)(en desuso en C++20)
(C++11)(en desuso en C++20)
Orden de memoria
Funciones independientes para operaciones atómicas
Funciones independientes para indicadores atómicos
 
 
void acquire();
(desde C++20)

Disminuye atómicamente el contador interno en 1 si es mayor que 0; de lo contrario, se bloquea hasta que sea mayor que 0 y pueda disminuir con éxito el contador interno.

Contenido

[editar] Precondiciones

(Ninguna)

[editar] Parámetros

(Ninguno)

[editar] Excepciones

Puede lanzar std::system_error.

[editar] Ejemplo

El ejemplo visualiza un trabajo concurrente de varios hilos aleatorios cuando no más de N (N es el valor del semáforo desired) de las funciones del hilo están activas, mientras que el otro podría esperar por el semáforo.

#include <array>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <random>
#include <semaphore>
#include <thread>
#include <vector>
using namespace std::literals;
 
constexpr std::size_t       max_threads{10U}; // cambiar y ver el efecto
constexpr std::ptrdiff_t    max_sema_threads{3}; // {1} para semáforo binario
std::counting_semaphore     semaphore{max_sema_threads};
constexpr auto              time_tick{10ms};
 
unsigned rnd() {
    static std::uniform_int_distribution<unsigned> distribution{2U, 9U}; // [retrasos]
    static std::random_device engine;
    static std::mt19937 noise{engine()};
    return distribution(noise);
}
 
class alignas( 128 /*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) {
            n *= x_scale;
            while (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
            << "\nHilos: " << max_threads << ", Rendimiento: " << max_sema_threads
            << " │ Leyenda: retraso inicial ░░ │ edo. espera ▒▒ │ ocupación sema ██ \n"
            << std::endl;
    }
};
 
std::array<Guide, max_threads> guides;
 
void workerThread(unsigned id) {
    guides[id].initial_delay(); // emular trabajo antes adquisición semáforo
    semaphore.acquire();        // esperar hasta que ranura semáforo esté disponible
    guides[id].occupy_sema();   // emular trabajo mientras semáforo se adquiere
    semaphore.release();
    guides[id].visualize(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));
    }
}

Posible salida:

Caso por defecto: max_threads{10U}, max_sema_threads{3}
 
Hilos: 10, Rendimiento: 3 │ Leyenda: retraso inicial ░░ │ edo. espera ▒▒ │ ocupación sema ██
 
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Caso "suficiente para todos" (sin edos. de espera!): max_threads{10U}, max_sema_threads{10}
 
Hilos: 10, Rendimiento: 10 │ Leyenda: retraso inicial ░░ │ edo. espera ▒▒ │ ocupación sema ██
 
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Caso semáforo binario: max_threads{10U}, max_sema_threads{1}
 
Hilos: 10, Rendimiento: 1 │ Leyenda: retraso inicial ░░ │ edo. espera ▒▒ │ ocupación sema ██
 
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒��▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████