diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/syncqueuetest.cpp | 46 | ||||
-rw-r--r-- | yage/util/syncqueue.h | 81 | ||||
-rw-r--r-- | yage/yage.h | 5 |
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. |