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