thread_local_unittest.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "butil/logging.h"
  5. #include "butil/threading/simple_thread.h"
  6. #include "butil/threading/thread_local.h"
  7. #include "butil/synchronization/waitable_event.h"
  8. #include <gtest/gtest.h>
  9. namespace butil {
  10. namespace {
  11. class ThreadLocalTesterBase : public butil::DelegateSimpleThreadPool::Delegate {
  12. public:
  13. typedef butil::ThreadLocalPointer<ThreadLocalTesterBase> TLPType;
  14. ThreadLocalTesterBase(TLPType* tlp, butil::WaitableEvent* done)
  15. : tlp_(tlp),
  16. done_(done) {
  17. }
  18. virtual ~ThreadLocalTesterBase() {}
  19. protected:
  20. TLPType* tlp_;
  21. butil::WaitableEvent* done_;
  22. };
  23. class SetThreadLocal : public ThreadLocalTesterBase {
  24. public:
  25. SetThreadLocal(TLPType* tlp, butil::WaitableEvent* done)
  26. : ThreadLocalTesterBase(tlp, done),
  27. val_(NULL) {
  28. }
  29. virtual ~SetThreadLocal() {}
  30. void set_value(ThreadLocalTesterBase* val) { val_ = val; }
  31. virtual void Run() OVERRIDE {
  32. DCHECK(!done_->IsSignaled());
  33. tlp_->Set(val_);
  34. done_->Signal();
  35. }
  36. private:
  37. ThreadLocalTesterBase* val_;
  38. };
  39. class GetThreadLocal : public ThreadLocalTesterBase {
  40. public:
  41. GetThreadLocal(TLPType* tlp, butil::WaitableEvent* done)
  42. : ThreadLocalTesterBase(tlp, done),
  43. ptr_(NULL) {
  44. }
  45. virtual ~GetThreadLocal() {}
  46. void set_ptr(ThreadLocalTesterBase** ptr) { ptr_ = ptr; }
  47. virtual void Run() OVERRIDE {
  48. DCHECK(!done_->IsSignaled());
  49. *ptr_ = tlp_->Get();
  50. done_->Signal();
  51. }
  52. private:
  53. ThreadLocalTesterBase** ptr_;
  54. };
  55. } // namespace
  56. // In this test, we start 2 threads which will access a ThreadLocalPointer. We
  57. // make sure the default is NULL, and the pointers are unique to the threads.
  58. TEST(ThreadLocalTest, Pointer) {
  59. butil::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
  60. butil::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
  61. tp1.Start();
  62. tp2.Start();
  63. butil::ThreadLocalPointer<ThreadLocalTesterBase> tlp;
  64. static ThreadLocalTesterBase* const kBogusPointer =
  65. reinterpret_cast<ThreadLocalTesterBase*>(0x1234);
  66. ThreadLocalTesterBase* tls_val;
  67. butil::WaitableEvent done(true, false);
  68. GetThreadLocal getter(&tlp, &done);
  69. getter.set_ptr(&tls_val);
  70. // Check that both threads defaulted to NULL.
  71. tls_val = kBogusPointer;
  72. done.Reset();
  73. tp1.AddWork(&getter);
  74. done.Wait();
  75. EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
  76. tls_val = kBogusPointer;
  77. done.Reset();
  78. tp2.AddWork(&getter);
  79. done.Wait();
  80. EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
  81. SetThreadLocal setter(&tlp, &done);
  82. setter.set_value(kBogusPointer);
  83. // Have thread 1 set their pointer value to kBogusPointer.
  84. done.Reset();
  85. tp1.AddWork(&setter);
  86. done.Wait();
  87. tls_val = NULL;
  88. done.Reset();
  89. tp1.AddWork(&getter);
  90. done.Wait();
  91. EXPECT_EQ(kBogusPointer, tls_val);
  92. // Make sure thread 2 is still NULL
  93. tls_val = kBogusPointer;
  94. done.Reset();
  95. tp2.AddWork(&getter);
  96. done.Wait();
  97. EXPECT_EQ(static_cast<ThreadLocalTesterBase*>(NULL), tls_val);
  98. // Set thread 2 to kBogusPointer + 1.
  99. setter.set_value(kBogusPointer + 1);
  100. done.Reset();
  101. tp2.AddWork(&setter);
  102. done.Wait();
  103. tls_val = NULL;
  104. done.Reset();
  105. tp2.AddWork(&getter);
  106. done.Wait();
  107. EXPECT_EQ(kBogusPointer + 1, tls_val);
  108. // Make sure thread 1 is still kBogusPointer.
  109. tls_val = NULL;
  110. done.Reset();
  111. tp1.AddWork(&getter);
  112. done.Wait();
  113. EXPECT_EQ(kBogusPointer, tls_val);
  114. tp1.JoinAll();
  115. tp2.JoinAll();
  116. }
  117. TEST(ThreadLocalTest, Boolean) {
  118. {
  119. butil::ThreadLocalBoolean tlb;
  120. EXPECT_FALSE(tlb.Get());
  121. tlb.Set(false);
  122. EXPECT_FALSE(tlb.Get());
  123. tlb.Set(true);
  124. EXPECT_TRUE(tlb.Get());
  125. }
  126. // Our slot should have been freed, we're all reset.
  127. {
  128. butil::ThreadLocalBoolean tlb;
  129. EXPECT_FALSE(tlb.Get());
  130. }
  131. }
  132. } // namespace butil