Bug 1071808: Remove Chromium lazy_instance from IPC code. r=nfroyd

This commit is contained in:
Josh Aas 2014-09-23 22:31:35 -05:00
parent 72edb72ad8
commit 0372b4fdd7
9 changed files with 33 additions and 291 deletions

View File

@ -42,7 +42,6 @@ UNIFIED_SOURCES += [
'src/base/file_path.cc',
'src/base/file_util.cc',
'src/base/histogram.cc',
'src/base/lazy_instance.cc',
'src/base/lock.cc',
'src/base/logging.cc',
'src/base/message_loop.cc',

View File

@ -18,7 +18,6 @@
// anyway. Remove the 0 above if we want it.
#include <gdk/gdkx.h>
#include <X11/extensions/scrnsaver.h>
#include "base/lazy_instance.h"
#include "base/thread_local.h"
#endif
@ -89,9 +88,8 @@ class IdleState {
};
bool OSIdleTimeSource(int32_t* milliseconds_interval_since_last_event) {
static LazyInstance<IdleState> state_instance = LAZY_INSTANCE_INITIALIZER;
IdleState* state = state_instance.Pointer();
int32_t idle_time = state->IdleTime();
static IdleState state;
int32_t idle_time = state.IdleTime();
if (0 < idle_time) {
*milliseconds_interval_since_last_event = idle_time;
return true;

View File

@ -1,55 +0,0 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/lazy_instance.h"
#include "base/at_exit.h"
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/platform_thread.h"
namespace base {
namespace internal {
// TODO(joth): This function could be shared with Singleton, in place of its
// WaitForInstance() call.
bool NeedsLazyInstance(subtle::AtomicWord* state) {
// Try to create the instance, if we're the first, will go from 0 to
// kLazyInstanceStateCreating, otherwise we've already been beaten here.
// The memory access has no memory ordering as state 0 and
// kLazyInstanceStateCreating have no associated data (memory barriers are
// all about ordering of memory accesses to *associated* data).
if (subtle::NoBarrier_CompareAndSwap(state, 0,
kLazyInstanceStateCreating) == 0)
// Caller must create instance
return true;
// It's either in the process of being created, or already created. Spin.
// The load has acquire memory ordering as a thread which sees
// state_ == STATE_CREATED needs to acquire visibility over
// the associated data (buf_). Pairing Release_Store is in
// CompleteLazyInstance().
while (subtle::Acquire_Load(state) == kLazyInstanceStateCreating) {
PlatformThread::YieldCurrentThread();
}
// Someone else created the instance.
return false;
}
void CompleteLazyInstance(subtle::AtomicWord* state,
subtle::AtomicWord new_instance,
void* lazy_instance,
void (*dtor)(void*)) {
// Instance is created, go from CREATING to CREATED.
// Releases visibility over private_buf_ to readers. Pairing Acquire_Load's
// are in NeedsInstance() and Pointer().
subtle::Release_Store(state, new_instance);
// Make sure that the lazily instantiated object will get destroyed at exit.
if (dtor)
AtExitManager::RegisterCallback(dtor, lazy_instance);
}
} // namespace internal
} // namespace base

View File

@ -1,195 +0,0 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// The LazyInstance<Type, Traits> class manages a single instance of Type,
// which will be lazily created on the first time it's accessed. This class is
// useful for places you would normally use a function-level static, but you
// need to have guaranteed thread-safety. The Type constructor will only ever
// be called once, even if two threads are racing to create the object. Get()
// and Pointer() will always return the same, completely initialized instance.
// When the instance is constructed it is registered with AtExitManager. The
// destructor will be called on program exit.
//
// LazyInstance is completely thread safe, assuming that you create it safely.
// The class was designed to be POD initialized, so it shouldn't require a
// static constructor. It really only makes sense to declare a LazyInstance as
// a global variable using the LAZY_INSTANCE_INITIALIZER initializer.
//
// LazyInstance is similar to Singleton, except it does not have the singleton
// property. You can have multiple LazyInstance's of the same type, and each
// will manage a unique instance. It also preallocates the space for Type, as
// to avoid allocating the Type instance on the heap. This may help with the
// performance of creating the instance, and reducing heap fragmentation. This
// requires that Type be a complete type so we can determine the size.
//
// Example usage:
// static LazyInstance<MyClass> my_instance = LAZY_INSTANCE_INITIALIZER;
// void SomeMethod() {
// my_instance.Get().SomeMethod(); // MyClass::SomeMethod()
//
// MyClass* ptr = my_instance.Pointer();
// ptr->DoDoDo(); // MyClass::DoDoDo
// }
#ifndef BASE_LAZY_INSTANCE_H_
#define BASE_LAZY_INSTANCE_H_
#include <new> // For placement new.
#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "mozilla/Alignment.h"
// LazyInstance uses its own struct initializer-list style static
// initialization, as base's LINKER_INITIALIZED requires a constructor and on
// some compilers (notably gcc 4.4) this still ends up needing runtime
// initialization.
#define LAZY_INSTANCE_INITIALIZER {0}
namespace base {
template <typename Type>
struct DefaultLazyInstanceTraits {
static const bool kRegisterOnExit = true;
static Type* New(void* instance) {
DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (MOZ_ALIGNOF(Type) - 1), 0u)
<< ": Bad boy, the buffer passed to placement new is not aligned!\n"
"This may break some stuff like SSE-based optimizations assuming the "
"<Type> objects are word aligned.";
// Use placement new to initialize our instance in our preallocated space.
// The parenthesis is very important here to force POD type initialization.
return new (instance) Type();
}
static void Delete(Type* instance) {
// Explicitly call the destructor.
instance->~Type();
}
};
// We pull out some of the functionality into non-templated functions, so we
// can implement the more complicated pieces out of line in the .cc file.
namespace internal {
// Use LazyInstance<T>::Leaky for a less-verbose call-site typedef; e.g.:
// base::LazyInstance<T>::Leaky my_leaky_lazy_instance;
// instead of:
// base::LazyInstance<T, base::internal::LeakyLazyInstanceTraits<T> >
// my_leaky_lazy_instance;
// (especially when T is MyLongTypeNameImplClientHolderFactory).
// Only use this internal::-qualified verbose form to extend this traits class
// (depending on its implementation details).
template <typename Type>
struct LeakyLazyInstanceTraits {
static const bool kRegisterOnExit = false;
static Type* New(void* instance) {
return DefaultLazyInstanceTraits<Type>::New(instance);
}
static void Delete(Type* instance) {
}
};
// Our AtomicWord doubles as a spinlock, where a value of
// kBeingCreatedMarker means the spinlock is being held for creation.
static const subtle::AtomicWord kLazyInstanceStateCreating = 1;
// Check if instance needs to be created. If so return true otherwise
// if another thread has beat us, wait for instance to be created and
// return false.
bool NeedsLazyInstance(subtle::AtomicWord* state);
// After creating an instance, call this to register the dtor to be called
// at program exit and to update the atomic state to hold the |new_instance|
void CompleteLazyInstance(subtle::AtomicWord* state,
subtle::AtomicWord new_instance,
void* lazy_instance,
void (*dtor)(void*));
} // namespace internal
template <typename Type, typename Traits = DefaultLazyInstanceTraits<Type> >
class LazyInstance {
public:
// Do not define a destructor, as doing so makes LazyInstance a
// non-POD-struct. We don't want that because then a static initializer will
// be created to register the (empty) destructor with atexit() under MSVC, for
// example. We handle destruction of the contained Type class explicitly via
// the OnExit member function, where needed.
// ~LazyInstance() {}
// Convenience typedef to avoid having to repeat Type for leaky lazy
// instances.
typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type> > Leaky;
Type& Get() {
return *Pointer();
}
Type* Pointer() {
// If any bit in the created mask is true, the instance has already been
// fully constructed.
static const subtle::AtomicWord kLazyInstanceCreatedMask =
~internal::kLazyInstanceStateCreating;
// We will hopefully have fast access when the instance is already created.
// Since a thread sees private_instance_ == 0 or kLazyInstanceStateCreating
// at most once, the load is taken out of NeedsInstance() as a fast-path.
// The load has acquire memory ordering as a thread which sees
// private_instance_ > creating needs to acquire visibility over
// the associated data (private_buf_). Pairing Release_Store is in
// CompleteLazyInstance().
subtle::AtomicWord value = subtle::Acquire_Load(&private_instance_);
if (!(value & kLazyInstanceCreatedMask) &&
internal::NeedsLazyInstance(&private_instance_)) {
// Create the instance in the space provided by |private_buf_|.
value = reinterpret_cast<subtle::AtomicWord>(
Traits::New(private_buf_.addr()));
internal::CompleteLazyInstance(&private_instance_, value, this,
Traits::kRegisterOnExit ? OnExit : NULL);
}
return instance();
}
bool operator==(Type* p) {
switch (subtle::NoBarrier_Load(&private_instance_)) {
case 0:
return p == NULL;
case internal::kLazyInstanceStateCreating:
return static_cast<void*>(p) == private_buf_.addr();
default:
return p == instance();
}
}
// Effectively private: member data is only public to allow the linker to
// statically initialize it and to maintain a POD class. DO NOT USE FROM
// OUTSIDE THIS CLASS.
subtle::AtomicWord private_instance_;
// Preallocated space for the Type instance.
mozilla::AlignedStorage2<Type> private_buf_;
private:
Type* instance() {
return reinterpret_cast<Type*>(subtle::NoBarrier_Load(&private_instance_));
}
// Adapter function for use with AtExit. This should be called single
// threaded, so don't synchronize across threads.
// Calling OnExit while the instance is in use by other threads is a mistake.
static void OnExit(void* lazy_instance) {
LazyInstance<Type, Traits>* me =
reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
Traits::Delete(me->instance());
subtle::NoBarrier_Store(&me->private_instance_, 0);
}
};
} // namespace base
#endif // BASE_LAZY_INSTANCE_H_

View File

@ -8,7 +8,6 @@
#include "mozilla/Atomics.h"
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_pump_default.h"
#include "base/string_util.h"
@ -41,10 +40,10 @@ using base::Time;
using base::TimeDelta;
using base::TimeTicks;
// A lazily created thread local storage for quick access to a thread's message
// loop, if one exists. This should be safe and free of static constructors.
static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
static base::ThreadLocalPointer<MessageLoop>& get_tls_ptr() {
static base::ThreadLocalPointer<MessageLoop> tls_ptr;
return tls_ptr;
}
//------------------------------------------------------------------------------
@ -84,10 +83,7 @@ static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
// static
MessageLoop* MessageLoop::current() {
// TODO(darin): sadly, we cannot enable this yet since people call us even
// when they have no intention of using us.
//DCHECK(loop) << "Ouch, did you forget to initialize me?";
return lazy_tls_ptr.Pointer()->Get();
return get_tls_ptr().Get();
}
static mozilla::Atomic<int32_t> message_loop_id_seq(0);
@ -106,7 +102,7 @@ MessageLoop::MessageLoop(Type type)
permanent_hang_timeout_(0),
next_sequence_num_(0) {
DCHECK(!current()) << "should only have one message loop per thread";
lazy_tls_ptr.Pointer()->Set(this);
get_tls_ptr().Set(this);
switch (type_) {
case TYPE_MOZILLA_UI:
@ -183,7 +179,7 @@ MessageLoop::~MessageLoop() {
DCHECK(!did_work);
// OK, now make it so that no one can find us.
lazy_tls_ptr.Pointer()->Set(NULL);
get_tls_ptr().Set(NULL);
}
void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {

View File

@ -8,7 +8,6 @@
#include <math.h>
#include "base/eintr_wrapper.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/platform_thread.h"

View File

@ -4,7 +4,6 @@
#include "base/thread.h"
#include "base/lazy_instance.h"
#include "base/string_util.h"
#include "base/thread_local.h"
#include "base/waitable_event.h"
@ -58,19 +57,22 @@ namespace {
// because its Stop method was called. This allows us to catch cases where
// MessageLoop::Quit() is called directly, which is unexpected when using a
// Thread to setup and run a MessageLoop.
base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool =
LAZY_INSTANCE_INITIALIZER;
static base::ThreadLocalBoolean& get_tls_bool() {
static base::ThreadLocalBoolean tls_ptr;
return tls_ptr;
}
} // namespace
void Thread::SetThreadWasQuitProperly(bool flag) {
lazy_tls_bool.Pointer()->Set(flag);
get_tls_bool().Set(flag);
}
bool Thread::GetThreadWasQuitProperly() {
bool quit_properly = true;
#ifndef NDEBUG
quit_properly = lazy_tls_bool.Pointer()->Get();
quit_properly = get_tls_bool().Get();
#endif
return quit_properly;
}

View File

@ -4,7 +4,6 @@
#include "chrome/common/ipc_sync_channel.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/thread_local.h"
#include "base/message_loop.h"
@ -38,15 +37,21 @@ namespace IPC {
class SyncChannel::ReceivedSyncMsgQueue {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SyncChannel::ReceivedSyncMsgQueue)
static base::ThreadLocalPointer<ReceivedSyncMsgQueue>& get_tls_ptr() {
static base::ThreadLocalPointer<ReceivedSyncMsgQueue> tls_ptr;
return tls_ptr;
}
// Returns the ReceivedSyncMsgQueue instance for this thread, creating one
// if necessary. Call RemoveContext on the same thread when done.
static ReceivedSyncMsgQueue* AddContext() {
// We want one ReceivedSyncMsgQueue per listener thread (i.e. since multiple
// SyncChannel objects can block the same thread).
ReceivedSyncMsgQueue* rv = lazy_tls_ptr_.Pointer()->Get();
ReceivedSyncMsgQueue* rv = get_tls_ptr().Get();
if (!rv) {
rv = new ReceivedSyncMsgQueue();
ReceivedSyncMsgQueue::lazy_tls_ptr_.Pointer()->Set(rv);
get_tls_ptr().Set(rv);
}
rv->listener_count_++;
return rv;
@ -121,18 +126,14 @@ class SyncChannel::ReceivedSyncMsgQueue {
}
if (--listener_count_ == 0) {
DCHECK(lazy_tls_ptr_.Pointer()->Get());
lazy_tls_ptr_.Pointer()->Set(NULL);
DCHECK(get_tls_ptr().Get());
get_tls_ptr().Set(NULL);
}
}
WaitableEvent* dispatch_event() { return &dispatch_event_; }
MessageLoop* listener_message_loop() { return listener_message_loop_; }
// Holds a pointer to the per-thread ReceivedSyncMsgQueue object.
static base::LazyInstance<base::ThreadLocalPointer<ReceivedSyncMsgQueue> >
lazy_tls_ptr_;
// Called on the ipc thread to check if we can unblock any current Send()
// calls based on a queued reply.
void DispatchReplies() {
@ -181,9 +182,6 @@ class SyncChannel::ReceivedSyncMsgQueue {
int listener_count_;
};
base::LazyInstance<base::ThreadLocalPointer<SyncChannel::ReceivedSyncMsgQueue> >
SyncChannel::ReceivedSyncMsgQueue::lazy_tls_ptr_ = LAZY_INSTANCE_INITIALIZER;
SyncChannel::SyncContext::SyncContext(
Channel::Listener* listener,
MessageFilter* filter,

View File

@ -3,16 +3,16 @@
// found in the LICENSE file.
#include "chrome/common/notification_service.h"
#include "base/lazy_instance.h"
#include "base/thread_local.h"
static base::LazyInstance<base::ThreadLocalPointer<NotificationService> >
lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER;
static base::ThreadLocalPointer<NotificationService>& get_tls_ptr() {
static base::ThreadLocalPointer<NotificationService> tls_ptr;
return tls_ptr;
}
// static
NotificationService* NotificationService::current() {
return lazy_tls_ptr.Pointer()->Get();
return get_tls_ptr().Get();
}
// static
@ -27,7 +27,7 @@ NotificationService::NotificationService() {
memset(observer_counts_, 0, sizeof(observer_counts_));
#endif
lazy_tls_ptr.Pointer()->Set(this);
get_tls_ptr().Set(this);
}
void NotificationService::AddObserver(NotificationObserver* observer,
@ -117,7 +117,7 @@ void NotificationService::Notify(NotificationType type,
NotificationService::~NotificationService() {
lazy_tls_ptr.Pointer()->Set(NULL);
get_tls_ptr().Set(NULL);
#ifndef NDEBUG
for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {