1 // Copyright 2013 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ 6 #define BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ 7 8 #include <utility> 9 10 #include "base/check.h" 11 #include "base/location.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/task/sequenced_task_runner.h" 14 15 namespace base { 16 17 // RefCountedDeleteOnSequence is similar to RefCountedThreadSafe, and ensures 18 // that the object will be deleted on a specified sequence. 19 // 20 // Sample usage: 21 // class Foo : public RefCountedDeleteOnSequence<Foo> { 22 // 23 // Foo(scoped_refptr<SequencedTaskRunner> task_runner) 24 // : RefCountedDeleteOnSequence<Foo>(std::move(task_runner)) {} 25 // ... 26 // private: 27 // friend class RefCountedDeleteOnSequence<Foo>; 28 // friend class DeleteHelper<Foo>; 29 // 30 // ~Foo(); 31 // }; 32 template <class T> 33 class RefCountedDeleteOnSequence : public subtle::RefCountedThreadSafeBase { 34 public: 35 using RefCountPreferenceTag = subtle::StartRefCountFromZeroTag; 36 37 // A SequencedTaskRunner for the current sequence can be acquired by calling 38 // SequencedTaskRunner::GetCurrentDefault(). RefCountedDeleteOnSequence(scoped_refptr<SequencedTaskRunner> owning_task_runner)39 explicit RefCountedDeleteOnSequence( 40 scoped_refptr<SequencedTaskRunner> owning_task_runner) 41 : subtle::RefCountedThreadSafeBase(subtle::GetRefCountPreference<T>()), 42 owning_task_runner_(std::move(owning_task_runner)) { 43 DCHECK(owning_task_runner_); 44 } 45 46 RefCountedDeleteOnSequence(const RefCountedDeleteOnSequence&) = delete; 47 RefCountedDeleteOnSequence& operator=(const RefCountedDeleteOnSequence&) = 48 delete; 49 AddRef()50 void AddRef() const { AddRefImpl(subtle::GetRefCountPreference<T>()); } 51 Release()52 void Release() const { 53 if (subtle::RefCountedThreadSafeBase::Release()) 54 DestructOnSequence(); 55 } 56 57 protected: 58 friend class DeleteHelper<RefCountedDeleteOnSequence>; 59 ~RefCountedDeleteOnSequence() = default; 60 owning_task_runner()61 SequencedTaskRunner* owning_task_runner() { 62 return owning_task_runner_.get(); 63 } owning_task_runner()64 const SequencedTaskRunner* owning_task_runner() const { 65 return owning_task_runner_.get(); 66 } 67 68 private: DestructOnSequence()69 void DestructOnSequence() const { 70 const T* t = static_cast<const T*>(this); 71 if (owning_task_runner_->RunsTasksInCurrentSequence()) 72 delete t; 73 else 74 owning_task_runner_->DeleteSoon(FROM_HERE, t); 75 } 76 AddRefImpl(subtle::StartRefCountFromZeroTag)77 void AddRefImpl(subtle::StartRefCountFromZeroTag) const { 78 subtle::RefCountedThreadSafeBase::AddRef(); 79 } 80 AddRefImpl(subtle::StartRefCountFromOneTag)81 void AddRefImpl(subtle::StartRefCountFromOneTag) const { 82 subtle::RefCountedThreadSafeBase::AddRefWithCheck(); 83 } 84 85 const scoped_refptr<SequencedTaskRunner> owning_task_runner_; 86 }; 87 88 } // namespace base 89 90 #endif // BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ 91