summaryrefslogtreecommitdiff
path: root/base/memory
diff options
context:
space:
mode:
authorJakub Pawlowski <jpawlowski@google.com>2017-12-20 18:26:31 +0000
committerMyles Watson <mylesgw@google.com>2017-12-20 18:47:15 +0000
commit70cd4fac31a9b0865dab6574540f70cc103337dc (patch)
treea9d13e0b40d89d8960e80b71a7c21e639ea6c2d5 /base/memory
parentbf8c17f71511c1e90cd8cccfe71f0852c566bd3b (diff)
downloadlibchrome-70cd4fac31a9b0865dab6574540f70cc103337dc.tar.gz
Revert "Uprev the library to r462023 from Chromium"
This reverts commit bf8c17f71511c1e90cd8cccfe71f0852c566bd3b. Reason for revert: https://buganizer.corp.google.com/issues/70858501 Change-Id: Iedb1193d46ea2211f8b6fdace41902ad8df6d754
Diffstat (limited to 'base/memory')
-rw-r--r--base/memory/ref_counted.cc31
-rw-r--r--base/memory/ref_counted.h201
-rw-r--r--base/memory/ref_counted_unittest.cc38
-rw-r--r--base/memory/ref_counted_unittest.nc25
-rw-r--r--base/memory/shared_memory_mac_unittest.cc8
-rw-r--r--base/memory/shared_memory_unittest.cc8
-rw-r--r--base/memory/singleton_objc.h60
7 files changed, 87 insertions, 284 deletions
diff --git a/base/memory/ref_counted.cc b/base/memory/ref_counted.cc
index 039f255b15..46bbd7ad85 100644
--- a/base/memory/ref_counted.cc
+++ b/base/memory/ref_counted.cc
@@ -3,17 +3,9 @@
// found in the LICENSE file.
#include "base/memory/ref_counted.h"
-
#include "base/threading/thread_collision_warner.h"
namespace base {
-namespace {
-
-#if DCHECK_IS_ON()
-AtomicRefCount g_cross_thread_ref_count_access_allow_count = 0;
-#endif
-
-} // namespace
namespace subtle {
@@ -21,6 +13,8 @@ bool RefCountedThreadSafeBase::HasOneRef() const {
return AtomicRefCountIsOne(&ref_count_);
}
+RefCountedThreadSafeBase::RefCountedThreadSafeBase() = default;
+
RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
#if DCHECK_IS_ON()
DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without "
@@ -31,10 +25,6 @@ RefCountedThreadSafeBase::~RefCountedThreadSafeBase() {
void RefCountedThreadSafeBase::AddRef() const {
#if DCHECK_IS_ON()
DCHECK(!in_dtor_);
- DCHECK(!needs_adopt_ref_)
- << "This RefCounted object is created with non-zero reference count."
- << " The first reference to such a object has to be made by AdoptRef or"
- << " MakeShared.";
#endif
AtomicRefCountInc(&ref_count_);
}
@@ -53,23 +43,6 @@ bool RefCountedThreadSafeBase::Release() const {
return false;
}
-#if DCHECK_IS_ON()
-bool RefCountedBase::CalledOnValidSequence() const {
- return sequence_checker_.CalledOnValidSequence() ||
- !AtomicRefCountIsZero(&g_cross_thread_ref_count_access_allow_count);
-}
-#endif
-
} // namespace subtle
-#if DCHECK_IS_ON()
-ScopedAllowCrossThreadRefCountAccess::ScopedAllowCrossThreadRefCountAccess() {
- AtomicRefCountInc(&g_cross_thread_ref_count_access_allow_count);
-}
-
-ScopedAllowCrossThreadRefCountAccess::~ScopedAllowCrossThreadRefCountAccess() {
- AtomicRefCountDec(&g_cross_thread_ref_count_access_allow_count);
-}
-#endif
-
} // namespace base
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h
index 46088f2240..9dd09ad346 100644
--- a/base/memory/ref_counted.h
+++ b/base/memory/ref_counted.h
@@ -16,40 +16,24 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/sequence_checker.h"
#include "base/threading/thread_collision_warner.h"
#include "build/build_config.h"
-template <class T>
-class scoped_refptr;
-
namespace base {
-template <typename T>
-scoped_refptr<T> AdoptRef(T* t);
-
namespace subtle {
-enum AdoptRefTag { kAdoptRefTag };
-enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag };
-enum StartRefCountFromOneTag { kStartRefCountFromOneTag };
-
class BASE_EXPORT RefCountedBase {
public:
bool HasOneRef() const { return ref_count_ == 1; }
protected:
- explicit RefCountedBase(StartRefCountFromZeroTag) {
+ RefCountedBase()
+ : ref_count_(0)
#if DCHECK_IS_ON()
- sequence_checker_.DetachFromSequence();
-#endif
- }
-
- explicit RefCountedBase(StartRefCountFromOneTag) : ref_count_(1) {
-#if DCHECK_IS_ON()
- needs_adopt_ref_ = true;
- sequence_checker_.DetachFromSequence();
+ , in_dtor_(false)
#endif
+ {
}
~RefCountedBase() {
@@ -58,6 +42,7 @@ class BASE_EXPORT RefCountedBase {
#endif
}
+
void AddRef() const {
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
// Current thread books the critical section "AddRelease"
@@ -65,62 +50,32 @@ class BASE_EXPORT RefCountedBase {
// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
#if DCHECK_IS_ON()
DCHECK(!in_dtor_);
- DCHECK(!needs_adopt_ref_)
- << "This RefCounted object is created with non-zero reference count."
- << " The first reference to such a object has to be made by AdoptRef or"
- << " MakeShared.";
- if (ref_count_ >= 1) {
- DCHECK(CalledOnValidSequence());
- }
#endif
-
++ref_count_;
}
// Returns true if the object should self-delete.
bool Release() const {
- --ref_count_;
-
// TODO(maruel): Add back once it doesn't assert 500 times/sec.
// Current thread books the critical section "AddRelease"
// without release it.
// DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_);
-
#if DCHECK_IS_ON()
DCHECK(!in_dtor_);
- if (ref_count_ == 0)
- in_dtor_ = true;
-
- if (ref_count_ >= 1)
- DCHECK(CalledOnValidSequence());
- if (ref_count_ == 1)
- sequence_checker_.DetachFromSequence();
#endif
-
- return ref_count_ == 0;
- }
-
- private:
- template <typename U>
- friend scoped_refptr<U> base::AdoptRef(U*);
-
- void Adopted() const {
+ if (--ref_count_ == 0) {
#if DCHECK_IS_ON()
- DCHECK(needs_adopt_ref_);
- needs_adopt_ref_ = false;
+ in_dtor_ = true;
#endif
+ return true;
+ }
+ return false;
}
+ private:
+ mutable size_t ref_count_;
#if DCHECK_IS_ON()
- bool CalledOnValidSequence() const;
-#endif
-
- mutable size_t ref_count_ = 0;
-
-#if DCHECK_IS_ON()
- mutable bool needs_adopt_ref_ = false;
- mutable bool in_dtor_ = false;
- mutable SequenceChecker sequence_checker_;
+ mutable bool in_dtor_;
#endif
DFAKE_MUTEX(add_release_);
@@ -133,13 +88,7 @@ class BASE_EXPORT RefCountedThreadSafeBase {
bool HasOneRef() const;
protected:
- explicit RefCountedThreadSafeBase(StartRefCountFromZeroTag) {}
- explicit RefCountedThreadSafeBase(StartRefCountFromOneTag) : ref_count_(1) {
-#if DCHECK_IS_ON()
- needs_adopt_ref_ = true;
-#endif
- }
-
+ RefCountedThreadSafeBase();
~RefCountedThreadSafeBase();
void AddRef() const;
@@ -148,19 +97,8 @@ class BASE_EXPORT RefCountedThreadSafeBase {
bool Release() const;
private:
- template <typename U>
- friend scoped_refptr<U> base::AdoptRef(U*);
-
- void Adopted() const {
-#if DCHECK_IS_ON()
- DCHECK(needs_adopt_ref_);
- needs_adopt_ref_ = false;
-#endif
- }
-
mutable AtomicRefCount ref_count_ = 0;
#if DCHECK_IS_ON()
- mutable bool needs_adopt_ref_ = false;
mutable bool in_dtor_ = false;
#endif
@@ -169,27 +107,6 @@ class BASE_EXPORT RefCountedThreadSafeBase {
} // namespace subtle
-// ScopedAllowCrossThreadRefCountAccess disables the check documented on
-// RefCounted below for rare pre-existing use cases where thread-safety was
-// guaranteed through other means (e.g. explicit sequencing of calls across
-// execution sequences when bouncing between threads in order). New callers
-// should refrain from using this (callsites handling thread-safety through
-// locks should use RefCountedThreadSafe per the overhead of its atomics being
-// negligible compared to locks anyways and callsites doing explicit sequencing
-// should properly std::move() the ref to avoid hitting this check).
-// TODO(tzik): Cleanup existing use cases and remove
-// ScopedAllowCrossThreadRefCountAccess.
-class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final {
- public:
-#if DCHECK_IS_ON()
- ScopedAllowCrossThreadRefCountAccess();
- ~ScopedAllowCrossThreadRefCountAccess();
-#else
- ScopedAllowCrossThreadRefCountAccess() {}
- ~ScopedAllowCrossThreadRefCountAccess() {}
-#endif
-};
-
//
// A base class for reference counted classes. Otherwise, known as a cheap
// knock-off of WebKit's RefCounted<T> class. To use this, just extend your
@@ -204,45 +121,10 @@ class BASE_EXPORT ScopedAllowCrossThreadRefCountAccess final {
//
// You should always make your destructor non-public, to avoid any code deleting
// the object accidently while there are references to it.
-//
-//
-// The ref count manipulation to RefCounted is NOT thread safe and has DCHECKs
-// to trap unsafe cross thread usage. A subclass instance of RefCounted can be
-// passed to another execution sequence only when its ref count is 1. If the ref
-// count is more than 1, the RefCounted class verifies the ref updates are made
-// on the same execution sequence as the previous ones.
-//
-//
-// The reference count starts from zero by default, and we intended to migrate
-// to start-from-one ref count. Put REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() to
-// the ref counted class to opt-in.
-//
-// If an object has start-from-one ref count, the first scoped_refptr need to be
-// created by base::AdoptRef() or base::MakeShared(). We can use
-// base::MakeShared() to create create both type of ref counted object.
-//
-// The motivations to use start-from-one ref count are:
-// - Start-from-one ref count doesn't need the ref count increment for the
-// first reference.
-// - It can detect an invalid object acquisition for a being-deleted object
-// that has zero ref count. That tends to happen on custom deleter that
-// delays the deletion.
-// TODO(tzik): Implement invalid acquisition detection.
-// - Behavior parity to Blink's WTF::RefCounted, whose count starts from one.
-// And start-from-one ref count is a step to merge WTF::RefCounted into
-// base::RefCounted.
-//
-#define REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() \
- static constexpr ::base::subtle::StartRefCountFromOneTag \
- kRefCountPreference = ::base::subtle::kStartRefCountFromOneTag
-
template <class T>
class RefCounted : public subtle::RefCountedBase {
public:
- static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference =
- subtle::kStartRefCountFromZeroTag;
-
- RefCounted() : subtle::RefCountedBase(T::kRefCountPreference) {}
+ RefCounted() = default;
void AddRef() const {
subtle::RefCountedBase::AddRef();
@@ -258,7 +140,7 @@ class RefCounted : public subtle::RefCountedBase {
~RefCounted() = default;
private:
- DISALLOW_COPY_AND_ASSIGN(RefCounted);
+ DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
};
// Forward declaration.
@@ -289,17 +171,10 @@ struct DefaultRefCountedThreadSafeTraits {
// private:
// friend class base::RefCountedThreadSafe<MyFoo>;
// ~MyFoo();
-//
-// We can use REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE() with RefCountedThreadSafe
-// too. See the comment above the RefCounted definition for details.
template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> >
class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase {
public:
- static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference =
- subtle::kStartRefCountFromZeroTag;
-
- explicit RefCountedThreadSafe()
- : subtle::RefCountedThreadSafeBase(T::kRefCountPreference) {}
+ RefCountedThreadSafe() = default;
void AddRef() const {
subtle::RefCountedThreadSafeBase::AddRef();
@@ -339,43 +214,6 @@ class RefCountedData
~RefCountedData() = default;
};
-// Creates a scoped_refptr from a raw pointer without incrementing the reference
-// count. Use this only for a newly created object whose reference count starts
-// from 1 instead of 0.
-template <typename T>
-scoped_refptr<T> AdoptRef(T* obj) {
- using Tag = typename std::decay<decltype(T::kRefCountPreference)>::type;
- static_assert(std::is_same<subtle::StartRefCountFromOneTag, Tag>::value,
- "Use AdoptRef only for the reference count starts from one.");
-
- DCHECK(obj);
- DCHECK(obj->HasOneRef());
- obj->Adopted();
- return scoped_refptr<T>(obj, subtle::kAdoptRefTag);
-}
-
-namespace subtle {
-
-template <typename T>
-scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) {
- return scoped_refptr<T>(obj);
-}
-
-template <typename T>
-scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) {
- return AdoptRef(obj);
-}
-
-} // namespace subtle
-
-// Constructs an instance of T, which is a ref counted type, and wraps the
-// object into a scoped_refptr.
-template <typename T, typename... Args>
-scoped_refptr<T> MakeShared(Args&&... args) {
- T* obj = new T(std::forward<Args>(args)...);
- return subtle::AdoptRefIfNeeded(obj, T::kRefCountPreference);
-}
-
} // namespace base
//
@@ -547,11 +385,6 @@ class scoped_refptr {
T* ptr_ = nullptr;
private:
- template <typename U>
- friend scoped_refptr<U> base::AdoptRef(U*);
-
- scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
-
// Friend required for move constructors that set r.ptr_ to null.
template <typename U>
friend class scoped_refptr;
diff --git a/base/memory/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc
index 515f4227ea..65c15d26ab 100644
--- a/base/memory/ref_counted_unittest.cc
+++ b/base/memory/ref_counted_unittest.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/test/gtest_util.h"
#include "base/test/opaque_ref_counted.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -123,16 +122,6 @@ scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
return self_assign;
}
-class InitialRefCountIsOne : public base::RefCounted<InitialRefCountIsOne> {
- public:
- REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
-
- InitialRefCountIsOne() {}
-
- private:
- friend class base::RefCounted<InitialRefCountIsOne>;
- ~InitialRefCountIsOne() {}
-};
} // end namespace
@@ -539,30 +528,3 @@ TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
scoped_refptr<Other> other2(other);
EXPECT_EQ(other2, Overloaded(std::move(other)));
}
-
-TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
- scoped_refptr<InitialRefCountIsOne> obj =
- base::MakeShared<InitialRefCountIsOne>();
- EXPECT_TRUE(obj->HasOneRef());
- obj = nullptr;
-
- scoped_refptr<InitialRefCountIsOne> obj2 =
- base::AdoptRef(new InitialRefCountIsOne);
- EXPECT_TRUE(obj2->HasOneRef());
- obj2 = nullptr;
-
- scoped_refptr<Other> obj3 = base::MakeShared<Other>();
- EXPECT_TRUE(obj3->HasOneRef());
- obj3 = nullptr;
-}
-
-TEST(RefCountedDeathTest, TestAdoptRef) {
- EXPECT_DCHECK_DEATH(make_scoped_refptr(new InitialRefCountIsOne));
-
- InitialRefCountIsOne* ptr = nullptr;
- EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
-
- scoped_refptr<InitialRefCountIsOne> obj =
- base::MakeShared<InitialRefCountIsOne>();
- EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
-}
diff --git a/base/memory/ref_counted_unittest.nc b/base/memory/ref_counted_unittest.nc
deleted file mode 100644
index 5022779214..0000000000
--- a/base/memory/ref_counted_unittest.nc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 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/ref_counted.h"
-
-namespace base {
-
-class InitialRefCountIsZero : public base::RefCounted<InitialRefCountIsZero> {
- public:
- InitialRefCountIsZero() {}
- private:
- friend class base::RefCounted<InitialRefCountIsZero>;
- ~InitialRefCountIsZero() {}
-};
-
-#if defined(NCTEST_ADOPT_REF_TO_ZERO_START) // [r"fatal error: static_assert failed \"Use AdoptRef only for the reference count starts from one\.\""]
-
-void WontCompile() {
- AdoptRef(new InitialRefCountIsZero());
-}
-
-#endif
-
-} // namespace base
diff --git a/base/memory/shared_memory_mac_unittest.cc b/base/memory/shared_memory_mac_unittest.cc
index 4ccee89deb..c7d20ec049 100644
--- a/base/memory/shared_memory_mac_unittest.cc
+++ b/base/memory/shared_memory_mac_unittest.cc
@@ -204,7 +204,7 @@ class SharedMemoryMacMultiProcessTest : public MultiProcessTest {
// similar tests.
service_name_ = CreateRandomServiceName();
server_port_.reset(BecomeMachServer(service_name_.c_str()));
- spawn_child_ = SpawnChild(name);
+ child_process_ = SpawnChild(name);
client_port_.reset(ReceiveMachPort(server_port_.get()));
}
@@ -221,7 +221,7 @@ class SharedMemoryMacMultiProcessTest : public MultiProcessTest {
// process.
mac::ScopedMachSendRight client_port_;
- base::SpawnChildResult spawn_child_;
+ base::Process child_process_;
DISALLOW_COPY_AND_ASSIGN(SharedMemoryMacMultiProcessTest);
};
@@ -237,7 +237,7 @@ TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemory) {
SendMachPort(client_port_.get(), shared_memory->handle().GetMemoryObject(),
MACH_MSG_TYPE_COPY_SEND);
int rv = -1;
- ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout(
+ ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
TestTimeouts::action_timeout(), &rv));
EXPECT_EQ(0, rv);
}
@@ -277,7 +277,7 @@ TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) {
SendMachPort(
client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND);
int rv = -1;
- ASSERT_TRUE(spawn_child_.process.WaitForExitWithTimeout(
+ ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
TestTimeouts::action_timeout(), &rv));
EXPECT_EQ(0, rv);
}
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
index d87fad01d3..19dedccb47 100644
--- a/base/memory/shared_memory_unittest.cc
+++ b/base/memory/shared_memory_unittest.cc
@@ -682,16 +682,16 @@ TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) {
// Start |kNumTasks| processes, each of which atomically increments the first
// word by 1.
- SpawnChildResult children[kNumTasks];
+ Process processes[kNumTasks];
for (int index = 0; index < kNumTasks; ++index) {
- children[index] = SpawnChild("SharedMemoryTestMain");
- ASSERT_TRUE(children[index].process.IsValid());
+ processes[index] = SpawnChild("SharedMemoryTestMain");
+ ASSERT_TRUE(processes[index].IsValid());
}
// Check that each process exited correctly.
int exit_code = 0;
for (int index = 0; index < kNumTasks; ++index) {
- EXPECT_TRUE(children[index].process.WaitForExit(&exit_code));
+ EXPECT_TRUE(processes[index].WaitForExit(&exit_code));
EXPECT_EQ(0, exit_code);
}
diff --git a/base/memory/singleton_objc.h b/base/memory/singleton_objc.h
new file mode 100644
index 0000000000..6df3f7757e
--- /dev/null
+++ b/base/memory/singleton_objc.h
@@ -0,0 +1,60 @@
+// 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.
+
+// Support for using the Singleton<T> pattern with Objective-C objects. A
+// SingletonObjC is the same as a Singleton, except the default traits are
+// appropriate for Objective-C objects. A typical Objective-C object of type
+// NSExampleType can be maintained as a singleton and accessed with:
+//
+// NSExampleType* exampleSingleton = SingletonObjC<NSExampleType>::get();
+//
+// The first time this is used, it will create exampleSingleton as the result
+// of [[NSExampleType alloc] init]. Subsequent calls will return the same
+// NSExampleType* object. The object will be released by calling
+// -[NSExampleType release] when Singleton's atexit routines run
+// (see singleton.h).
+//
+// For Objective-C objects initialized through means other than the
+// no-parameter -init selector, DefaultSingletonObjCTraits may be extended
+// as needed:
+//
+// struct FooSingletonTraits : public DefaultSingletonObjCTraits<Foo> {
+// static Foo* New() {
+// return [[Foo alloc] initWithName:@"selecty"];
+// }
+// };
+// ...
+// Foo* widgetSingleton = SingletonObjC<Foo, FooSingletonTraits>::get();
+
+#ifndef BASE_MEMORY_SINGLETON_OBJC_H_
+#define BASE_MEMORY_SINGLETON_OBJC_H_
+
+#import <Foundation/Foundation.h>
+#include "base/memory/singleton.h"
+
+// Singleton traits usable to manage traditional Objective-C objects, which
+// are instantiated by sending |alloc| and |init| messages, and are deallocated
+// in a memory-managed environment when their retain counts drop to 0 by
+// sending |release| messages.
+template<typename Type>
+struct DefaultSingletonObjCTraits : public DefaultSingletonTraits<Type> {
+ static Type* New() {
+ return [[Type alloc] init];
+ }
+
+ static void Delete(Type* object) {
+ [object release];
+ }
+};
+
+// Exactly like Singleton, but without the DefaultSingletonObjCTraits as the
+// default trait class. This makes it straightforward for Objective-C++ code
+// to hold Objective-C objects as singletons.
+template<typename Type,
+ typename Traits = DefaultSingletonObjCTraits<Type>,
+ typename DifferentiatingType = Type>
+class SingletonObjC : public Singleton<Type, Traits, DifferentiatingType> {
+};
+
+#endif // BASE_MEMORY_SINGLETON_OBJC_H_