Browse Source

sys: get rid of pthreads.

Since C++11 threads are available on every platform that has threads, we
no longer need our pthread implementation. The LOL_FEATURE_CXX11_THREADS
macro is gone, too, and we now just use LOL_FEATURE_THREADS.

Note that it is still necessary to link with -lpthread or -pthread on
some platforms, so we don’t throw that part away.
undefined
Sam Hocevar 9 years ago
parent
commit
144cb0df31
7 changed files with 41 additions and 212 deletions
  1. +1
    -1
      build/lol-build
  2. +0
    -1
      build/msbuild/lol.vars.props
  3. +1
    -1
      configure.ac
  4. +0
    -4
      src/lol/base/features.h
  5. +0
    -1
      src/platform/nacl/opengl_context.cpp
  6. +0
    -1
      src/platform/nacl/opengl_context.h
  7. +39
    -203
      src/sys/threadbase.h

+ 1
- 1
build/lol-build View File

@@ -236,7 +236,7 @@ configure()
# ant clean
;;
raspi-arm)
do_configure --host=arm-bcm2708hardfp-linux-gnueabi CPPFLAGS="-I$RASPI_SDK_ROOT/firmware/opt/vc/include -I$RASPI_SDK_ROOT/firmware/opt/vc/include/interface/vcos/pthreads -I$RASPI_SDK_ROOT/firmware/opt/vc/include/interface/vmcs_host/linux -I$RASPI_SDK_ROOT/chroot/usr/include -I$RASPI_SDK_ROOT/chroot/usr/include/arm-linux-gnueabihf" LDFLAGS="-L$RASPI_SDK_ROOT/firmware/opt/vc/lib -L$RASPI_SDK_ROOT/chroot/lib/arm-linux-gnueabihf -Wl,-rpath-link -Wl,$RASPI_SDK_ROOT/chroot/lib/arm-linux-gnueabihf -L$RASPI_SDK_ROOT/chroot/usr/lib/arm-linux-gnueabihf -Wl,-rpath-link -Wl,$RASPI_SDK_ROOT/chroot/usr/lib/arm-linux-gnueabihf -Wl,--unresolved-symbols=ignore-in-shared-libs"
do_configure --host=arm-bcm2708hardfp-linux-gnueabi CPPFLAGS="-I$RASPI_SDK_ROOT/firmware/opt/vc/include -I$RASPI_SDK_ROOT/firmware/opt/vc/include/interface/vmcs_host/linux -I$RASPI_SDK_ROOT/chroot/usr/include -I$RASPI_SDK_ROOT/chroot/usr/include/arm-linux-gnueabihf" LDFLAGS="-L$RASPI_SDK_ROOT/firmware/opt/vc/lib -L$RASPI_SDK_ROOT/chroot/lib/arm-linux-gnueabihf -Wl,-rpath-link -Wl,$RASPI_SDK_ROOT/chroot/lib/arm-linux-gnueabihf -L$RASPI_SDK_ROOT/chroot/usr/lib/arm-linux-gnueabihf -Wl,-rpath-link -Wl,$RASPI_SDK_ROOT/chroot/usr/lib/arm-linux-gnueabihf -Wl,--unresolved-symbols=ignore-in-shared-libs"
;;
nacl-i386)
do_configure CXX=i686-nacl-g++ CC=i686-nacl-gcc ac_cv_exeext=.32.nexe --host=i386 CPPFLAGS="-I$NACL_SDK_ROOT/include" LOL_LIBS="-lppapi -lppapi_gles2 -lppapi_cpp -u _ZN2pp12CreateModuleEv"


+ 0
- 1
build/msbuild/lol.vars.props View File

@@ -98,7 +98,6 @@

<!-- PS4-specific -->
<OrbisDefines>HAVE_STDIO_H;
HAVE_PTHREAD_H;
$(OrbisDefines)</OrbisDefines>

<!-- X360-specific -->


+ 1
- 1
configure.ac View File

@@ -99,7 +99,7 @@ AC_ARG_ENABLE(doc,

dnl Common C headers
AC_CHECK_HEADERS(stdio.h stdarg.h inttypes.h endian.h stdint.h getopt.h math.h)
AC_CHECK_HEADERS(fastmath.h pthread.h libutil.h util.h pty.h glob.h unistd.h io.h)
AC_CHECK_HEADERS(fastmath.h libutil.h util.h pty.h glob.h unistd.h io.h)
AC_CHECK_HEADERS(execinfo.h)
AC_CHECK_HEADERS(sys/ioctl.h sys/ptrace.h sys/stat.h sys/syscall.h sys/user.h)
AC_CHECK_HEADERS(sys/wait.h sys/time.h sys/types.h)


+ 0
- 4
src/lol/base/features.h View File

@@ -28,7 +28,6 @@

#if defined EMSCRIPTEN
# undef LOL_FEATURE_THREADS
# define LOL_FEATURE_THREADS 0
#endif

/* Use this to disable code that causes compiler crashes. */
@@ -51,9 +50,6 @@
#undef LOL_FEATURE_CXX11_NULLPTR
#undef LOL_FEATURE_CXX11_TEMPLATE_ALIASES
#undef LOL_FEATURE_CXX11_SFINAE_FOR_CTORS
#undef LOL_FEATURE_CXX11_THREADS /* Touky: Is it really needed ? */

#define LOL_FEATURE_CXX11_THREADS 1 /* Touky: This should be available everywhere */

/* Features supported by GCC */
#if defined __GNUC__


+ 0
- 1
src/platform/nacl/opengl_context.cpp View File

@@ -4,7 +4,6 @@

#include <lol/engine-internal.h>

#include <pthread.h>
#include <ppapi/cpp/completion_callback.h>
#include <ppapi/gles2/gl2ext_ppapi.h>



+ 0
- 1
src/platform/nacl/opengl_context.h View File

@@ -11,7 +11,6 @@
///

#include <assert.h>
#include <pthread.h>

#include <algorithm>
#include <string>


+ 39
- 203
src/sys/threadbase.h View File

@@ -18,16 +18,12 @@
// -----------------------------------
//

#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
# include <thread>
# include <mutex>
# include <condition_variable>
#elif defined HAVE_PTHREAD_H
# include <pthread.h>
#else
# error No threading support yet :(
/* Nothing */
#endif

/* XXX: workaround for a bug in Visual Studio 2012 and 2013!
@@ -54,152 +50,74 @@ namespace lol
class mutex_base
{
public:
//-------------------------------------------------------------------------
mutex_base()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
/* Nothing */
#elif defined HAVE_PTHREAD_H
pthread_mutex_init(&m_mutex, nullptr);
#endif
}

//-------------------------------------------------------------------------
~mutex_base()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
/* Nothing */
#elif defined HAVE_PTHREAD_H
pthread_mutex_destroy(&m_mutex);
#endif
}

//Will block the thread if another has already locked ---------------------
// Will block the thread if another has already locked
void lock()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
m_mutex.lock();
#elif defined HAVE_PTHREAD_H
pthread_mutex_lock(&m_mutex);
#endif
}

// Will not block if another thread has already locked ---------------------
// Will not block if another thread has already locked
bool try_lock()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
return false;
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
return m_mutex.try_lock();
#elif defined HAVE_PTHREAD_H
return !pthread_mutex_trylock(&m_mutex);
#else
return false;
#endif
}

//-------------------------------------------------------------------------
void unlock()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
m_mutex.unlock();
#elif defined HAVE_PTHREAD_H
pthread_mutex_unlock(&m_mutex);
#endif
}

//-------------------------------------------------------------------------
private:
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
std::mutex m_mutex;
#elif defined HAVE_PTHREAD_H
pthread_mutex_t m_mutex;
#endif
};

//A FIFO queue for threads ----------------------------------------------------
// A FIFO queue for threads
template<typename T, int N>
class queue_base
{
public:
queue_base()
: m_start(0),
m_count(0)
{
m_start = m_count = 0;
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
/* Nothing */
#elif defined HAVE_PTHREAD_H
m_poppers = m_pushers = 0;
pthread_mutex_init(&m_mutex, nullptr);
pthread_cond_init(&m_empty_cond, nullptr);
pthread_cond_init(&m_full_cond, nullptr);
#endif
}

~queue_base()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
/* Nothing */
#elif defined HAVE_PTHREAD_H
pthread_cond_destroy(&m_empty_cond);
pthread_cond_destroy(&m_full_cond);
pthread_mutex_destroy(&m_mutex);
#endif
}

//Will block the thread if another has already locked ---------------------
// Will block the thread if another has already locked
void push(T value)
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Wait for the mutex availability or non-fullness */
std::unique_lock<std::mutex> uni_lock(m_mutex);
m_full_cond.wait(uni_lock, [&]{return m_count < CAPACITY; });
#elif defined HAVE_PTHREAD_H
pthread_mutex_lock(&m_mutex);
/* If queue is full, wait on the "full" cond var. */
m_pushers++;
while (m_count == CAPACITY)
pthread_cond_wait(&m_full_cond, &m_mutex);
m_pushers--;
#endif

do_push(value); /* Push value */

#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Release lock and notify empty condition var (in that order) */
uni_lock.unlock();
m_empty_cond.notify_one();
#elif 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);
#endif
}

//Will not block if another has already locked ----------------------------
// Will not block if another has already locked
bool try_push(T value)
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
if (m_count == CAPACITY)
return false;
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Same as Push(), except .... */
std::unique_lock<std::mutex> uni_lock(m_mutex, std::try_to_lock);
/* Bail on fail try_lock fail */
@@ -211,84 +129,48 @@ public:
uni_lock.unlock();
return false;
}
#elif defined HAVE_PTHREAD_H
/* Bail on fail try_lock */
if (pthread_mutex_trylock(&m_mutex))
return false;
/* Bail on max CAPACITY */
#else
if (m_count == CAPACITY)
{
pthread_mutex_unlock(&m_mutex);
return false;
}
#endif

do_push(value); /* Push value */

#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Release lock and notify empty condition var (in that order) */
uni_lock.unlock();
m_empty_cond.notify_one();
#elif 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);
#endif

return true;
}

//Will block the thread if another has already locked ---------------------
// Will block the thread if another has already locked
T pop()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
ASSERT(0, "Pop should only be used with threads. Use try_pop instead.");
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Wait for the mutex availability or non-emptiness */
std::unique_lock<std::mutex> uni_lock(m_mutex);
m_empty_cond.wait(uni_lock, [&]{return m_count > 0; });
#elif defined HAVE_PTHREAD_H
pthread_mutex_lock(&m_mutex);
/* Wait until there is something in the queue. Be careful, we
* could get woken up but another thread may have eaten the
* message in the meantime. */
m_poppers++;
while (m_count == 0)
pthread_cond_wait(&m_empty_cond, &m_mutex);
m_poppers--;
#else
ASSERT(0, "Pop should only be used with threads. Use try_pop instead.");
#endif

T ret = do_pop(); /* Pop value */

#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Release lock and notify full condition var (in that order) */
uni_lock.unlock();
m_full_cond.notify_one();
#elif 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 ret;
}

//Will not block if another has already locked ----------------------------
// Will not block if another has already locked
bool try_pop(T &ret)
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
if (m_count == 0)
return false;
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Same as Pop(), except .... */
std::unique_lock<std::mutex> uni_lock(m_mutex, std::try_to_lock);
/* Bail on fail try_lock fail */
@@ -300,37 +182,23 @@ public:
uni_lock.unlock();
return false;
}
#elif defined HAVE_PTHREAD_H
pthread_mutex_lock(&m_mutex);
#else
if (m_count == 0)
{
pthread_mutex_unlock(&m_mutex);
return false;
}
#endif

ret = do_pop(); /* Pop value */

#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
/* Release lock and notify full condition var (in that order) */
uni_lock.unlock();
m_full_cond.notify_one();
#elif 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;
}

//Inner methods for actual update -----------------------------------------
// Inner methods for actual update
private:
void do_push(T &value)
{
@@ -340,30 +208,23 @@ private:

T& do_pop()
{
size_t idx = m_start;
ptrdiff_t idx = m_start;
m_start = (m_start + 1) % CAPACITY;
m_count--;
return m_values[idx];
}

//-------------------------------------------------------------------------
private:
static size_t const CAPACITY = N;
static ptrdiff_t const CAPACITY = N;
T m_values[CAPACITY];
size_t m_start, m_count;
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
ptrdiff_t m_start, m_count;
#if LOL_FEATURE_THREADS
std::mutex m_mutex;
std::condition_variable m_empty_cond, m_full_cond;
#elif defined HAVE_PTHREAD_H
size_t m_poppers, m_pushers;
pthread_mutex_t m_mutex;
pthread_cond_t m_empty_cond, m_full_cond;
#endif
};

//Base class for threads ------------------------------------------------------
// Base class for threads
class thread_base
{
public:
@@ -373,38 +234,24 @@ public:

void Init()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
m_thread = std::thread(trampoline, this);
#elif defined HAVE_PTHREAD_H
/* Set the joinable attribute for systems who don't play nice */
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&m_thread, &attr, trampoline, this);
#endif
}

virtual ~thread_base()
{
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
# if LOL_VISUAL_STUDIO_BUG_747145_WORKAROUND
m_thread.detach();
# else
m_thread.join();
# endif
#elif defined HAVE_PTHREAD_H
pthread_join(m_thread, nullptr);
#endif
}

private:
#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
static void trampoline(thread_base *that)
{
that->m_function();
@@ -412,23 +259,12 @@ private:
ExitThread(0);
# endif
}
#else
static void *trampoline(void *data)
{
thread_base *that = (thread_base *)data;
that->m_function();
return nullptr;
}
#endif

std::function<void(void)> m_function;

#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS
/* Nothing */
#elif LOL_FEATURE_CXX11_THREADS
#if LOL_FEATURE_THREADS
std::thread m_thread;
#elif defined HAVE_PTHREAD_H
pthread_t m_thread;
#endif
};



Loading…
Cancel
Save