self_deleter_helper.h revision f2477e01787aa58f445919b809d89e252beef54f
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" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/ref_counted.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/weak_ptr.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace base { 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SingleThreadTaskRunner; 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace base 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace forwarder2 { 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Helper template class to be used in the following case: 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// * T is the type of an object that implements some work through an internal 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// or worker thread. 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// * T wants the internal thread to invoke deletion of its own instance, on 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// the thread where the instance was created. 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// To make this easier, do something like: 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 1) Add a SelfDeleteHelper<T> member to your class T, and default-initialize 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// it in its constructor. 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 2) In the internal thread, to trigger self-deletion, call the 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// MaybeDeleteSoon() method on this member. 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// MaybeDeleteSoon() posts a task on the message loop where the T instance was 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// created to delete it. The task will be safely ignored if the instance is 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// otherwise deleted. 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Usage example: 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// class Object { 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// public: 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// typedef base::Callback<void (scoped_ptr<Object>)> ErrorCallback; 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Object(const ErrorCallback& error_callback) 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// : self_deleter_helper_(this, error_callback) { 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// } 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// void StartWork() { 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // Post a callback to DoSomethingOnWorkerThread() below to another 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // thread. 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// } 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// void DoSomethingOnWorkerThread() { 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ... 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// if (error_happened) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// self_deleter_helper_.MaybeDeleteSoon(); 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// } 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// private: 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// SelfDeleterHelper<MySelfDeletingClass> self_deleter_helper_; 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// }; 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// class ObjectOwner { 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// public: 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ObjectOwner() 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// : object_(new Object(base::Bind(&ObjectOwner::DeleteObjectOnError, 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// base::Unretained(this))) { 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // To keep this example simple base::Unretained(this) is used above but 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // note that in a real world scenario the client would have to make sure 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // that the ObjectOwner instance is still alive when 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // DeleteObjectOnError() gets called below. This can be achieved by 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // using a WeakPtr<ObjectOwner> for instance. 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// } 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// void StartWork() { 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// object_->StartWork(); 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// } 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// private: 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// void DeleteObjectOnError(scoped_ptr<Object> object) { 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// DCHECK(thread_checker_.CalledOnValidThread()); 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// DCHECK_EQ(object_, object); 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// // Do some extra work with |object| before it gets deleted... 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// object_.reset(); 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ignore_result(object.release()); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// } 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// base::ThreadChecker thread_checker_; 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// scoped_ptr<Object> object_; 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// }; 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template <typename T> 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SelfDeleterHelper { 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public: 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) typedef base::Callback<void (scoped_ptr<T>)> DeletionCallback; 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SelfDeleterHelper(T* self_deleting_object, 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const DeletionCallback& deletion_callback) 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : weak_ptr_factory_(this), 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) construction_runner_(base::MessageLoopProxy::current()), 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self_deleting_object_(self_deleting_object), 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) deletion_callback_(deletion_callback) { 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ~SelfDeleterHelper() { 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(construction_runner_->RunsTasksOnCurrentThread()); 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void MaybeSelfDeleteSoon() { 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!construction_runner_->RunsTasksOnCurrentThread()); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) construction_runner_->PostTask( 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&SelfDeleterHelper::SelfDelete, 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private: 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void SelfDelete() { 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(construction_runner_->RunsTasksOnCurrentThread()); 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) deletion_callback_.Run(make_scoped_ptr(self_deleting_object_)); 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::WeakPtrFactory<SelfDeleterHelper<T> > weak_ptr_factory_; 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) 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SelfDeleterHelper); 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace forwarder2 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif // TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_ 136