Home | History | Annotate | Download | only in base
      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:
     18   ConstructAndDestructLogger() {
     19     constructed_seq_.GetNext();
     20   }
     21   ~ConstructAndDestructLogger() {
     22     destructed_seq_.GetNext();
     23   }
     24 };
     25 
     26 class 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 
     40 int SlowConstructor::constructed = 0;
     41 
     42 class SlowDelegate : public base::DelegateSimpleThread::Delegate {
     43  public:
     44   explicit SlowDelegate(base::LazyInstance<SlowConstructor>* lazy)
     45       : lazy_(lazy) {}
     46 
     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 
     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 
     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