summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2015-11-17 22:21:09 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2015-11-17 22:21:09 +0000
commit22fe281b639187960a9ca92c58676ad55bcc0769 (patch)
tree06f9a096cd1421e0b301e1ca89dd88dfd76aaad6
parentImprove core with traits and decltype for working with functions that return ... (diff)
downloadlibadhocutil-22fe281b639187960a9ca92c58676ad55bcc0769.tar.bz2
libadhocutil-22fe281b639187960a9ca92c58676ad55bcc0769.tar.xz
libadhocutil-22fe281b639187960a9ca92c58676ad55bcc0769.zip
Add a portable semaphore class with timeout support
-rw-r--r--libadhocutil/Jamfile.jam5
-rw-r--r--libadhocutil/semaphore.cpp40
-rw-r--r--libadhocutil/semaphore.h29
-rw-r--r--libadhocutil/unittests/Jamfile.jam11
-rw-r--r--libadhocutil/unittests/testSemaphore.cpp44
5 files changed, 128 insertions, 1 deletions
diff --git a/libadhocutil/Jamfile.jam b/libadhocutil/Jamfile.jam
index 861509a..c82dade 100644
--- a/libadhocutil/Jamfile.jam
+++ b/libadhocutil/Jamfile.jam
@@ -1,7 +1,8 @@
import package ;
import lex ;
-lib boost_utf : : <name>boost_unit_test_framework ;
+lib boost_system ;
+lib boost_thread ;
lib Ice : ;
lib IceUtil ;
lib pthread ;
@@ -15,6 +16,8 @@ lib adhocutil :
:
<include>.
<library>iceall
+ <library>boost_system
+ <library>boost_thread
<library>curl
<library>dl
<cflags>-fvisibility=hidden
diff --git a/libadhocutil/semaphore.cpp b/libadhocutil/semaphore.cpp
new file mode 100644
index 0000000..0500445
--- /dev/null
+++ b/libadhocutil/semaphore.cpp
@@ -0,0 +1,40 @@
+#include "semaphore.h"
+
+namespace AdHoc {
+ Semaphore::Semaphore(unsigned int initial) : count(initial)
+ {
+ }
+
+ void
+ Semaphore::notify()
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ ++count;
+ condition.notify_one();
+ }
+
+ void
+ Semaphore::wait()
+ {
+ boost::mutex::scoped_lock lock(mutex);
+ while (!count) {
+ condition.wait(lock);
+ }
+ --count;
+ }
+
+ bool
+ Semaphore::wait(unsigned int timeout)
+ {
+ const boost::system_time expiry = boost::get_system_time() + boost::posix_time::milliseconds(timeout);
+ boost::mutex::scoped_lock lock(mutex);
+ while (!count) {
+ if (!condition.timed_wait(lock, expiry)) {
+ return false;
+ }
+ }
+ --count;
+ return true;
+ }
+}
+
diff --git a/libadhocutil/semaphore.h b/libadhocutil/semaphore.h
new file mode 100644
index 0000000..de10333
--- /dev/null
+++ b/libadhocutil/semaphore.h
@@ -0,0 +1,29 @@
+#ifndef ADHOCUTIL_SEMAPHORE_H
+#define ADHOCUTIL_SEMAPHORE_H
+
+// Borrowed from StackOverflow
+// http://stackoverflow.com/questions/4792449/c0x-has-no-semaphores-how-to-synchronize-threads
+
+#include <boost/thread/condition.hpp>
+#include <boost/thread/mutex.hpp>
+#include "visibility.h"
+
+namespace AdHoc {
+ /// A portable semaphore with timeout support
+ class DLL_PUBLIC Semaphore {
+ public:
+ Semaphore(unsigned int initial = 0);
+
+ void notify();
+ void wait();
+ bool wait(unsigned int);
+
+ private:
+ boost::mutex mutex;
+ boost::condition_variable condition;
+ unsigned long count;
+ };
+}
+
+#endif
+
diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam
index 0961f31..334b47e 100644
--- a/libadhocutil/unittests/Jamfile.jam
+++ b/libadhocutil/unittests/Jamfile.jam
@@ -165,6 +165,17 @@ run
;
run
+ testSemaphore.cpp
+ : : :
+ <define>BOOST_TEST_DYN_LINK
+ <library>..//adhocutil
+ <library>boost_utf
+ <library>boost_system
+ :
+ testSemaphore
+ ;
+
+run
testException.cpp
: : :
<define>BOOST_TEST_DYN_LINK
diff --git a/libadhocutil/unittests/testSemaphore.cpp b/libadhocutil/unittests/testSemaphore.cpp
new file mode 100644
index 0000000..b5e435e
--- /dev/null
+++ b/libadhocutil/unittests/testSemaphore.cpp
@@ -0,0 +1,44 @@
+#define BOOST_TEST_MODULE Semaphore
+#include <boost/test/unit_test.hpp>
+
+#include <thread>
+#include <semaphore.h>
+
+BOOST_AUTO_TEST_CASE( addRemoveOne )
+{
+ AdHoc::Semaphore s;
+ s.notify();
+ s.wait();
+}
+
+BOOST_AUTO_TEST_CASE( addRemoveSome )
+{
+ AdHoc::Semaphore s;
+ s.notify();
+ s.notify();
+ s.notify();
+ s.wait();
+ s.wait();
+ s.wait();
+}
+
+BOOST_AUTO_TEST_CASE( addRemoveTimeOut )
+{
+ AdHoc::Semaphore s;
+ s.notify();
+ s.wait();
+ BOOST_REQUIRE_EQUAL(false, s.wait(100));
+ BOOST_REQUIRE_EQUAL(false, s.wait(0));
+}
+
+BOOST_AUTO_TEST_CASE( addRemoveWait )
+{
+ AdHoc::Semaphore s;
+ s.notify();
+ s.wait();
+ std::thread th([&s]() { usleep(100000); s.notify(); });
+ BOOST_REQUIRE_EQUAL(false, s.wait(1));
+ s.wait();
+ th.join();
+}
+