blob: 17313818ebb064f89d92b26eee3d949a0851aa76 [file] [log] [blame]
[email protected]30039e62008-09-08 14:11:131// 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
[email protected]30039e62008-09-08 14:11:1313base::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:
[email protected]2fdc86a2010-01-26 23:08:0244 explicit SlowDelegate(base::LazyInstance<SlowConstructor>* lazy)
45 : lazy_(lazy) {}
46
[email protected]30039e62008-09-08 14:11:1347 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 {
[email protected]4ea927b2009-11-19 09:11:3963 base::ShadowingAtExitManager shadow;
[email protected]30039e62008-09-08 14:11:1364
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());
[email protected]52a261f2009-03-03 15:01:1275 }
[email protected]30039e62008-09-08 14:11:1376 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 {
[email protected]4ea927b2009-11-19 09:11:3984 base::ShadowingAtExitManager shadow;
[email protected]30039e62008-09-08 14:11:1385
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}
[email protected]dcc69332010-10-21 20:41:4798
99namespace {
100
101// DeleteLogger is an object which sets a flag when it's destroyed.
102// It accepts a bool* and sets the bool to true when the dtor runs.
103class DeleteLogger {
104 public:
105 DeleteLogger() : deleted_(NULL) {}
106 ~DeleteLogger() { *deleted_ = true; }
107
108 void SetDeletedPtr(bool* deleted) {
109 deleted_ = deleted;
110 }
111
112 private:
113 bool* deleted_;
114};
115
116} // anonymous namespace
117
118TEST(LazyInstanceTest, LeakyLazyInstance) {
119 // Check that using a plain LazyInstance causes the dtor to run
120 // when the AtExitManager finishes.
121 bool deleted1 = false;
122 {
123 base::ShadowingAtExitManager shadow;
124 static base::LazyInstance<DeleteLogger> test(base::LINKER_INITIALIZED);
125 test.Get().SetDeletedPtr(&deleted1);
126 }
127 EXPECT_TRUE(deleted1);
128
129 // Check that using a *leaky* LazyInstance makes the dtor not run
130 // when the AtExitManager finishes.
131 bool deleted2 = false;
132 {
133 base::ShadowingAtExitManager shadow;
134 static base::LazyInstance<DeleteLogger,
135 base::LeakyLazyInstanceTraits<DeleteLogger> >
136 test(base::LINKER_INITIALIZED);
137 test.Get().SetDeletedPtr(&deleted2);
138 }
139 EXPECT_FALSE(deleted2);
140}