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 <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_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) {
		    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 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

http://cppreference.com		  2022.07.31	  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.0>

home | help