lazy_instance_unittest.cc revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
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 11namespace { 12 13base::AtomicSequenceNumber constructed_seq_(base::LINKER_INITIALIZED); 14base::AtomicSequenceNumber destructed_seq_(base::LINKER_INITIALIZED); 15 16class ConstructAndDestructLogger { 17 public: 18 ConstructAndDestructLogger() { 19 constructed_seq_.GetNext(); 20 } 21 ~ConstructAndDestructLogger() { 22 destructed_seq_.GetNext(); 23 } 24}; 25 26class 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 40int SlowConstructor::constructed = 0; 41 42class 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 58static base::LazyInstance<ConstructAndDestructLogger> lazy_logger( 59 base::LINKER_INITIALIZED); 60 61TEST(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 80static base::LazyInstance<SlowConstructor> lazy_slow(base::LINKER_INITIALIZED); 81 82TEST(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