@@ -492,7 +492,7 @@ class thread {
492
492
// / Default constructor.
493
493
// / Construct a @c thread object without an associated thread of execution
494
494
// / (i.e. non-joinable).
495
- thread () : mHandle (0 ), mNotAThread ( true )
495
+ thread () : mHandle (0 ), mJoinable ( false )
496
496
#if defined(_TTHREAD_WIN32_)
497
497
, mWin32ThreadID (0 )
498
498
#endif
@@ -554,7 +554,7 @@ class thread {
554
554
private:
555
555
native_handle_type mHandle ; // /< Thread handle.
556
556
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?
558
558
#if defined(_TTHREAD_WIN32_)
559
559
unsigned int mWin32ThreadID ; // /< Unique thread ID (filled out by _beginthreadex).
560
560
#endif
@@ -871,11 +871,16 @@ inline void * thread::wrapper_function(void * aArg)
871
871
872
872
// The thread is no longer executing
873
873
lock_guard<mutex> guard (ti->mThread ->mDataMutex );
874
- ti->mThread ->mNotAThread = true ;
875
874
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
+ //
876
878
// The thread is responsible for freeing the startup information
877
- delete ti;
879
+ #if defined(_TTHREAD_WIN32_)
880
+ ti->mThread ->mJoinable = false ;
881
+ #endif
878
882
883
+ delete ti;
879
884
return 0 ;
880
885
}
881
886
@@ -891,8 +896,8 @@ inline thread::thread(void (*aFunction)(void *), void * aArg)
891
896
ti->mArg = aArg;
892
897
ti->mThread = this ;
893
898
894
- // The thread is now alive
895
- mNotAThread = false ;
899
+ // Mark thread as joinable
900
+ mJoinable = true ;
896
901
897
902
// Create the thread
898
903
#if defined(_TTHREAD_WIN32_)
@@ -905,9 +910,10 @@ inline thread::thread(void (*aFunction)(void *), void * aArg)
905
910
// Did we fail to create the thread?
906
911
if (!mHandle )
907
912
{
908
- mNotAThread = true ;
913
+ mJoinable = false ;
909
914
delete ti;
910
915
}
916
+
911
917
}
912
918
913
919
inline thread::~thread ()
@@ -926,28 +932,31 @@ inline void thread::join()
926
932
#elif defined(_TTHREAD_POSIX_)
927
933
pthread_join (mHandle , NULL );
928
934
#endif
935
+ mJoinable = false ;
929
936
}
930
937
}
931
938
932
939
inline bool thread::joinable () const
933
940
{
934
941
mDataMutex .lock ();
935
- bool result = ! mNotAThread ;
942
+ bool result = mJoinable ;
936
943
mDataMutex .unlock ();
937
944
return result;
938
945
}
939
946
940
947
inline void thread::detach ()
941
948
{
949
+ // TODO: Attempting to detach a non-joinable thread should throw.
950
+ // https://en.cppreference.com/w/cpp/thread/thread/detach
942
951
mDataMutex .lock ();
943
- if (! mNotAThread )
952
+ if (mJoinable )
944
953
{
945
954
#if defined(_TTHREAD_WIN32_)
946
955
CloseHandle (mHandle );
947
956
#elif defined(_TTHREAD_POSIX_)
948
957
pthread_detach (mHandle );
949
958
#endif
950
- mNotAThread = true ;
959
+ mJoinable = false ;
951
960
}
952
961
mDataMutex .unlock ();
953
962
}
0 commit comments