зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1071808: Remove Chromium lazy_instance from IPC code. r=nfroyd
This commit is contained in:
Родитель
72edb72ad8
Коммит
0372b4fdd7
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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++) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче