blob: 51fcff10a9cf6cd9d476a17ad0ed45c65eab4c23 [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001// Copyright 2013 The Chromium Authors. All rights reserved.
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 TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_
6#define TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_
7
8#include "base/basictypes.h"
9#include "base/bind.h"
10#include "base/callback.h"
11#include "base/location.h"
12#include "base/logging.h"
13#include "base/memory/ref_counted.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/memory/weak_ptr.h"
James Robinson646469d2014-10-03 15:33:28 -070016
17namespace base {
18
19class SingleThreadTaskRunner;
20
21} // namespace base
22
23namespace forwarder2 {
24
25// Helper template class to be used in the following case:
26// * T is the type of an object that implements some work through an internal
27// or worker thread.
28// * T wants the internal thread to invoke deletion of its own instance, on
29// the thread where the instance was created.
30//
31// To make this easier, do something like:
32// 1) Add a SelfDeleteHelper<T> member to your class T, and default-initialize
33// it in its constructor.
34// 2) In the internal thread, to trigger self-deletion, call the
35// MaybeDeleteSoon() method on this member.
36//
37// MaybeDeleteSoon() posts a task on the message loop where the T instance was
38// created to delete it. The task will be safely ignored if the instance is
39// otherwise deleted.
40//
41// Usage example:
42// class Object {
43// public:
44// typedef base::Callback<void (scoped_ptr<Object>)> ErrorCallback;
45//
46// Object(const ErrorCallback& error_callback)
47// : self_deleter_helper_(this, error_callback) {
48// }
49//
50// void StartWork() {
51// // Post a callback to DoSomethingOnWorkerThread() below to another
52// // thread.
53// }
54//
55// void DoSomethingOnWorkerThread() {
56// ...
57// if (error_happened)
58// self_deleter_helper_.MaybeDeleteSoon();
59// }
60//
61// private:
62// SelfDeleterHelper<MySelfDeletingClass> self_deleter_helper_;
63// };
64//
65// class ObjectOwner {
66// public:
67// ObjectOwner()
68// : object_(new Object(base::Bind(&ObjectOwner::DeleteObjectOnError,
69// base::Unretained(this))) {
70// // To keep this example simple base::Unretained(this) is used above but
71// // note that in a real world scenario the client would have to make sure
72// // that the ObjectOwner instance is still alive when
73// // DeleteObjectOnError() gets called below. This can be achieved by
74// // using a WeakPtr<ObjectOwner> for instance.
75// }
76//
77// void StartWork() {
78// object_->StartWork();
79// }
80//
81// private:
82// void DeleteObjectOnError(scoped_ptr<Object> object) {
83// DCHECK(thread_checker_.CalledOnValidThread());
84// DCHECK_EQ(object_, object);
85// // Do some extra work with |object| before it gets deleted...
86// object_.reset();
87// ignore_result(object.release());
88// }
89//
90// base::ThreadChecker thread_checker_;
91// scoped_ptr<Object> object_;
92// };
93//
94template <typename T>
95class SelfDeleterHelper {
96 public:
97 typedef base::Callback<void (scoped_ptr<T>)> DeletionCallback;
98
99 SelfDeleterHelper(T* self_deleting_object,
100 const DeletionCallback& deletion_callback)
James Robinsonc4d0fb22016-01-28 14:31:21 -0800101 : construction_runner_(base::MessageLoop::current()->task_runner()),
James Robinson646469d2014-10-03 15:33:28 -0700102 self_deleting_object_(self_deleting_object),
103 deletion_callback_(deletion_callback),
James Robinsonc4d0fb22016-01-28 14:31:21 -0800104 weak_ptr_factory_(this) {}
James Robinson646469d2014-10-03 15:33:28 -0700105
106 ~SelfDeleterHelper() {
107 DCHECK(construction_runner_->RunsTasksOnCurrentThread());
108 }
109
110 void MaybeSelfDeleteSoon() {
111 DCHECK(!construction_runner_->RunsTasksOnCurrentThread());
112 construction_runner_->PostTask(
113 FROM_HERE,
114 base::Bind(&SelfDeleterHelper::SelfDelete,
115 weak_ptr_factory_.GetWeakPtr()));
116 }
117
118 private:
119 void SelfDelete() {
120 DCHECK(construction_runner_->RunsTasksOnCurrentThread());
121 deletion_callback_.Run(make_scoped_ptr(self_deleting_object_));
122 }
123
124 const scoped_refptr<base::SingleThreadTaskRunner> construction_runner_;
125 T* const self_deleting_object_;
126 const DeletionCallback deletion_callback_;
127
128 //WeakPtrFactory's documentation says:
129 // Member variables should appear before the WeakPtrFactory, to ensure
130 // that any WeakPtrs to Controller are invalidated before its members
131 // variable's destructors are executed, rendering them invalid.
132 base::WeakPtrFactory<SelfDeleterHelper<T> > weak_ptr_factory_;
133
134 DISALLOW_COPY_AND_ASSIGN(SelfDeleterHelper);
135};
136
137} // namespace forwarder2
138
139#endif // TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_