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:
ConstructAndDestructLogger()18 ConstructAndDestructLogger() {
19 constructed_seq_.GetNext();
20 }
~ConstructAndDestructLogger()21 ~ConstructAndDestructLogger() {
22 destructed_seq_.GetNext();
23 }
24 };
25
26 class SlowConstructor {
27 public:
SlowConstructor()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 }
some_int() const33 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:
SlowDelegate(base::LazyInstance<SlowConstructor> * lazy)44 explicit SlowDelegate(base::LazyInstance<SlowConstructor>* lazy)
45 : lazy_(lazy) {}
46
Run()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
TEST(LazyInstanceTest,Basic)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
TEST(LazyInstanceTest,ConstructorThreadSafety)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