diff --git a/src/platform/ps3/threadbase.h b/src/platform/ps3/threadbase.h
index b362f66e..409230bb 100644
--- a/src/platform/ps3/threadbase.h
+++ b/src/platform/ps3/threadbase.h
@@ -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];
diff --git a/src/sys/threadbase.h b/src/sys/threadbase.h
index 3d210459..ec887b50 100644
--- a/src/sys/threadbase.h
+++ b/src/sys/threadbase.h
@@ -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];
diff --git a/test/Makefile.am b/test/Makefile.am
index 6b21786c..e9f6e65b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -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
diff --git a/test/testsuite.vcxproj b/test/testsuite.vcxproj
index 137cc6ed..55214223 100644
--- a/test/testsuite.vcxproj
+++ b/test/testsuite.vcxproj
@@ -59,6 +59,7 @@
+
diff --git a/test/unit/thread.cpp b/test/unit/thread.cpp
new file mode 100644
index 00000000..fad7fa5e
--- /dev/null
+++ b/test/unit/thread.cpp
@@ -0,0 +1,56 @@
+//
+// Lol Engine
+//
+// Copyright: (c) 2010-2013 Sam Hocevar
+// 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 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 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 */
+