1 // 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/logging.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/message_loop/message_loop_proxy.h" 16 17 namespace base { 18 19 class SingleThreadTaskRunner; 20 21 } // namespace base 22 23 namespace 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 // 94 template <typename T> 95 class SelfDeleterHelper { 96 public: 97 typedef base::Callback<void (scoped_ptr<T>)> DeletionCallback; 98 99 SelfDeleterHelper(T* self_deleting_object, 100 const DeletionCallback& deletion_callback) 101 : weak_ptr_factory_(this), 102 construction_runner_(base::MessageLoopProxy::current()), 103 self_deleting_object_(self_deleting_object), 104 deletion_callback_(deletion_callback) { 105 } 106 107 ~SelfDeleterHelper() { 108 DCHECK(construction_runner_->RunsTasksOnCurrentThread()); 109 } 110 111 void MaybeSelfDeleteSoon() { 112 DCHECK(!construction_runner_->RunsTasksOnCurrentThread()); 113 construction_runner_->PostTask( 114 FROM_HERE, 115 base::Bind(&SelfDeleterHelper::SelfDelete, 116 weak_ptr_factory_.GetWeakPtr())); 117 } 118 119 private: 120 void SelfDelete() { 121 DCHECK(construction_runner_->RunsTasksOnCurrentThread()); 122 deletion_callback_.Run(make_scoped_ptr(self_deleting_object_)); 123 } 124 125 base::WeakPtrFactory<SelfDeleterHelper<T> > weak_ptr_factory_; 126 const scoped_refptr<base::SingleThreadTaskRunner> construction_runner_; 127 T* const self_deleting_object_; 128 const DeletionCallback deletion_callback_; 129 130 DISALLOW_COPY_AND_ASSIGN(SelfDeleterHelper); 131 }; 132 133 } // namespace forwarder2 134 135 #endif // TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_ 136