1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <stddef.h>
6cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko
7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/at_exit.h"
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/atomic_sequence_num.h"
9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/lazy_instance.h"
10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/aligned_memory.h"
11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/simple_thread.h"
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "testing/gtest/include/gtest/gtest.h"
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace {
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::StaticAtomicSequenceNumber constructed_seq_;
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbase::StaticAtomicSequenceNumber destructed_seq_;
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass ConstructAndDestructLogger {
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ConstructAndDestructLogger() {
22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    constructed_seq_.GetNext();
23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~ConstructAndDestructLogger() {
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    destructed_seq_.GetNext();
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass SlowConstructor {
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  SlowConstructor() : some_int_(0) {
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Sleep for 1 second to try to cause a race.
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    ++constructed;
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    some_int_ = 12;
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int some_int() const { return some_int_; }
38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static int constructed;
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int some_int_;
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint SlowConstructor::constructed = 0;
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass SlowDelegate : public base::DelegateSimpleThread::Delegate {
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  explicit SlowDelegate(base::LazyInstance<SlowConstructor>* lazy)
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      : lazy_(lazy) {}
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void Run() override {
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(12, lazy_->Get().some_int());
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(12, lazy_->Pointer()->some_int());
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  base::LazyInstance<SlowConstructor>* lazy_;
58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic base::LazyInstance<ConstructAndDestructLogger> lazy_logger =
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    LAZY_INSTANCE_INITIALIZER;
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(LazyInstanceTest, Basic) {
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::ShadowingAtExitManager shadow;
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, constructed_seq_.GetNext());
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, destructed_seq_.GetNext());
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    lazy_logger.Get();
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(2, constructed_seq_.GetNext());
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(1, destructed_seq_.GetNext());
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    lazy_logger.Pointer();
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(3, constructed_seq_.GetNext());
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(2, destructed_seq_.GetNext());
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(4, constructed_seq_.GetNext());
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_EQ(4, destructed_seq_.GetNext());
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstatic base::LazyInstance<SlowConstructor> lazy_slow =
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    LAZY_INSTANCE_INITIALIZER;
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(LazyInstanceTest, ConstructorThreadSafety) {
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::ShadowingAtExitManager shadow;
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    SlowDelegate delegate(&lazy_slow);
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, SlowConstructor::constructed);
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::DelegateSimpleThreadPool pool("lazy_instance_cons", 5);
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    pool.AddWork(&delegate, 20);
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0, SlowConstructor::constructed);
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    pool.Start();
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    pool.JoinAll();
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(1, SlowConstructor::constructed);
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace {
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// DeleteLogger is an object which sets a flag when it's destroyed.
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// It accepts a bool* and sets the bool to true when the dtor runs.
108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass DeleteLogger {
109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DeleteLogger() : deleted_(NULL) {}
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~DeleteLogger() { *deleted_ = true; }
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void SetDeletedPtr(bool* deleted) {
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    deleted_ = deleted;
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool* deleted_;
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // anonymous namespace
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(LazyInstanceTest, LeakyLazyInstance) {
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Check that using a plain LazyInstance causes the dtor to run
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // when the AtExitManager finishes.
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool deleted1 = false;
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::ShadowingAtExitManager shadow;
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    static base::LazyInstance<DeleteLogger> test = LAZY_INSTANCE_INITIALIZER;
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    test.Get().SetDeletedPtr(&deleted1);
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_TRUE(deleted1);
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Check that using a *leaky* LazyInstance makes the dtor not run
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // when the AtExitManager finishes.
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  bool deleted2 = false;
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  {
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    base::ShadowingAtExitManager shadow;
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    static base::LazyInstance<DeleteLogger>::Leaky
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        test = LAZY_INSTANCE_INITIALIZER;
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    test.Get().SetDeletedPtr(&deleted2);
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_FALSE(deleted2);
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace {
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <size_t alignment>
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass AlignedData {
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  AlignedData() {}
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~AlignedData() {}
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  base::AlignedMemory<alignment, alignment> data_;
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // anonymous namespace
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#define EXPECT_ALIGNED(ptr, align) \
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(LazyInstanceTest, Alignment) {
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  using base::LazyInstance;
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Create some static instances with increasing sizes and alignment
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // requirements. By ordering this way, the linker will need to do some work to
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // ensure proper alignment of the static data.
167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static LazyInstance<AlignedData<4> > align4 = LAZY_INSTANCE_INITIALIZER;
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static LazyInstance<AlignedData<32> > align32 = LAZY_INSTANCE_INITIALIZER;
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  static LazyInstance<AlignedData<4096> > align4096 = LAZY_INSTANCE_INITIALIZER;
170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_ALIGNED(align4.Pointer(), 4);
172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_ALIGNED(align32.Pointer(), 32);
173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  EXPECT_ALIGNED(align4096.Pointer(), 4096);
174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
175