1 // Copyright (c) 2011 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/lazy_instance.h" 6 7 #include "base/at_exit.h" 8 #include "base/atomicops.h" 9 #include "base/threading/platform_thread.h" 10 11 namespace base { 12 namespace internal { 13 14 // TODO(joth): This function could be shared with Singleton, in place of its 15 // WaitForInstance() call. 16 bool NeedsLazyInstance(subtle::AtomicWord* state) { 17 // Try to create the instance, if we're the first, will go from 0 to 18 // kLazyInstanceStateCreating, otherwise we've already been beaten here. 19 // The memory access has no memory ordering as state 0 and 20 // kLazyInstanceStateCreating have no associated data (memory barriers are 21 // all about ordering of memory accesses to *associated* data). 22 if (subtle::NoBarrier_CompareAndSwap(state, 0, 23 kLazyInstanceStateCreating) == 0) 24 // Caller must create instance 25 return true; 26 27 // It's either in the process of being created, or already created. Spin. 28 // The load has acquire memory ordering as a thread which sees 29 // state_ == STATE_CREATED needs to acquire visibility over 30 // the associated data (buf_). Pairing Release_Store is in 31 // CompleteLazyInstance(). 32 while (subtle::Acquire_Load(state) == kLazyInstanceStateCreating) { 33 PlatformThread::YieldCurrentThread(); 34 } 35 // Someone else created the instance. 36 return false; 37 } 38 39 void CompleteLazyInstance(subtle::AtomicWord* state, 40 subtle::AtomicWord new_instance, 41 void* lazy_instance, 42 void (*dtor)(void*)) { 43 // Instance is created, go from CREATING to CREATED. 44 // Releases visibility over private_buf_ to readers. Pairing Acquire_Load's 45 // are in NeedsInstance() and Pointer(). 46 subtle::Release_Store(state, new_instance); 47 48 // Make sure that the lazily instantiated object will get destroyed at exit. 49 if (dtor) 50 AtExitManager::RegisterCallback(dtor, lazy_instance); 51 } 52 53 } // namespace internal 54 } // namespace base 55