@@ -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
913919inline 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
932939inline bool thread::joinable () const
933940{
934941 mDataMutex .lock ();
935- bool result = ! mNotAThread ;
942+ bool result = mJoinable ;
936943 mDataMutex .unlock ();
937944 return result;
938945}
939946
940947inline 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