This is a second thread-safe semaphore-oriented design pattern that's more suitable for internal application semaphores that have a fixed number of instances. There is no queue, if a semaphore instance or instances cannot be acquired, too bad.
#include <x/fixed_semaphore.H> x::fixed_semaphore s=x::fixed_semaphore::create(4); x::fixed_semaphore::base::acquiredptr acquired=s->acquire( [] { return true; }, [] { // ... }, 2);
x::fixed_semaphore
is a
reference-counted object.
Its constructor takes the number of available semaphore instances, which
defaults to 1.
acquire
() immediately returns an
x::semaphore::base::acquiredptr
.
It's null
()
if the number of available semaphores is fewer than the third, optional
parameter, which defaults to 1.
Otherwise, the first functor gets invoked. If it returns
false
,
acquire
() returns a
null
()
x::semaphore::base::acquiredptr
, and
takes no further action.
Otherwise, the requested number of semaphore instances is now
considered to be acquired
(the fixed semaphore object remains internally locked for the
duration of the functor call) and a
non-null
(),
x::semaphore::base::acquiredptr
gets returned. This is an opaque, reference-counted, handle
the represents the requested number of acquired semaphores.
The handle maintains an internal reference on the semaphore. When
the last reference to the handle goes out of scope and it gets destroyed,
the second functor that was passed to
acquire
() gets invoked.
The second functor cannot throw exceptions. When the second functor returns, the acquired semaphore instances are now considered to be released.