Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
std::counti...re::acquire(3)  C++ Standard Libary std::counti...re::acquire(3)

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

Synopsis
	  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.

Preconditions
	  (none)

Parameters
	  (none)

Exceptions
	  May throw std::system_error.

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	 sema-
       phore
	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_resolu-
       tion_clock> started_at;
	    unsigned delay{rnd()}, occupy{rnd()}, wait_on_sema{};

	public:
	    static  void start_time() {	started_at = std::chrono::high_resolu-
       tion_clock::now(); }

	    void   initial_delay()   {	 std::this_thread::sleep_for(delay   *
       time_tick); }

	    void occupy_sema()
	    {
		wait_on_sema =
		    static_cast<unsigned>(std::chrono::dura-
       tion_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  oc-
       cupation	 \n"
			  << std::endl;
	    }
	};

	std::array<Guide, max_threads> guides;

	void workerThread(unsigned id)
	{
	    guides[id].initial_delay();	 //  emulate some work before sema ac-
       quisition
	    semaphore.acquire();	// wait	until  a  free	sema  slot  is
       available
	    guides[id].occupy_sema();	// emulate some	work while sema	is ac-
       quired
	    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

See also
	  release	    increments the internal counter and	 unblocks  ac-
       quirers
			    (public member function)
	  try_acquire	     tries  to	decrement the internal counter without
       blocking
			    (public member function)
			    tries to decrement the internal counter,  blocking
       for up to a
	  try_acquire_for   duration time
			    (public member function)
			    tries  to decrement	the internal counter, blocking
       until a point in
	  try_acquire_until time
			    (public member function)

http://cppreference.com		  2024.06.10	  std::counti...re::acquire(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::counting_semaphore::acquire&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help