1 // Copyright (c) 2008 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 5 #include "base/at_exit.h" 6 #include "base/atomic_sequence_num.h" 7 #include "base/lazy_instance.h" 8 #include "base/simple_thread.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 namespace { 12 13 base::AtomicSequenceNumber constructed_seq_(base::LINKER_INITIALIZED); 14 base::AtomicSequenceNumber destructed_seq_(base::LINKER_INITIALIZED); 15 16 class ConstructAndDestructLogger { 17 public: 18 ConstructAndDestructLogger() { 19 constructed_seq_.GetNext(); 20 } 21 ~ConstructAndDestructLogger() { 22 destructed_seq_.GetNext(); 23 } 24 }; 25 26 class SlowConstructor { 27 public: 28 SlowConstructor() : some_int_(0) { 29 PlatformThread::Sleep(1000); // Sleep for 1 second to try to cause a race. 30 ++constructed; 31 some_int_ = 12; 32 } 33 int some_int() const { return some_int_; } 34 35 static int constructed; 36 private: 37 int some_int_; 38 }; 39 40 int SlowConstructor::constructed = 0; 41 42 class SlowDelegate : public base::DelegateSimpleThread::Delegate { 43 public: 44 explicit SlowDelegate(base::LazyInstance<SlowConstructor>* lazy) 45 : lazy_(lazy) {} 46 47 virtual void Run() { 48 EXPECT_EQ(12, lazy_->Get().some_int()); 49 EXPECT_EQ(12, lazy_->Pointer()->some_int()); 50 } 51 52 private: 53 base::LazyInstance<SlowConstructor>* lazy_; 54 }; 55 56 } // namespace 57 58 static base::LazyInstance<ConstructAndDestructLogger> lazy_logger( 59 base::LINKER_INITIALIZED); 60 61 TEST(LazyInstanceTest, Basic) { 62 { 63 base::ShadowingAtExitManager shadow; 64 65 EXPECT_EQ(0, constructed_seq_.GetNext()); 66 EXPECT_EQ(0, destructed_seq_.GetNext()); 67 68 lazy_logger.Get(); 69 EXPECT_EQ(2, constructed_seq_.GetNext()); 70 EXPECT_EQ(1, destructed_seq_.GetNext()); 71 72 lazy_logger.Pointer(); 73 EXPECT_EQ(3, constructed_seq_.GetNext()); 74 EXPECT_EQ(2, destructed_seq_.GetNext()); 75 } 76 EXPECT_EQ(4, constructed_seq_.GetNext()); 77 EXPECT_EQ(4, destructed_seq_.GetNext()); 78 } 79 80 static base::LazyInstance<SlowConstructor> lazy_slow(base::LINKER_INITIALIZED); 81 82 TEST(LazyInstanceTest, ConstructorThreadSafety) { 83 { 84 base::ShadowingAtExitManager shadow; 85 86 SlowDelegate delegate(&lazy_slow); 87 EXPECT_EQ(0, SlowConstructor::constructed); 88 89 base::DelegateSimpleThreadPool pool("lazy_instance_cons", 5); 90 pool.AddWork(&delegate, 20); 91 EXPECT_EQ(0, SlowConstructor::constructed); 92 93 pool.Start(); 94 pool.JoinAll(); 95 EXPECT_EQ(1, SlowConstructor::constructed); 96 } 97 } 98