@@ -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 */ | |||||