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