Namespaces
Variants
Actions

std::counting_semaphore<LeastMaxValue>::acquire

From cppreference.com
 
 
Concurrency support library
(C++11)
(C++20)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++17)
(C++11)
(C++11)
(C++17)
(C++11)
(C++14)
(C++11)
(C++11)
(C++11)
(C++11)
(C++20)
(C++20)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++26)
(C++26)
(C++26)
(C++26)
(C++11)
(C++20)
(C++11)
(C++11)(deprecated in C++20)
(C++11)(deprecated in C++20)
(C++11)
(C++11)(deprecated in C++26)
 
 
void acquire();
(since C++20)

Atomically decrements the internal counter by 1 if it is greater than 0; otherwise blocks until it is greater than 0 and can successfully decrement the internal counter.

[edit] Preconditions

(none)

[edit] Parameters

(none)

[edit] Exceptions

May throw std::system_error .

[edit] Example

The example visualizes a concurrent work of several randomized threads when no more than N (N is the semaphore desired value) of the thread-functions are active, while the other might wait on the semaphore.

Run this code
#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}; // change and see the effect
constexpr std::ptrdiff_t max_sema_threads{3}; // {1} for binary semaphore
std::counting_semaphore semaphore{max_sema_threads};
constexpr auto time_tick{10ms};
 
unsigned rnd()
{
 static std::uniform_int_distribution <unsigned> distribution{2U, 9U}; // [delays]
 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 << ", Throughput: " << max_sema_threads
 << " │ Legend: initial delay ░░ │ wait state ▒▒ │ sema occupation ██ \n"
 << std::endl ;
 }
};
 
std::array <Guide, max_threads> guides;
 
void workerThread(unsigned id)
{
 guides[id].initial_delay(); // emulate some work before sema acquisition
 semaphore.acquire(); // wait until a free sema slot is available
 guides[id].occupy_sema(); // emulate some work while sema is acquired
 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));
}

Possible output:

Default case: max_threads{10U}, max_sema_threads{3}
 
Threads: 10, Throughput: 3 │ Legend: initial delay ░░ │ wait state ▒▒ │ sema occupation ██
 
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
"Enough for everyone" case (no wait states!): max_threads{10U}, max_sema_threads{10}
 
Threads: 10, Throughput: 10 │ Legend: initial delay ░░ │ wait state ▒▒ │ sema occupation ██
 
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Binary semaphore case: max_threads{10U}, max_sema_threads{1}
 
Threads: 10, Throughput: 1 │ Legend: initial delay ░░ │ wait state ▒▒ │ sema occupation ██
 
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████

[edit] See also

increments the internal counter and unblocks acquirers
(public member function) [edit]
tries to decrement the internal counter without blocking
(public member function) [edit]
tries to decrement the internal counter, blocking for up to a duration time
(public member function) [edit]
tries to decrement the internal counter, blocking until a point in time
(public member function) [edit]
Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/thread/counting_semaphore/acquire&oldid=161745"

AltStyle によって変換されたページ (->オリジナル) /