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.
5 #include "base/at_exit.h"
6 #include "base/atomic_sequence_num.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/aligned_memory.h"
9 #include "base/threading/simple_thread.h"
10 #include "testing/gtest/include/gtest/gtest.h"
14 base::StaticAtomicSequenceNumber constructed_seq_
;
15 base::StaticAtomicSequenceNumber destructed_seq_
;
17 class ConstructAndDestructLogger
{
19 ConstructAndDestructLogger() {
20 constructed_seq_
.GetNext();
22 ~ConstructAndDestructLogger() {
23 destructed_seq_
.GetNext();
27 class SlowConstructor
{
29 SlowConstructor() : some_int_(0) {
30 // Sleep for 1 second to try to cause a race.
31 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
35 int some_int() const { return some_int_
; }
37 static int constructed
;
42 int SlowConstructor::constructed
= 0;
44 class SlowDelegate
: public base::DelegateSimpleThread::Delegate
{
46 explicit SlowDelegate(base::LazyInstance
<SlowConstructor
>* lazy
)
49 virtual void Run() override
{
50 EXPECT_EQ(12, lazy_
->Get().some_int());
51 EXPECT_EQ(12, lazy_
->Pointer()->some_int());
55 base::LazyInstance
<SlowConstructor
>* lazy_
;
60 static base::LazyInstance
<ConstructAndDestructLogger
> lazy_logger
=
61 LAZY_INSTANCE_INITIALIZER
;
63 TEST(LazyInstanceTest
, Basic
) {
65 base::ShadowingAtExitManager shadow
;
67 EXPECT_EQ(0, constructed_seq_
.GetNext());
68 EXPECT_EQ(0, destructed_seq_
.GetNext());
71 EXPECT_EQ(2, constructed_seq_
.GetNext());
72 EXPECT_EQ(1, destructed_seq_
.GetNext());
74 lazy_logger
.Pointer();
75 EXPECT_EQ(3, constructed_seq_
.GetNext());
76 EXPECT_EQ(2, destructed_seq_
.GetNext());
78 EXPECT_EQ(4, constructed_seq_
.GetNext());
79 EXPECT_EQ(4, destructed_seq_
.GetNext());
82 static base::LazyInstance
<SlowConstructor
> lazy_slow
=
83 LAZY_INSTANCE_INITIALIZER
;
85 TEST(LazyInstanceTest
, ConstructorThreadSafety
) {
87 base::ShadowingAtExitManager shadow
;
89 SlowDelegate
delegate(&lazy_slow
);
90 EXPECT_EQ(0, SlowConstructor::constructed
);
92 base::DelegateSimpleThreadPool
pool("lazy_instance_cons", 5);
93 pool
.AddWork(&delegate
, 20);
94 EXPECT_EQ(0, SlowConstructor::constructed
);
98 EXPECT_EQ(1, SlowConstructor::constructed
);
104 // DeleteLogger is an object which sets a flag when it's destroyed.
105 // It accepts a bool* and sets the bool to true when the dtor runs.
108 DeleteLogger() : deleted_(NULL
) {}
109 ~DeleteLogger() { *deleted_
= true; }
111 void SetDeletedPtr(bool* deleted
) {
119 } // anonymous namespace
121 TEST(LazyInstanceTest
, LeakyLazyInstance
) {
122 // Check that using a plain LazyInstance causes the dtor to run
123 // when the AtExitManager finishes.
124 bool deleted1
= false;
126 base::ShadowingAtExitManager shadow
;
127 static base::LazyInstance
<DeleteLogger
> test
= LAZY_INSTANCE_INITIALIZER
;
128 test
.Get().SetDeletedPtr(&deleted1
);
130 EXPECT_TRUE(deleted1
);
132 // Check that using a *leaky* LazyInstance makes the dtor not run
133 // when the AtExitManager finishes.
134 bool deleted2
= false;
136 base::ShadowingAtExitManager shadow
;
137 static base::LazyInstance
<DeleteLogger
>::Leaky
138 test
= LAZY_INSTANCE_INITIALIZER
;
139 test
.Get().SetDeletedPtr(&deleted2
);
141 EXPECT_FALSE(deleted2
);
146 template <size_t alignment
>
151 base::AlignedMemory
<alignment
, alignment
> data_
;
154 } // anonymous namespace
156 #define EXPECT_ALIGNED(ptr, align) \
157 EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
159 TEST(LazyInstanceTest
, Alignment
) {
160 using base::LazyInstance
;
162 // Create some static instances with increasing sizes and alignment
163 // requirements. By ordering this way, the linker will need to do some work to
164 // ensure proper alignment of the static data.
165 static LazyInstance
<AlignedData
<4> > align4
= LAZY_INSTANCE_INITIALIZER
;
166 static LazyInstance
<AlignedData
<32> > align32
= LAZY_INSTANCE_INITIALIZER
;
167 static LazyInstance
<AlignedData
<4096> > align4096
= LAZY_INSTANCE_INITIALIZER
;
169 EXPECT_ALIGNED(align4
.Pointer(), 4);
170 EXPECT_ALIGNED(align32
.Pointer(), 32);
171 EXPECT_ALIGNED(align4096
.Pointer(), 4096);