std::counting_semaphore<LeastMaxValue>::acquire
De cppreference.com
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.
Precondiciones
(Ninguna)
ParΓ‘metros
(Ninguno)
Excepciones
Puede lanzar std::system_error.
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.
Ejecuta este cΓ³digo
#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 ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ