diff options
author | Jakub Pawlowski <jpawlowski@google.com> | 2017-12-20 18:26:31 +0000 |
---|---|---|
committer | Myles Watson <mylesgw@google.com> | 2017-12-20 18:47:15 +0000 |
commit | 70cd4fac31a9b0865dab6574540f70cc103337dc (patch) | |
tree | a9d13e0b40d89d8960e80b71a7c21e639ea6c2d5 /base/memory | |
parent | bf8c17f71511c1e90cd8cccfe71f0852c566bd3b (diff) | |
download | libchrome-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.cc | 31 | ||||
-rw-r--r-- | base/memory/ref_counted.h | 201 | ||||
-rw-r--r-- | base/memory/ref_counted_unittest.cc | 38 | ||||
-rw-r--r-- | base/memory/ref_counted_unittest.nc | 25 | ||||
-rw-r--r-- | base/memory/shared_memory_mac_unittest.cc | 8 | ||||
-rw-r--r-- | base/memory/shared_memory_unittest.cc | 8 | ||||
-rw-r--r-- | base/memory/singleton_objc.h | 60 |
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_ |