async_counting_semaphore


A async_counting_semaphore is the equivalent of the std::counting_semaphore.

A counting_semaphore is a lightweight synchronization primitive that can control access to a shared resource. Unlike a std::mutex, a counting_semaphore allows more than one concurrent access to the same resource, for at least LeastMaxValue concurrent accessors. The program is ill-formed if LeastMaxValue is negative.

A counting_semaphore contains an internal counter initialized by the constructor. This counter is decremented by calls to _operator co_await_, and is incremented by calls to release(). When the counter is zero, operator co_await suspends until the counter is incremented, but try_acquire() does not block;

try_acquire_for() and try_acquire_until() are not included in this interface.


Example
guaranteed_future<size_t>
your_class::to_wake_up();

async_function<>
your_class::do_work(thread_t _thread, async_counting_semaphore<>& _sem)
{
   /* Move into our thread */
   co_await yield(_thread);

   /* Consumer loop wont block as it suspends... */
   while (true)
   {

      /* Process work as it comes in... */
      co_await _sem;

      /* Do some work... */
   }
}

async_function<>
your_class::queue_work()
{
   /* Move into thread 0 */
   co_await yield(thread_t{0})

   async_counting_semaphore<> sem(engine_, 0);

   /* Create worker [logical] threads 1 - n */
   const auto threads = engine_->number_of_workers();
   assert(t > 1);
   for (std::uint16_t t = 1; t < threads; ++t)
   {
      do_work(thread_t{t}, sem);
   }

   /* Producer loop wont block as it suspends... */
   while (true)
   {
      /* Get work from somewhere */
      auto to_wake_up = co_await to_wake_up();

      /* notify to wake up threads */
      sem.release(to_wake_up);
   }
}

template<std::ptrdiff_t Count = 2>
class zab::async_counting_semaphore

Public Functions

inline async_counting_semaphore(engine *_engine, std::ptrdiff_t _start)
inline async_counting_semaphore(engine *_engine)
~async_counting_semaphore() = default
inline bool try_aquire() noexcept
inline void release(std::ptrdiff_t _update = 1) noexcept
inline waiter operator co_await() noexcept
struct waiter

Public Functions

inline bool await_suspend(std::coroutine_handle<> _awaiter) noexcept
inline bool await_ready() const noexcept
inline void await_resume() const noexcept

Public Members

async_counting_semaphore &semaphore_
thread_t thread_ = thread_t{}
waiter *next_waiting_ = nullptr
std::coroutine_handle handle_ = nullptr