| @@ -96,6 +96,22 @@ public: | |||||
| sys_lwmutex_unlock(&m_mutex); | sys_lwmutex_unlock(&m_mutex); | ||||
| } | } | ||||
| bool TryPush(T value) | |||||
| { | |||||
| sys_lwmutex_lock(&m_mutex, 0); | |||||
| if (m_count == CAPACITY) | |||||
| { | |||||
| sys_lwmutex_unlock(&m_mutex); | |||||
| return false; | |||||
| } | |||||
| m_values[(m_start + m_count) % CAPACITY] = value; | |||||
| m_count++; | |||||
| if (m_poppers) | |||||
| sys_lwcond_signal(&m_empty_cond); | |||||
| sys_lwmutex_unlock(&m_mutex); | |||||
| return true; | |||||
| } | |||||
| T Pop() | T Pop() | ||||
| { | { | ||||
| sys_lwmutex_lock(&m_mutex, 0); | sys_lwmutex_lock(&m_mutex, 0); | ||||
| @@ -112,6 +128,23 @@ public: | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| bool TryPop(T &ret) | |||||
| { | |||||
| sys_lwmutex_lock(&m_mutex, 0); | |||||
| if (m_count == 0) | |||||
| { | |||||
| sys_lwmutex_unlock(&m_mutex); | |||||
| return false; | |||||
| } | |||||
| ret = m_values[m_start]; | |||||
| m_start = (m_start + 1) % CAPACITY; | |||||
| m_count--; | |||||
| if (m_pushers) | |||||
| sys_lwcond_signal(&m_full_cond); | |||||
| sys_lwmutex_unlock(&m_mutex); | |||||
| return true; | |||||
| } | |||||
| private: | private: | ||||
| static size_t const CAPACITY = N; | static size_t const CAPACITY = N; | ||||
| T m_values[CAPACITY]; | T m_values[CAPACITY]; | ||||
| @@ -140,6 +140,40 @@ public: | |||||
| #endif | #endif | ||||
| } | } | ||||
| bool TryPush(T value) | |||||
| { | |||||
| #if defined HAVE_PTHREAD_H | |||||
| pthread_mutex_lock(&m_mutex); | |||||
| /* If queue is full, wait on the "full" cond var. */ | |||||
| if (m_count == CAPACITY) | |||||
| { | |||||
| pthread_mutex_unlock(&m_mutex); | |||||
| return false; | |||||
| } | |||||
| #elif defined _WIN32 | |||||
| DWORD status = WaitForSingleObject(m_empty_sem, 0); | |||||
| if (status == WAIT_TIMEOUT) | |||||
| return false; | |||||
| EnterCriticalSection(&m_mutex); | |||||
| #endif | |||||
| /* Push value */ | |||||
| m_values[(m_start + m_count) % CAPACITY] = value; | |||||
| m_count++; | |||||
| #if defined HAVE_PTHREAD_H | |||||
| /* If there were poppers waiting, signal the "empty" cond var. */ | |||||
| if (m_poppers) | |||||
| pthread_cond_signal(&m_empty_cond); | |||||
| pthread_mutex_unlock(&m_mutex); | |||||
| #elif defined _WIN32 | |||||
| LeaveCriticalSection(&m_mutex); | |||||
| ReleaseSemaphore(m_full_sem, 1, nullptr); | |||||
| #endif | |||||
| return true; | |||||
| } | |||||
| T Pop() | T Pop() | ||||
| { | { | ||||
| #if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
| @@ -174,6 +208,40 @@ public: | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| bool TryPop(T &ret) | |||||
| { | |||||
| #if defined HAVE_PTHREAD_H | |||||
| pthread_mutex_lock(&m_mutex); | |||||
| if (m_count == 0) | |||||
| { | |||||
| pthread_mutex_unlock(&m_mutex); | |||||
| return false; | |||||
| } | |||||
| #elif defined _WIN32 | |||||
| DWORD status = WaitForSingleObject(m_full_sem, 0); | |||||
| if (status == WAIT_TIMEOUT) | |||||
| return false; | |||||
| EnterCriticalSection(&m_mutex); | |||||
| #endif | |||||
| /* Pop value */ | |||||
| ret = m_values[m_start]; | |||||
| m_start = (m_start + 1) % CAPACITY; | |||||
| m_count--; | |||||
| #if defined HAVE_PTHREAD_H | |||||
| /* If there were pushers waiting, signal the "full" cond var. */ | |||||
| if (m_pushers) | |||||
| pthread_cond_signal(&m_full_cond); | |||||
| pthread_mutex_unlock(&m_mutex); | |||||
| #else | |||||
| LeaveCriticalSection(&m_mutex); | |||||
| ReleaseSemaphore(m_empty_sem, 1, nullptr); | |||||
| #endif | |||||
| return true; | |||||
| } | |||||
| private: | private: | ||||
| static size_t const CAPACITY = N; | static size_t const CAPACITY = N; | ||||
| T m_values[CAPACITY]; | T m_values[CAPACITY]; | ||||
| @@ -20,7 +20,7 @@ testsuite_SOURCES = testsuite.cpp \ | |||||
| unit/build.cpp unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp \ | unit/build.cpp unit/real.cpp unit/image.cpp unit/quat.cpp unit/cmplx.cpp \ | ||||
| unit/array.cpp unit/rotation.cpp unit/string.cpp unit/map.cpp \ | unit/array.cpp unit/rotation.cpp unit/string.cpp unit/map.cpp \ | ||||
| unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp \ | unit/color.cpp unit/atomic.cpp unit/interp.cpp unit/box.cpp \ | ||||
| unit/rand.cpp | |||||
| unit/rand.cpp unit/thread.cpp | |||||
| testsuite_CPPFLAGS = $(AM_CPPFLAGS) | testsuite_CPPFLAGS = $(AM_CPPFLAGS) | ||||
| testsuite_DEPENDENCIES = @LOL_DEPS@ | testsuite_DEPENDENCIES = @LOL_DEPS@ | ||||
| noinst_DATA = data/gradient.png | noinst_DATA = data/gradient.png | ||||
| @@ -59,6 +59,7 @@ | |||||
| <ClCompile Include="unit\real.cpp" /> | <ClCompile Include="unit\real.cpp" /> | ||||
| <ClCompile Include="unit\rotation.cpp" /> | <ClCompile Include="unit\rotation.cpp" /> | ||||
| <ClCompile Include="unit\string.cpp" /> | <ClCompile Include="unit\string.cpp" /> | ||||
| <ClCompile Include="unit\thread.cpp" /> | |||||
| <ClCompile Include="unit\trig.cpp" /> | <ClCompile Include="unit\trig.cpp" /> | ||||
| <ClCompile Include="unit\vector.cpp" /> | <ClCompile Include="unit\vector.cpp" /> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| @@ -0,0 +1,56 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #if defined HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include "core.h" | |||||
| #include "lol/unit.h" | |||||
| namespace lol | |||||
| { | |||||
| LOLUNIT_FIXTURE(ThreadTest) | |||||
| { | |||||
| void SetUp() {} | |||||
| void TearDown() {} | |||||
| LOLUNIT_TEST(QueueTryPush) | |||||
| { | |||||
| Queue<int, 1> q; | |||||
| bool b1 = q.TryPush(0); | |||||
| LOLUNIT_ASSERT_EQUAL(true, b1); | |||||
| bool b2 = q.TryPush(1); | |||||
| LOLUNIT_ASSERT_EQUAL(false, b2); | |||||
| } | |||||
| LOLUNIT_TEST(QueueTryPop) | |||||
| { | |||||
| Queue<int, 1> q; | |||||
| int tmp; | |||||
| q.Push(42); | |||||
| bool b1 = q.TryPop(tmp); | |||||
| LOLUNIT_ASSERT_EQUAL(true, b1); | |||||
| LOLUNIT_ASSERT_EQUAL(42, tmp); | |||||
| bool b2 = q.TryPop(tmp); | |||||
| LOLUNIT_ASSERT_EQUAL(false, b2); | |||||
| LOLUNIT_ASSERT_EQUAL(42, tmp); | |||||
| } | |||||
| }; | |||||
| } /* namespace lol */ | |||||