From 3f7333b9ed377f5baf3d9e798eee57ac41cba5fb Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 2 Oct 2010 20:20:59 -0300 Subject: [PATCH] Fix pthread implementation of base::thread class (problems joining threads, initializing m_id field, etc.). --- src/base/thread.cpp | 43 ++++++++++++++++++++++-------------- src/base/thread.h | 12 +++------- src/base/thread_unittest.cpp | 28 +++++++++++++++++------ 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/base/thread.cpp b/src/base/thread.cpp index be49d3e32..d015248d5 100644 --- a/src/base/thread.cpp +++ b/src/base/thread.cpp @@ -39,7 +39,7 @@ namespace { base::thread::thread() : m_native_handle(NULL) - , m_id() + , m_id(this_thread::get_id()) { } @@ -47,15 +47,11 @@ base::thread::~thread() { if (joinable()) detach(); - -#ifdef USE_PTHREADS - delete (pthread_t*)m_native_handle; -#endif } bool base::thread::joinable() const { - return (m_id != this_thread::get_id()); + return (m_id != 0 && m_id != this_thread::get_id()); } void base::thread::join() @@ -64,7 +60,7 @@ void base::thread::join() #ifdef WIN32 ::WaitForSingleObject(m_native_handle, INFINITE); #else - ::pthread_join(*(pthread_t*)m_native_handle, NULL); + ::pthread_join(m_id.m_native_id, NULL); #endif detach(); } @@ -75,32 +71,47 @@ void base::thread::detach() if (joinable()) { #ifdef WIN32 ::CloseHandle(m_native_handle); -#else - ::pthread_detach(*(pthread_t*)m_native_handle); - delete (pthread_t*)m_native_handle; -#endif m_native_handle = NULL; +#else + ::pthread_detach(m_id.m_native_id); +#endif m_id = id(); } } +base::thread::id base::thread::get_id() const +{ + return m_id; +} + +base::thread::native_handle_type base::thread::native_handle() +{ +#ifdef WIN32 + return (native_handle_type)m_native_handle; +#else + return (native_handle_type)m_id.m_native_id; +#endif +} + void base::thread::launch_thread(func_wrapper* f) { + m_native_handle = NULL; + m_id = id(); + #ifdef WIN32 DWORD native_id; m_native_handle = ::CreateThread(NULL, 0, win32_thread_proxy, (LPVOID)f, CREATE_SUSPENDED, &native_id); - m_id.m_native_id = native_id; + m_id = id((unsigned int)native_id); + ResumeThread(m_native_handle); #else pthread_t thread; - if (::pthread_create(&thread, NULL, pthread_thread_proxy, f)) - m_native_handle = new pthread_t(thread); - else - m_native_handle = NULL; + if (::pthread_create(&thread, NULL, pthread_thread_proxy, f) == 0) + m_id = id((unsigned int)thread); #endif } diff --git a/src/base/thread.h b/src/base/thread.h index b3a3c49cb..555b8cf25 100644 --- a/src/base/thread.h +++ b/src/base/thread.h @@ -28,8 +28,7 @@ namespace base { // Based on C++0x threads lib bool operator> (const id& y) const { return m_native_id > y.m_native_id; } bool operator>=(const id& y) const { return m_native_id >= y.m_native_id; } - // TODO should we replace this with support for iostreams? - //unsigned get_native_id() { return m_native_id; } + id& operator=(const id& y) { m_native_id = y.m_native_id; } }; typedef void* native_handle_type; @@ -63,13 +62,8 @@ namespace base { // Based on C++0x threads lib void join(); void detach(); - id get_id() const { - return m_id; - } - - native_handle_type native_handle() { - return m_native_handle; - } + id get_id() const; + native_handle_type native_handle(); class details { public: diff --git a/src/base/thread_unittest.cpp b/src/base/thread_unittest.cpp index 5282d4c1c..2e23bb065 100644 --- a/src/base/thread_unittest.cpp +++ b/src/base/thread_unittest.cpp @@ -8,23 +8,37 @@ #include "base/thread.h" -#include - -using std::cout; using namespace base; -static bool flag = false; +void nothing() { } -static void func0() { +TEST(Thread, NotJoinable) +{ + thread t; + EXPECT_FALSE(t.joinable()); +} + +TEST(Thread, Joinable) +{ + thread t(¬hing); + EXPECT_TRUE(t.joinable()); + t.join(); +} + +////////////////////////////////////////////////////////////////////// + +bool flag = false; + +void func0() { flag = true; } -static void func1(int x) { +void func1(int x) { flag = true; EXPECT_EQ(2, x); } -static void func2(int x, int y) { +void func2(int x, int y) { flag = true; EXPECT_EQ(2, x); EXPECT_EQ(4, y);