|  | // Copyright 2013 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. | 
|  |  | 
|  | #ifndef BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ | 
|  | #define BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/location.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/sequenced_task_runner.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | // RefCountedDeleteOnSequence is similar to RefCountedThreadSafe, and ensures | 
|  | // that the object will be deleted on a specified sequence. | 
|  | // | 
|  | // Sample usage: | 
|  | // class Foo : public RefCountedDeleteOnSequence<Foo> { | 
|  | // | 
|  | //   Foo(scoped_refptr<SequencedTaskRunner> task_runner) | 
|  | //       : RefCountedDeleteOnSequence<Foo>(std::move(task_runner)) {} | 
|  | //   ... | 
|  | //  private: | 
|  | //   friend class RefCountedDeleteOnSequence<Foo>; | 
|  | //   friend class DeleteHelper<Foo>; | 
|  | // | 
|  | //   ~Foo(); | 
|  | // }; | 
|  | template <class T> | 
|  | class RefCountedDeleteOnSequence : public subtle::RefCountedThreadSafeBase { | 
|  | public: | 
|  | static constexpr subtle::StartRefCountFromZeroTag kRefCountPreference = | 
|  | subtle::kStartRefCountFromZeroTag; | 
|  |  | 
|  | // A SequencedTaskRunner for the current sequence can be acquired by calling | 
|  | // SequencedTaskRunnerHandle::Get(). | 
|  | RefCountedDeleteOnSequence( | 
|  | scoped_refptr<SequencedTaskRunner> owning_task_runner) | 
|  | : subtle::RefCountedThreadSafeBase(T::kRefCountPreference), | 
|  | owning_task_runner_(std::move(owning_task_runner)) { | 
|  | DCHECK(owning_task_runner_); | 
|  | } | 
|  |  | 
|  | void AddRef() const { AddRefImpl(T::kRefCountPreference); } | 
|  |  | 
|  | void Release() const { | 
|  | if (subtle::RefCountedThreadSafeBase::Release()) | 
|  | DestructOnSequence(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | friend class DeleteHelper<RefCountedDeleteOnSequence>; | 
|  | ~RefCountedDeleteOnSequence() = default; | 
|  |  | 
|  | SequencedTaskRunner* owning_task_runner() { | 
|  | return owning_task_runner_.get(); | 
|  | } | 
|  | const SequencedTaskRunner* owning_task_runner() const { | 
|  | return owning_task_runner_.get(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | void DestructOnSequence() const { | 
|  | const T* t = static_cast<const T*>(this); | 
|  | if (owning_task_runner_->RunsTasksInCurrentSequence()) | 
|  | delete t; | 
|  | else | 
|  | owning_task_runner_->DeleteSoon(FROM_HERE, t); | 
|  | } | 
|  |  | 
|  | void AddRefImpl(subtle::StartRefCountFromZeroTag) const { | 
|  | subtle::RefCountedThreadSafeBase::AddRef(); | 
|  | } | 
|  |  | 
|  | void AddRefImpl(subtle::StartRefCountFromOneTag) const { | 
|  | subtle::RefCountedThreadSafeBase::AddRefWithCheck(); | 
|  | } | 
|  |  | 
|  | const scoped_refptr<SequencedTaskRunner> owning_task_runner_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(RefCountedDeleteOnSequence); | 
|  | }; | 
|  |  | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_MEMORY_REF_COUNTED_DELETE_ON_SEQUENCE_H_ |