| @@ -96,6 +96,22 @@ public: | |||
| 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() | |||
| { | |||
| sys_lwmutex_lock(&m_mutex, 0); | |||
| @@ -112,6 +128,23 @@ public: | |||
| 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: | |||
| static size_t const CAPACITY = N; | |||
| T m_values[CAPACITY]; | |||
| @@ -140,6 +140,40 @@ public: | |||
| #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() | |||
| { | |||
| #if defined HAVE_PTHREAD_H | |||
| @@ -174,6 +208,40 @@ public: | |||
| 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: | |||
| static size_t const CAPACITY = N; | |||
| 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/array.cpp unit/rotation.cpp unit/string.cpp unit/map.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_DEPENDENCIES = @LOL_DEPS@ | |||
| noinst_DATA = data/gradient.png | |||
| @@ -59,6 +59,7 @@ | |||
| <ClCompile Include="unit\real.cpp" /> | |||
| <ClCompile Include="unit\rotation.cpp" /> | |||
| <ClCompile Include="unit\string.cpp" /> | |||
| <ClCompile Include="unit\thread.cpp" /> | |||
| <ClCompile Include="unit\trig.cpp" /> | |||
| <ClCompile Include="unit\vector.cpp" /> | |||
| </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 */ | |||