From 144cb0df31c8f850df0029f6303651b34d0da7b2 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Mon, 27 Apr 2015 22:26:14 +0000 Subject: [PATCH] sys: get rid of pthreads. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- build/lol-build | 2 +- build/msbuild/lol.vars.props | 1 - configure.ac | 2 +- src/lol/base/features.h | 4 - src/platform/nacl/opengl_context.cpp | 1 - src/platform/nacl/opengl_context.h | 1 - src/sys/threadbase.h | 242 +++++---------------------- 7 files changed, 41 insertions(+), 212 deletions(-) diff --git a/build/lol-build b/build/lol-build index 0a3eca5b..0c86fd4d 100755 --- a/build/lol-build +++ b/build/lol-build @@ -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" diff --git a/build/msbuild/lol.vars.props b/build/msbuild/lol.vars.props index 81e392f1..bdc6007e 100644 --- a/build/msbuild/lol.vars.props +++ b/build/msbuild/lol.vars.props @@ -98,7 +98,6 @@ HAVE_STDIO_H; - HAVE_PTHREAD_H; $(OrbisDefines) diff --git a/configure.ac b/configure.ac index 9231a177..70e6877b 100644 --- a/configure.ac +++ b/configure.ac @@ -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) diff --git a/src/lol/base/features.h b/src/lol/base/features.h index cbedf50b..05d096a5 100644 --- a/src/lol/base/features.h +++ b/src/lol/base/features.h @@ -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__ diff --git a/src/platform/nacl/opengl_context.cpp b/src/platform/nacl/opengl_context.cpp index 88c23277..e6e6f821 100644 --- a/src/platform/nacl/opengl_context.cpp +++ b/src/platform/nacl/opengl_context.cpp @@ -4,7 +4,6 @@ #include -#include #include #include diff --git a/src/platform/nacl/opengl_context.h b/src/platform/nacl/opengl_context.h index abffd7a6..0d01a392 100644 --- a/src/platform/nacl/opengl_context.h +++ b/src/platform/nacl/opengl_context.h @@ -11,7 +11,6 @@ /// #include -#include #include #include diff --git a/src/sys/threadbase.h b/src/sys/threadbase.h index 6307184a..3533a814 100644 --- a/src/sys/threadbase.h +++ b/src/sys/threadbase.h @@ -18,16 +18,12 @@ // ----------------------------------- // -#if !defined(LOL_FEATURE_THREADS) || !LOL_FEATURE_THREADS -/* Nothing */ -#elif LOL_FEATURE_CXX11_THREADS +#if LOL_FEATURE_THREADS # include # include # include -#elif defined HAVE_PTHREAD_H -# include #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 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 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 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 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 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 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 };