FBB::Semaphore - Implements the Semaphore type designed by
Dijkstra
#include <bobcat/semaphore>
Linking option: -lpthread -lbobcat
According to
http://en.wikipedia.org/wiki/Semaphore_(programming) a semaphore is a
variable or abstract data type that is used for controlling access, by
multiple processes, to a common resource in a parallel programming or a
multi user environment. The Semaphore as a data type was designed
around 1962 by Edsger Dijkstra.
A useful way to think of a semaphore is as a record of how many
units of a particular resource are available, coupled with operations to
safely (i.e., without race conditions) adjust that record as units are
required or become free, and, if necessary, wait until a unit of the
resource becomes available.
Semaphores are a useful tool in the prevention of race conditions.
Semaphores allowing an arbitrary resource count are called counting
semaphores, while semaphores which are restricted to the values 0 and 1 (or
locked/unlocked, unavailable/available) are called binary semaphores. Both
types are supported by Bobcat’s implementation.
FBB
All constructors, members, operators and manipulators, mentioned in this
man-page, are defined in the namespace FBB.
- o
- Semaphore(size_t nAvailable):
The constructor defines the semaphore’s initial state. With a
counting semaphore nAvailable defines, e.g., the number of
available locations in a storage area. Locking/unlocking, supporting
facilities to notify other waiting threads is implemented via binary
semaphores, which are initialized to 1 or 0. A semaphore containing the
value 0 blocks. I.e., its wait member waits until its value is
incremented by another thread, calling one of the semaphore’s
notify members.
Copy and move constructors (and assignment operators) are not
available.
- o
- void notify():
The internally maintained available value is incremented and one
waiting thread (cf. the wait members below) is notified,
reactivating that thread.
- o
- void notify_all():
The internally maintained available value is incremented and all
waiting threads (cf. the wait members below) are notified. Only one
waiting thread will be able to obtain the semaphore’s lock and to
reduce available, and that particular thread is thereupon
reactivated.
- o
- void set(size_t available):
This member blocks until it has obtained the lock of the std::mutex
which is maintained internally by the Semaphore object. Next the
Semaphore’s available value receives the value of the
member’s argument, and the lock is released.
- o
- size_t size() const:
Without trying to lock the Semaphore object’s mutex the
current value of the Semaphore’s available value is
returned.
- o
- void wait():
This member blocks for as long as the internally stored value
(available) equals zero. When returning from wait the
current thread holds the lock of the std::mutex which is maintained
internally by the Semaphore object. Notify members are used
to increment available and to inform wait that it may
return. When multiple threads are waiting only one thread will stop
waiting, while the remaining threads will continue to wait for another
notification.
- o
- bool wait(Fun fun, Params &&...args):
This is a member template, where Fun is a function (object) receiving
the argument passed to wait, and returning a bool. This
member blocks until it has obtained the Semaphore’s mutex
lock, then, while its available value equals 0, waits until being
notified. Once it has reacquired the lock after being notified fun
is called, receiving wait’s perfectly forwarded remaining
arguments. This member returns false if fun returns
false. It returns true if fun returns true and
available was unequal zero following fun returning
true. The function may therefore perform tasks outside of the
Semaphore local environment, which might even involve updating the
Semaphore’s available value.
- o
- std::cv_status wait_for(std::chrono::duration<Rep, Period>
const &relTime):
This member blocks for as long as the internally stored value
(available) equals zero and the amount of time specified by
relTime hasn’t passed. If the latter happens,
std::cv_status::timeout is returned, otherwise
std::cv_status::no_timeout is returned, in which case the current
thread holds the lock of the std::mutex which is maintained
internally by the Semaphore object. Notify members are used
to increment available and to inform wait that it may
return. When multiple threads are waiting only one thread will stop
waiting, while the remaining threads will continue to wait for another
notification.
- o
- std::cv_status wait_until(std::chrono::time_point<Clock,
Duration> const &absTime):
This member blocks for as long as the internally stored value
(available) equals zero and the time specified by absTime
hasn’t been reached. If the latter happens (or if absTime
lies in the past) std::cv_status::timeout is returned, otherwise
std::cv_status::no_timeout is returned, in which case the current
thread holds the lock of the std::mutex which is maintained
internally by the Semaphore object. Notify members are used
to increment available and to inform wait that it may
return. When multiple threads are waiting only one thread will stop
waiting, while the remaining threads will continue to wait for another
notification.
#include <bobcat/semaphore>
using namespace FBB;
Semaphore produce(10); // storage area size
Semaphore consume(0); // # items in store
std::queue itemQueue; // storage queue
void consumer()
{
while (true)
{
consume.wait(); // wait until there’s an item in store
// mutex lock the queue with multiple consumers
size_t item = itemQueue.front();
itemQueue.pop();
produce.notify(); // notify the producer
process(item); // not implemented
}
}
void producer()
{
size_t item = 0;
while (true)
{
++item;
produce.wait(); // wait for room in the storage
// mutex lock the queue with multiple consumers
itemQueue.push(item);
consume.notify(); // notify the consumer
}
}
int main()
{
thread cons(consumer);
thread prod(producer);
cons.join(); // ending the threads not implemented
prod.join();
}
bobcat/semaphore - defines the class interface
- o
- https://fbb-git.gitlab.io/bobcat/: gitlab project page;
- o
- bobcat_5.07.00-x.dsc: detached signature;
- o
- bobcat_5.07.00-x.tar.gz: source archive;
- o
- bobcat_5.07.00-x_i386.changes: change log;
- o
- libbobcat1_5.07.00-x_*.deb: debian package containing the
libraries;
- o
- libbobcat1-dev_5.07.00-x_*.deb: debian package containing the
libraries, headers and manual pages;
Bobcat is an acronym of `Brokken’s Own Base Classes And
Templates’.
This is free software, distributed under the terms of the GNU
General Public License (GPL).
Frank B. Brokken (f.b.brokken@rug.nl).