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