@ -289,36 +289,61 @@ void* ThreadFunc(void* data) {
}
TEST ( GetThreadCountTest , ReturnsCorrectValue ) {
const size_t starting_count = GetThreadCount ( ) ;
pthread_t thread_id ;
size_t starting_count ;
size_t thread_count_after_create ;
size_t thread_count_after_join ;
// We can't guarantee that no other thread was created or destroyed between
// any two calls to GetThreadCount(). We make multiple attempts, hoping that
// background noise is not constant and we would see the "right" values at
// some point.
for ( int attempt = 0 ; attempt < 20 ; + + attempt ) {
starting_count = GetThreadCount ( ) ;
pthread_t thread_id ;
internal : : Mutex mutex ;
{
internal : : MutexLock lock ( & mutex ) ;
pthread_attr_t attr ;
ASSERT_EQ ( 0 , pthread_attr_init ( & attr ) ) ;
ASSERT_EQ ( 0 , pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_JOINABLE ) ) ;
const int status = pthread_create ( & thread_id , & attr , & ThreadFunc , & mutex ) ;
ASSERT_EQ ( 0 , pthread_attr_destroy ( & attr ) ) ;
ASSERT_EQ ( 0 , status ) ;
}
internal : : Mutex mutex ;
{
internal : : MutexLock lock ( & mutex ) ;
pthread_attr_t attr ;
ASSERT_EQ ( 0 , pthread_attr_init ( & attr ) ) ;
ASSERT_EQ ( 0 , pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_JOINABLE ) ) ;
const int status = pthread_create ( & thread_id , & attr , & ThreadFunc , & mutex ) ;
ASSERT_EQ ( 0 , pthread_attr_destroy ( & attr ) ) ;
ASSERT_EQ ( 0 , status ) ;
EXPECT_EQ ( starting_count + 1 , GetThreadCount ( ) ) ;
}
thread_count_after_create = GetThreadCount ( ) ;
void * dummy ;
ASSERT_EQ ( 0 , pthread_join ( thread_id , & dummy ) ) ;
void * dummy ;
ASSERT_EQ ( 0 , pthread_join ( thread_id , & dummy ) ) ;
// The OS may not immediately report the updated thread count after
// joining a thread, causing flakiness in this test. To counter that, we
// wait for up to .5 seconds for the OS to report the correct value.
for ( int i = 0 ; i < 5 ; + + i ) {
if ( GetThreadCount ( ) = = starting_count )
break ;
// Join before we decide whether we need to retry the test. Retry if an
// arbitrary other thread was created or destroyed in the meantime.
if ( thread_count_after_create ! = starting_count + 1 ) continue ;
// The OS may not immediately report the updated thread count after
// joining a thread, causing flakiness in this test. To counter that, we
// wait for up to .5 seconds for the OS to report the correct value.
bool thread_count_matches = false ;
for ( int i = 0 ; i < 5 ; + + i ) {
thread_count_after_join = GetThreadCount ( ) ;
if ( thread_count_after_join = = starting_count ) {
thread_count_matches = true ;
break ;
}
SleepMilliseconds ( 100 ) ;
}
// Retry if an arbitrary other thread was created or destroyed.
if ( ! thread_count_matches ) continue ;
SleepMilliseconds ( 100 ) ;
break ;
}
EXPECT_EQ ( starting_count , GetThreadCount ( ) ) ;
EXPECT_EQ ( thread_count_after_create , starting_count + 1 ) ;
EXPECT_EQ ( thread_count_after_join , starting_count ) ;
}
# else
TEST ( GetThreadCountTest , ReturnsZeroWhenUnableToCountThreads ) {