GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
std::counting_semaphore::acquire(3) C++ Standard Libary std::counting_semaphore::acquire(3)

std::counting_semaphore::acquire - std::counting_semaphore::acquire


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.


(none)


(none)


May throw std::system_error.


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 <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( 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
<< "\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));
}
}


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 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████

2022.07.31 http://cppreference.com

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.