Browse Source

thread: implement Queue::TryPush and Queue::TryPop.

undefined
Sam Hocevar 11 years ago
parent
commit
ca230a60ad
5 changed files with 159 additions and 1 deletions
  1. +33
    -0
      src/platform/ps3/threadbase.h
  2. +68
    -0
      src/sys/threadbase.h
  3. +1
    -1
      test/Makefile.am
  4. +1
    -0
      test/testsuite.vcxproj
  5. +56
    -0
      test/unit/thread.cpp

+ 33
- 0
src/platform/ps3/threadbase.h View File

@@ -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];


+ 68
- 0
src/sys/threadbase.h View File

@@ -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];


+ 1
- 1
test/Makefile.am View File

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


+ 1
- 0
test/testsuite.vcxproj View File

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


+ 56
- 0
test/unit/thread.cpp View File

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


Loading…
Cancel
Save