Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/base/internal/thread_identity.h"
00016
00017 #include <thread>
00018 #include <vector>
00019
00020 #include "gtest/gtest.h"
00021 #include "absl/base/attributes.h"
00022 #include "absl/base/internal/spinlock.h"
00023 #include "absl/base/macros.h"
00024 #include "absl/synchronization/internal/per_thread_sem.h"
00025 #include "absl/synchronization/mutex.h"
00026
00027 namespace absl {
00028 namespace base_internal {
00029 namespace {
00030
00031
00032 static absl::base_internal::SpinLock map_lock(
00033 absl::base_internal::kLinkerInitialized);
00034 static int num_identities_reused;
00035
00036 static const void* const kCheckNoIdentity = reinterpret_cast<void*>(1);
00037
00038 static void TestThreadIdentityCurrent(const void* assert_no_identity) {
00039 ThreadIdentity* identity;
00040
00041
00042
00043
00044 if (assert_no_identity == kCheckNoIdentity) {
00045 identity = CurrentThreadIdentityIfPresent();
00046 EXPECT_TRUE(identity == nullptr);
00047 }
00048
00049 identity = synchronization_internal::GetOrCreateCurrentThreadIdentity();
00050 EXPECT_TRUE(identity != nullptr);
00051 ThreadIdentity* identity_no_init;
00052 identity_no_init = CurrentThreadIdentityIfPresent();
00053 EXPECT_TRUE(identity == identity_no_init);
00054
00055
00056 EXPECT_EQ(0, reinterpret_cast<intptr_t>(&identity->per_thread_synch) %
00057 PerThreadSynch::kAlignment);
00058 EXPECT_EQ(identity, identity->per_thread_synch.thread_identity());
00059
00060 absl::base_internal::SpinLockHolder l(&map_lock);
00061 num_identities_reused++;
00062 }
00063
00064 TEST(ThreadIdentityTest, BasicIdentityWorks) {
00065
00066 TestThreadIdentityCurrent(nullptr);
00067 }
00068
00069 TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
00070
00071
00072
00073
00074
00075
00076 static const int kNumLoops = 3;
00077 static const int kNumThreads = 400;
00078 for (int iter = 0; iter < kNumLoops; iter++) {
00079 std::vector<std::thread> threads;
00080 for (int i = 0; i < kNumThreads; ++i) {
00081 threads.push_back(
00082 std::thread(TestThreadIdentityCurrent, kCheckNoIdentity));
00083 }
00084 for (auto& thread : threads) {
00085 thread.join();
00086 }
00087 }
00088
00089
00090
00091
00092 EXPECT_LT(kNumThreads, num_identities_reused);
00093 }
00094
00095 TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) {
00096
00097
00098
00099
00100
00101 static const int kNumLoops = 10;
00102 static const int kNumThreads = 12;
00103 static const int kNumMutexes = 3;
00104 static const int kNumLockLoops = 5;
00105
00106 Mutex mutexes[kNumMutexes];
00107 for (int iter = 0; iter < kNumLoops; ++iter) {
00108 std::vector<std::thread> threads;
00109 for (int thread = 0; thread < kNumThreads; ++thread) {
00110 threads.push_back(std::thread([&]() {
00111 for (int l = 0; l < kNumLockLoops; ++l) {
00112 for (int m = 0; m < kNumMutexes; ++m) {
00113 MutexLock lock(&mutexes[m]);
00114 }
00115 }
00116 }));
00117 }
00118 for (auto& thread : threads) {
00119 thread.join();
00120 }
00121 }
00122 }
00123
00124 }
00125 }
00126 }