diff options
author | joth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-07 11:11:51 +0000 |
---|---|---|
committer | joth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-07 11:11:51 +0000 |
commit | ee5272d8cc1cd65bb185fdbdd8a00836fa3c9a4d (patch) | |
tree | 22a88ed7e88674949a53b0637a144ac3f5cdac1e | |
parent | 628a22ae07ae79d1184ca081b36b226863e536ca (diff) | |
download | chromium_src-ee5272d8cc1cd65bb185fdbdd8a00836fa3c9a4d.zip chromium_src-ee5272d8cc1cd65bb185fdbdd8a00836fa3c9a4d.tar.gz chromium_src-ee5272d8cc1cd65bb185fdbdd8a00836fa3c9a4d.tar.bz2 |
Thin out the Singeton template code
- hides platform_thread.h from users of singelton
- knock 4KB off the release binary size
BUG=None
TEST=Nothing breaks
Review URL: http://codereview.chromium.org/8475007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108853 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/memory/singleton.cc | 31 | ||||
-rw-r--r-- | base/memory/singleton.h | 43 |
3 files changed, 53 insertions, 22 deletions
diff --git a/base/base.gypi b/base/base.gypi index ac20ab4..6e7d88d 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -171,6 +171,7 @@ 'memory/scoped_open_process.h', 'memory/scoped_ptr.h', 'memory/scoped_vector.h', + 'memory/singleton.cc', 'memory/singleton.h', 'memory/weak_ptr.cc', 'memory/weak_ptr.h', diff --git a/base/memory/singleton.cc b/base/memory/singleton.cc new file mode 100644 index 0000000..ee5e58d --- /dev/null +++ b/base/memory/singleton.cc @@ -0,0 +1,31 @@ +// 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/memory/singleton.h" +#include "base/threading/platform_thread.h" + +namespace base { +namespace internal { + +subtle::AtomicWord WaitForInstance(subtle::AtomicWord* instance) { + // Handle the race. Another thread beat us and either: + // - Has the object in BeingCreated state + // - Already has the object created... + // We know value != NULL. It could be kBeingCreatedMarker, or a valid ptr. + // Unless your constructor can be very time consuming, it is very unlikely + // to hit this race. When it does, we just spin and yield the thread until + // the object has been created. + subtle::AtomicWord value; + while (true) { + value = subtle::NoBarrier_Load(instance); + if (value != kBeingCreatedMarker) + break; + PlatformThread::YieldCurrentThread(); + } + return value; +} + +} // namespace internal +} // namespace base + diff --git a/base/memory/singleton.h b/base/memory/singleton.h index f82a37e..d51fe36 100644 --- a/base/memory/singleton.h +++ b/base/memory/singleton.h @@ -23,9 +23,24 @@ #include "base/at_exit.h" #include "base/atomicops.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" -#include "base/threading/platform_thread.h" #include "base/threading/thread_restrictions.h" +namespace base { +namespace internal { + +// Our AtomicWord doubles as a spinlock, where a value of +// kBeingCreatedMarker means the spinlock is being held for creation. +static const subtle::AtomicWord kBeingCreatedMarker = 1; + +// We pull out some of the functionality into a non-templated function, so that +// we can implement the more complicated pieces out of line in the .cc file. +subtle::AtomicWord WaitForInstance(subtle::AtomicWord* instance); + +} // namespace internal +} // namespace base + +// TODO(joth): Move more of this file into namespace base + // Default traits for Singleton<Type>. Calls operator new and operator delete on // the object. Registers automatic deletion at process exit. // Overload if you need arguments or another memory allocation function. @@ -219,21 +234,16 @@ class Singleton { base::ThreadRestrictions::AssertSingletonAllowed(); #endif - // Our AtomicWord doubles as a spinlock, where a value of - // kBeingCreatedMarker means the spinlock is being held for creation. - static const base::subtle::AtomicWord kBeingCreatedMarker = 1; - base::subtle::AtomicWord value = base::subtle::NoBarrier_Load(&instance_); - if (value != 0 && value != kBeingCreatedMarker) { + if (value != 0 && value != base::internal::kBeingCreatedMarker) { // See the corresponding HAPPENS_BEFORE below. ANNOTATE_HAPPENS_AFTER(&instance_); return reinterpret_cast<Type*>(value); } // Object isn't created yet, maybe we will get to create it, let's try... - if (base::subtle::Acquire_CompareAndSwap(&instance_, - 0, - kBeingCreatedMarker) == 0) { + if (base::subtle::Acquire_CompareAndSwap( + &instance_, 0, base::internal::kBeingCreatedMarker) == 0) { // instance_ was NULL and is now kBeingCreatedMarker. Only one thread // will ever get here. Threads might be spinning on us, and they will // stop right after we do this store. @@ -252,19 +262,8 @@ class Singleton { return newval; } - // We hit a race. Another thread beat us and either: - // - Has the object in BeingCreated state - // - Already has the object created... - // We know value != NULL. It could be kBeingCreatedMarker, or a valid ptr. - // Unless your constructor can be very time consuming, it is very unlikely - // to hit this race. When it does, we just spin and yield the thread until - // the object has been created. - while (true) { - value = base::subtle::NoBarrier_Load(&instance_); - if (value != kBeingCreatedMarker) - break; - base::PlatformThread::YieldCurrentThread(); - } + // We hit a race. Wait for the other thread to complete it. + value = base::internal::WaitForInstance(&instance_); // See the corresponding HAPPENS_BEFORE above. ANNOTATE_HAPPENS_AFTER(&instance_); |