summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-07 11:11:51 +0000
committerjoth@chromium.org <joth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-07 11:11:51 +0000
commitee5272d8cc1cd65bb185fdbdd8a00836fa3c9a4d (patch)
tree22a88ed7e88674949a53b0637a144ac3f5cdac1e
parent628a22ae07ae79d1184ca081b36b226863e536ca (diff)
downloadchromium_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.gypi1
-rw-r--r--base/memory/singleton.cc31
-rw-r--r--base/memory/singleton.h43
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_);