1 /* 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_BASE_ASYNCINVOKER_H_ 12 #define WEBRTC_BASE_ASYNCINVOKER_H_ 13 14 #include "webrtc/base/asyncinvoker-inl.h" 15 #include "webrtc/base/bind.h" 16 #include "webrtc/base/sigslot.h" 17 #include "webrtc/base/scopedptrcollection.h" 18 #include "webrtc/base/thread.h" 19 20 namespace rtc { 21 22 // Invokes function objects (aka functors) asynchronously on a Thread, and 23 // owns the lifetime of calls (ie, when this object is destroyed, calls in 24 // flight are cancelled). AsyncInvoker can optionally execute a user-specified 25 // function when the asynchronous call is complete, or operates in 26 // fire-and-forget mode otherwise. 27 // 28 // AsyncInvoker does not own the thread it calls functors on. 29 // 30 // A note about async calls and object lifetimes: users should 31 // be mindful of object lifetimes when calling functions asynchronously and 32 // ensure objects used by the function _cannot_ be deleted between the 33 // invocation and execution of the functor. AsyncInvoker is designed to 34 // help: any calls in flight will be cancelled when the AsyncInvoker used to 35 // make the call is destructed, and any calls executing will be allowed to 36 // complete before AsyncInvoker destructs. 37 // 38 // The easiest way to ensure lifetimes are handled correctly is to create a 39 // class that owns the Thread and AsyncInvoker objects, and then call its 40 // methods asynchronously as needed. 41 // 42 // Example: 43 // class MyClass { 44 // public: 45 // void FireAsyncTaskWithResult(Thread* thread, int x) { 46 // // Specify a callback to get the result upon completion. 47 // invoker_.AsyncInvoke<int>( 48 // thread, Bind(&MyClass::AsyncTaskWithResult, this, x), 49 // &MyClass::OnTaskComplete, this); 50 // } 51 // void FireAnotherAsyncTask(Thread* thread) { 52 // // No callback specified means fire-and-forget. 53 // invoker_.AsyncInvoke<void>( 54 // thread, Bind(&MyClass::AnotherAsyncTask, this)); 55 // 56 // private: 57 // int AsyncTaskWithResult(int x) { 58 // // Some long running process... 59 // return x * x; 60 // } 61 // void AnotherAsyncTask() { 62 // // Some other long running process... 63 // } 64 // void OnTaskComplete(int result) { result_ = result; } 65 // 66 // AsyncInvoker invoker_; 67 // int result_; 68 // }; 69 class AsyncInvoker : public MessageHandler { 70 public: 71 AsyncInvoker(); 72 ~AsyncInvoker() override; 73 74 // Call |functor| asynchronously on |thread|, with no callback upon 75 // completion. Returns immediately. 76 template <class ReturnT, class FunctorT> 77 void AsyncInvoke(Thread* thread, const FunctorT& functor, uint32_t id = 0) { 78 scoped_refptr<AsyncClosure> closure( 79 new RefCountedObject<FireAndForgetAsyncClosure<FunctorT> >(functor)); 80 DoInvoke(thread, closure, id); 81 } 82 83 // Call |functor| asynchronously on |thread| with |delay_ms|, with no callback 84 // upon completion. Returns immediately. 85 template <class ReturnT, class FunctorT> 86 void AsyncInvokeDelayed(Thread* thread, 87 const FunctorT& functor, 88 uint32_t delay_ms, 89 uint32_t id = 0) { 90 scoped_refptr<AsyncClosure> closure( 91 new RefCountedObject<FireAndForgetAsyncClosure<FunctorT> >(functor)); 92 DoInvokeDelayed(thread, closure, delay_ms, id); 93 } 94 95 // Call |functor| asynchronously on |thread|, calling |callback| when done. 96 template <class ReturnT, class FunctorT, class HostT> 97 void AsyncInvoke(Thread* thread, 98 const FunctorT& functor, 99 void (HostT::*callback)(ReturnT), 100 HostT* callback_host, 101 uint32_t id = 0) { 102 scoped_refptr<AsyncClosure> closure( 103 new RefCountedObject<NotifyingAsyncClosure<ReturnT, FunctorT, HostT> >( 104 this, Thread::Current(), functor, callback, callback_host)); 105 DoInvoke(thread, closure, id); 106 } 107 108 // Call |functor| asynchronously on |thread|, calling |callback| when done. 109 // Overloaded for void return. 110 template <class ReturnT, class FunctorT, class HostT> 111 void AsyncInvoke(Thread* thread, 112 const FunctorT& functor, 113 void (HostT::*callback)(), 114 HostT* callback_host, 115 uint32_t id = 0) { 116 scoped_refptr<AsyncClosure> closure( 117 new RefCountedObject<NotifyingAsyncClosure<void, FunctorT, HostT> >( 118 this, Thread::Current(), functor, callback, callback_host)); 119 DoInvoke(thread, closure, id); 120 } 121 122 // Synchronously execute on |thread| all outstanding calls we own 123 // that are pending on |thread|, and wait for calls to complete 124 // before returning. Optionally filter by message id. 125 // The destructor will not wait for outstanding calls, so if that 126 // behavior is desired, call Flush() before destroying this object. 127 void Flush(Thread* thread, uint32_t id = MQID_ANY); 128 129 // Signaled when this object is destructed. 130 sigslot::signal0<> SignalInvokerDestroyed; 131 132 private: 133 void OnMessage(Message* msg) override; 134 void DoInvoke(Thread* thread, 135 const scoped_refptr<AsyncClosure>& closure, 136 uint32_t id); 137 void DoInvokeDelayed(Thread* thread, 138 const scoped_refptr<AsyncClosure>& closure, 139 uint32_t delay_ms, 140 uint32_t id); 141 bool destroying_; 142 143 RTC_DISALLOW_COPY_AND_ASSIGN(AsyncInvoker); 144 }; 145 146 // Similar to AsyncInvoker, but guards against the Thread being destroyed while 147 // there are outstanding dangling pointers to it. It will connect to the current 148 // thread in the constructor, and will get notified when that thread is 149 // destroyed. After GuardedAsyncInvoker is constructed, it can be used from 150 // other threads to post functors to the thread it was constructed on. If that 151 // thread dies, any further calls to AsyncInvoke() will be safely ignored. 152 class GuardedAsyncInvoker : public sigslot::has_slots<> { 153 public: 154 GuardedAsyncInvoker(); 155 ~GuardedAsyncInvoker() override; 156 157 // Synchronously execute all outstanding calls we own, and wait for calls to 158 // complete before returning. Optionally filter by message id. The destructor 159 // will not wait for outstanding calls, so if that behavior is desired, call 160 // Flush() first. Returns false if the thread has died. 161 bool Flush(uint32_t id = MQID_ANY); 162 163 // Call |functor| asynchronously with no callback upon completion. Returns 164 // immediately. Returns false if the thread has died. 165 template <class ReturnT, class FunctorT> 166 bool AsyncInvoke(const FunctorT& functor, uint32_t id = 0) { 167 rtc::CritScope cs(&crit_); 168 if (thread_ == nullptr) 169 return false; 170 invoker_.AsyncInvoke<ReturnT, FunctorT>(thread_, functor, id); 171 return true; 172 } 173 174 // Call |functor| asynchronously with |delay_ms|, with no callback upon 175 // completion. Returns immediately. Returns false if the thread has died. 176 template <class ReturnT, class FunctorT> 177 bool AsyncInvokeDelayed(const FunctorT& functor, 178 uint32_t delay_ms, 179 uint32_t id = 0) { 180 rtc::CritScope cs(&crit_); 181 if (thread_ == nullptr) 182 return false; 183 invoker_.AsyncInvokeDelayed<ReturnT, FunctorT>(thread_, functor, delay_ms, 184 id); 185 return true; 186 } 187 188 // Call |functor| asynchronously, calling |callback| when done. Returns false 189 // if the thread has died. 190 template <class ReturnT, class FunctorT, class HostT> 191 bool AsyncInvoke(const FunctorT& functor, 192 void (HostT::*callback)(ReturnT), 193 HostT* callback_host, 194 uint32_t id = 0) { 195 rtc::CritScope cs(&crit_); 196 if (thread_ == nullptr) 197 return false; 198 invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(thread_, functor, callback, 199 callback_host, id); 200 return true; 201 } 202 203 // Call |functor| asynchronously calling |callback| when done. Overloaded for 204 // void return. Returns false if the thread has died. 205 template <class ReturnT, class FunctorT, class HostT> 206 bool AsyncInvoke(const FunctorT& functor, 207 void (HostT::*callback)(), 208 HostT* callback_host, 209 uint32_t id = 0) { 210 rtc::CritScope cs(&crit_); 211 if (thread_ == nullptr) 212 return false; 213 invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(thread_, functor, callback, 214 callback_host, id); 215 return true; 216 } 217 218 private: 219 // Callback when |thread_| is destroyed. 220 void ThreadDestroyed(); 221 222 CriticalSection crit_; 223 Thread* thread_ GUARDED_BY(crit_); 224 AsyncInvoker invoker_ GUARDED_BY(crit_); 225 }; 226 227 } // namespace rtc 228 229 #endif // WEBRTC_BASE_ASYNCINVOKER_H_ 230