.TH "FBB::Semaphore" "3bobcat" "2005\-2020" "libbobcat\-dev_5\&.07\&.00" "Dijkstra\(cq\&s Semaphore" .PP .SH "NAME" FBB::Semaphore \- Implements the Semaphore type designed by Dijkstra .PP .SH "SYNOPSIS" \fB#include \fP .br .PP Linking option: \fI\-lpthread \-lbobcat\fP .PP .SH "DESCRIPTION" .PP According to \fIhttp://en\&.wikipedia\&.org/wiki/Semaphore_(programming)\fP 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 \fISemaphore\fP as a data type was designed around 1962 by Edsger Dijkstra\&. .PP 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\&. .PP 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\(cq\&s implementation\&. .PP .SH "NAMESPACE" \fBFBB\fP .br All constructors, members, operators and manipulators, mentioned in this man\-page, are defined in the namespace \fBFBB\fP\&. .PP .SH "INHERITS FROM" \- .PP .SH "CONSTRUCTORS" .IP o \fBSemaphore(size_t nAvailable)\fP: .br The constructor defines the semaphore\(cq\&s initial state\&. With a counting semaphore \fInAvailable\fP 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 \fIwait\fP member waits until its value is incremented by another thread, calling one of the semaphore\(cq\&s \fInotify\fP members\&. .PP Copy and move constructors (and assignment operators) are not available\&. .PP .SH "MEMBER FUNCTIONS" .IP o \fBvoid notify()\fP: .br The internally maintained \fIavailable\fP value is incremented and one waiting thread (cf\&. the \fIwait\fP members below) is notified, reactivating that thread\&. .IP o \fBvoid notify_all()\fP: .br The internally maintained \fIavailable\fP value is incremented and all waiting threads (cf\&. the \fIwait\fP members below) are notified\&. Only one waiting thread will be able to obtain the semaphore\(cq\&s lock and to reduce \fIavailable\fP, and that particular thread is thereupon reactivated\&. .IP o \fBvoid set(size_t available)\fP: .br This member blocks until it has obtained the lock of the \fIstd::mutex\fP which is maintained internally by the \fISemaphore\fP object\&. Next the \fISemaphore\(cq\&s available\fP value receives the value of the member\(cq\&s argument, and the lock is released\&. .IP o \fBsize_t size() const\fP: .br Without trying to lock the \fISemaphore\fP object\(cq\&s \fImutex\fP the current value of the \fISemaphore\(cq\&s available\fP value is returned\&. .IP o \fBvoid wait()\fP: .br This member blocks for as long as the internally stored value (\fIavailable\fP) equals zero\&. When returning from \fIwait\fP the current thread holds the lock of the \fIstd::mutex\fP which is maintained internally by the \fISemaphore\fP object\&. \fINotify\fP members are used to increment \fIavailable\fP and to inform \fIwait\fP 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\&. .IP o \fBbool wait(Fun fun, Params &&\&.\&.\&.args)\fP: .br This is a member template, where \fIFun\fP is a function (object) receiving the argument passed to \fIwait\fP, and returning a \fIbool\fP\&. This member blocks until it has obtained the \fISemaphore\(cq\&s\fP mutex lock, then, while its \fIavailable\fP value equals 0, waits until being notified\&. Once it has reacquired the lock after being notified \fIfun\fP is called, receiving \fIwait\(cq\&s\fP perfectly forwarded remaining arguments\&. This member returns \fIfalse\fP if \fIfun\fP returns \fIfalse\fP\&. It returns \fItrue\fP if \fIfun\fP returns \fItrue\fP and \fIavailable\fP was unequal zero following \fIfun\fP returning \fItrue\fP\&. The function may therefore perform tasks outside of the \fISemaphore\fP local environment, which might even involve updating the \fISemaphore\(cq\&s\fP \fIavailable\fP value\&. .IP o \fBstd::cv_status wait_for(std::chrono::duration const &relTime)\fP: .br This member blocks for as long as the internally stored value (\fIavailable\fP) equals zero and the amount of time specified by \fIrelTime\fP hasn\(cq\&t passed\&. If the latter happens, \fIstd::cv_status::timeout\fP is returned, otherwise \fIstd::cv_status::no_timeout\fP is returned, in which case the current thread holds the lock of the \fIstd::mutex\fP which is maintained internally by the \fISemaphore\fP object\&. \fINotify\fP members are used to increment \fIavailable\fP and to inform \fIwait\fP 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\&. .IP o \fBstd::cv_status wait_until(std::chrono::time_point const &absTime)\fP: .br This member blocks for as long as the internally stored value (\fIavailable\fP) equals zero and the time specified by \fIabsTime\fP hasn\(cq\&t been reached\&. If the latter happens (or if \fIabsTime\fP lies in the past) \fIstd::cv_status::timeout\fP is returned, otherwise \fIstd::cv_status::no_timeout\fP is returned, in which case the current thread holds the lock of the \fIstd::mutex\fP which is maintained internally by the \fISemaphore\fP object\&. \fINotify\fP members are used to increment \fIavailable\fP and to inform \fIwait\fP 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\&. .PP .SH "EXAMPLE" .nf #include 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\(cq\&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(); } .fi .PP .SH "FILES" \fIbobcat/semaphore\fP \- defines the class interface .PP .SH "SEE ALSO" \fBbobcat\fP(7) .PP .SH "BUGS" None Reported\&. .PP .SH "BOBCAT PROJECT FILES" .PP .IP o \fIhttps://fbb\-git\&.gitlab\&.io/bobcat/\fP: gitlab project page; .IP o \fIbobcat_5\&.07\&.00\-x\&.dsc\fP: detached signature; .IP o \fIbobcat_5\&.07\&.00\-x\&.tar\&.gz\fP: source archive; .IP o \fIbobcat_5\&.07\&.00\-x_i386\&.changes\fP: change log; .IP o \fIlibbobcat1_5\&.07\&.00\-x_*\&.deb\fP: debian package containing the libraries; .IP o \fIlibbobcat1\-dev_5\&.07\&.00\-x_*\&.deb\fP: debian package containing the libraries, headers and manual pages; .PP .SH "BOBCAT" Bobcat is an acronym of `Brokken\(cq\&s Own Base Classes And Templates\(cq\&\&. .PP .SH "COPYRIGHT" This is free software, distributed under the terms of the GNU General Public License (GPL)\&. .PP .SH "AUTHOR" Frank B\&. Brokken (\fBf\&.b\&.brokken@rug\&.nl\fP)\&. .PP