Skip to content

Commit 652e838

Browse files
committed
allow pthread_join after thread has finished execution
1 parent 1a21781 commit 652e838

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

inst/include/tthread/tinythread.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ class thread {
492492
/// Default constructor.
493493
/// Construct a @c thread object without an associated thread of execution
494494
/// (i.e. non-joinable).
495-
thread() : mHandle(0), mNotAThread(true)
495+
thread() : mHandle(0), mJoinable(false)
496496
#if defined(_TTHREAD_WIN32_)
497497
, mWin32ThreadID(0)
498498
#endif
@@ -554,7 +554,7 @@ class thread {
554554
private:
555555
native_handle_type mHandle; ///< Thread handle.
556556
mutable mutex mDataMutex; ///< Serializer for access to the thread private data.
557-
bool mNotAThread; ///< True if this object is not a thread of execution.
557+
bool mJoinable; ///< Is the thread joinable?
558558
#if defined(_TTHREAD_WIN32_)
559559
unsigned int mWin32ThreadID; ///< Unique thread ID (filled out by _beginthreadex).
560560
#endif
@@ -871,11 +871,16 @@ inline void * thread::wrapper_function(void * aArg)
871871

872872
// The thread is no longer executing
873873
lock_guard<mutex> guard(ti->mThread->mDataMutex);
874-
ti->mThread->mNotAThread = true;
875874

875+
// On Linux, we allow the thread to be joined even after execution has finished.
876+
// This is necessary to ensure that thread-local memory can be cleaned up.
877+
//
876878
// The thread is responsible for freeing the startup information
877-
delete ti;
879+
#if defined(_TTHREAD_WIN32_)
880+
ti->mThread->mJoinable = false;
881+
#endif
878882

883+
delete ti;
879884
return 0;
880885
}
881886

@@ -891,8 +896,8 @@ inline thread::thread(void (*aFunction)(void *), void * aArg)
891896
ti->mArg = aArg;
892897
ti->mThread = this;
893898

894-
// The thread is now alive
895-
mNotAThread = false;
899+
// Mark thread as joinable
900+
mJoinable = true;
896901

897902
// Create the thread
898903
#if defined(_TTHREAD_WIN32_)
@@ -905,9 +910,10 @@ inline thread::thread(void (*aFunction)(void *), void * aArg)
905910
// Did we fail to create the thread?
906911
if(!mHandle)
907912
{
908-
mNotAThread = true;
913+
mJoinable = false;
909914
delete ti;
910915
}
916+
911917
}
912918

913919
inline thread::~thread()
@@ -926,28 +932,31 @@ inline void thread::join()
926932
#elif defined(_TTHREAD_POSIX_)
927933
pthread_join(mHandle, NULL);
928934
#endif
935+
mJoinable = false;
929936
}
930937
}
931938

932939
inline bool thread::joinable() const
933940
{
934941
mDataMutex.lock();
935-
bool result = !mNotAThread;
942+
bool result = mJoinable;
936943
mDataMutex.unlock();
937944
return result;
938945
}
939946

940947
inline void thread::detach()
941948
{
949+
// TODO: Attempting to detach a non-joinable thread should throw.
950+
// https://en.cppreference.com/w/cpp/thread/thread/detach
942951
mDataMutex.lock();
943-
if(!mNotAThread)
952+
if(mJoinable)
944953
{
945954
#if defined(_TTHREAD_WIN32_)
946955
CloseHandle(mHandle);
947956
#elif defined(_TTHREAD_POSIX_)
948957
pthread_detach(mHandle);
949958
#endif
950-
mNotAThread = true;
959+
mJoinable = false;
951960
}
952961
mDataMutex.unlock();
953962
}

0 commit comments

Comments
 (0)