aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--tests/syncqueuetest.cpp46
-rw-r--r--yage/util/syncqueue.h81
-rw-r--r--yage/yage.h5
4 files changed, 133 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f003b103..b6826631 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,4 +48,5 @@ if($ENV{UNIT_TESTS})
make_test(vector4test ${SIMULATION_RUNS})
make_test(logtest 1)
make_test(threadtest 1)
+ make_test(syncqueuetest 1)
endif()
diff --git a/tests/syncqueuetest.cpp b/tests/syncqueuetest.cpp
new file mode 100644
index 00000000..cb9a920e
--- /dev/null
+++ b/tests/syncqueuetest.cpp
@@ -0,0 +1,46 @@
+#include <yage.h>
+
+#include <atomic>
+#include <thread>
+
+using namespace yage;
+
+SyncQueue<int> queue;
+std::atomic_int j;
+
+void push_to_queue1(int elements)
+{
+ for (int i = 0; i < elements; i++) {
+ queue.push(1);
+ j.fetch_add(1, std::memory_order_relaxed);
+ }
+ std::cout << "Done 1\n";
+}
+
+void push_to_queue2(int elements)
+{
+ for (int i = 0; i < elements; i++) {
+ queue.push(2);
+ j.fetch_add(1, std::memory_order_relaxed);
+ }
+ std::cout << "Done 2\n";
+}
+
+int main()
+{
+ j.store(0);
+ std::thread first(push_to_queue1, 100000);
+ std::thread second(push_to_queue2, 100000);
+
+ std::cout << "created threads, now adding in main\n";
+ for (int i = 0; i < 1000000; ++i) {
+ queue.push(i);
+ j.fetch_add(1, std::memory_order_relaxed);
+ }
+
+ std::cout << "now joining the threads\n";
+ first.join();
+ second.join();
+ std::cout << "done\n"
+ << "iterations: " << j << "\n";
+}
diff --git a/yage/util/syncqueue.h b/yage/util/syncqueue.h
new file mode 100644
index 00000000..a23b1857
--- /dev/null
+++ b/yage/util/syncqueue.h
@@ -0,0 +1,81 @@
+#ifndef YAGE_UTIL_SYNCQUEUE_H
+#define YAGE_UTIL_SYNCQUEUE_H
+
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+
+namespace yage
+{
+
+template <typename T>
+class SyncQueue
+{
+public:
+ SyncQueue() = default;
+ SyncQueue(const SyncQueue &) = delete;
+ SyncQueue &operator=(const SyncQueue &) = delete;
+
+ T pop();
+ void pop(T &item);
+ void push(const T &item);
+ void push(T &&item);
+
+private:
+ std::queue<T> queue_;
+ std::mutex mutex_;
+ std::condition_variable cond_;
+};
+
+// Template definitions
+
+template <typename T>
+T SyncQueue<T>::pop()
+{
+ std::unique_lock<std::mutex> mlock(mutex_);
+
+ while (queue_.empty()) {
+ cond_.wait(mlock);
+ }
+
+ auto item = queue_.front();
+ queue_.pop();
+ return item;
+}
+
+template <typename T>
+void SyncQueue<T>::pop(T &item)
+{
+ std::unique_lock<std::mutex> mlock(mutex_);
+
+ while (queue_.empty()) {
+ cond_.wait(mlock);
+ }
+
+ item = queue_.front();
+ queue_.pop();
+}
+
+template <typename T>
+void SyncQueue<T>::push(const T &item)
+{
+ std::unique_lock<std::mutex> mlock(mutex_);
+
+ queue_.push(item);
+ mlock.unlock();
+ cond_.notify_one();
+}
+
+template <typename T>
+void SyncQueue<T>::push(T &&item)
+{
+ std::unique_lock<std::mutex> mlock(mutex_);
+
+ queue_.push(std::move(item));
+ mlock.unlock();
+ cond_.notify_one();
+}
+
+} // namespace yage
+
+#endif
diff --git a/yage/yage.h b/yage/yage.h
index 8becefde..d9f5a6e6 100644
--- a/yage/yage.h
+++ b/yage/yage.h
@@ -35,6 +35,11 @@
#include "physics/rectanglecollider.h"
#include "physics/rigidbody.h"
+#include "math/matrix.h"
+
+#include "util/active.h"
+#include "util/syncqueue.h"
+
/** Project namespace.
*
* Avoids collision as all the classes and global functions are wrapped in.