• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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