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