blob: 43fffeac10568526755d097ec9b167f83811a001 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
deadbeefa8bc1a12017-02-17 18:06:26 -080014#include <memory>
15#include <utility>
16
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000017#include "webrtc/base/asyncinvoker-inl.h"
18#include "webrtc/base/bind.h"
kwiberg4485ffb2016-04-26 08:14:39 -070019#include "webrtc/base/constructormagic.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020#include "webrtc/base/sigslot.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021#include "webrtc/base/thread.h"
22
23namespace rtc {
24
25// Invokes function objects (aka functors) asynchronously on a Thread, and
26// owns the lifetime of calls (ie, when this object is destroyed, calls in
27// flight are cancelled). AsyncInvoker can optionally execute a user-specified
28// function when the asynchronous call is complete, or operates in
29// fire-and-forget mode otherwise.
30//
31// AsyncInvoker does not own the thread it calls functors on.
32//
33// A note about async calls and object lifetimes: users should
34// be mindful of object lifetimes when calling functions asynchronously and
35// ensure objects used by the function _cannot_ be deleted between the
36// invocation and execution of the functor. AsyncInvoker is designed to
37// help: any calls in flight will be cancelled when the AsyncInvoker used to
38// make the call is destructed, and any calls executing will be allowed to
39// complete before AsyncInvoker destructs.
40//
41// The easiest way to ensure lifetimes are handled correctly is to create a
42// class that owns the Thread and AsyncInvoker objects, and then call its
43// methods asynchronously as needed.
44//
45// Example:
46// class MyClass {
47// public:
48// void FireAsyncTaskWithResult(Thread* thread, int x) {
49// // Specify a callback to get the result upon completion.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070050// invoker_.AsyncInvoke<int>(RTC_FROM_HERE,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051// thread, Bind(&MyClass::AsyncTaskWithResult, this, x),
52// &MyClass::OnTaskComplete, this);
53// }
54// void FireAnotherAsyncTask(Thread* thread) {
55// // No callback specified means fire-and-forget.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070056// invoker_.AsyncInvoke<void>(RTC_FROM_HERE,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000057// thread, Bind(&MyClass::AnotherAsyncTask, this));
58//
59// private:
60// int AsyncTaskWithResult(int x) {
61// // Some long running process...
62// return x * x;
63// }
64// void AnotherAsyncTask() {
65// // Some other long running process...
66// }
67// void OnTaskComplete(int result) { result_ = result; }
68//
69// AsyncInvoker invoker_;
70// int result_;
71// };
72class AsyncInvoker : public MessageHandler {
73 public:
74 AsyncInvoker();
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000075 ~AsyncInvoker() override;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000076
77 // Call |functor| asynchronously on |thread|, with no callback upon
78 // completion. Returns immediately.
79 template <class ReturnT, class FunctorT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070080 void AsyncInvoke(const Location& posted_from,
81 Thread* thread,
82 const FunctorT& functor,
83 uint32_t id = 0) {
deadbeefa8bc1a12017-02-17 18:06:26 -080084 std::unique_ptr<AsyncClosure> closure(
85 new FireAndForgetAsyncClosure<FunctorT>(functor));
86 DoInvoke(posted_from, thread, std::move(closure), id);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000087 }
88
Guo-wei Shiehdc13abc2015-06-18 14:44:41 -070089 // Call |functor| asynchronously on |thread| with |delay_ms|, with no callback
90 // upon completion. Returns immediately.
91 template <class ReturnT, class FunctorT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -070092 void AsyncInvokeDelayed(const Location& posted_from,
93 Thread* thread,
Guo-wei Shiehdc13abc2015-06-18 14:44:41 -070094 const FunctorT& functor,
Peter Boström0c4e06b2015-10-07 12:23:21 +020095 uint32_t delay_ms,
96 uint32_t id = 0) {
deadbeefa8bc1a12017-02-17 18:06:26 -080097 std::unique_ptr<AsyncClosure> closure(
98 new FireAndForgetAsyncClosure<FunctorT>(functor));
99 DoInvokeDelayed(posted_from, thread, std::move(closure), delay_ms, id);
Guo-wei Shiehdc13abc2015-06-18 14:44:41 -0700100 }
101
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000102 // Call |functor| asynchronously on |thread|, calling |callback| when done.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700103 // Uses a separate Location for |callback_posted_from| so that the functor
104 // invoke and the callback invoke can be differentiated.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000105 template <class ReturnT, class FunctorT, class HostT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700106 void AsyncInvoke(const Location& posted_from,
107 const Location& callback_posted_from,
108 Thread* thread,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000109 const FunctorT& functor,
110 void (HostT::*callback)(ReturnT),
111 HostT* callback_host,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200112 uint32_t id = 0) {
deadbeefa8bc1a12017-02-17 18:06:26 -0800113 std::unique_ptr<AsyncClosure> closure(
114 new NotifyingAsyncClosure<ReturnT, FunctorT, HostT>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700115 this, callback_posted_from, Thread::Current(), functor, callback,
116 callback_host));
deadbeefa8bc1a12017-02-17 18:06:26 -0800117 DoInvoke(posted_from, thread, std::move(closure), id);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000118 }
119
120 // Call |functor| asynchronously on |thread|, calling |callback| when done.
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700121 // Uses a separate Location for |callback_posted_from| so that the functor
122 // invoke and the callback invoke can be differentiated.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000123 // Overloaded for void return.
124 template <class ReturnT, class FunctorT, class HostT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700125 void AsyncInvoke(const Location& posted_from,
126 const Location& callback_posted_from,
127 Thread* thread,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000128 const FunctorT& functor,
129 void (HostT::*callback)(),
130 HostT* callback_host,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200131 uint32_t id = 0) {
deadbeefa8bc1a12017-02-17 18:06:26 -0800132 std::unique_ptr<AsyncClosure> closure(
133 new NotifyingAsyncClosure<void, FunctorT, HostT>(
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700134 this, callback_posted_from, Thread::Current(), functor, callback,
135 callback_host));
deadbeefa8bc1a12017-02-17 18:06:26 -0800136 DoInvoke(posted_from, thread, std::move(closure), id);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000137 }
138
139 // Synchronously execute on |thread| all outstanding calls we own
140 // that are pending on |thread|, and wait for calls to complete
141 // before returning. Optionally filter by message id.
142 // The destructor will not wait for outstanding calls, so if that
143 // behavior is desired, call Flush() before destroying this object.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200144 void Flush(Thread* thread, uint32_t id = MQID_ANY);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000145
146 // Signaled when this object is destructed.
147 sigslot::signal0<> SignalInvokerDestroyed;
148
149 private:
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +0000150 void OnMessage(Message* msg) override;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700151 void DoInvoke(const Location& posted_from,
152 Thread* thread,
deadbeefa8bc1a12017-02-17 18:06:26 -0800153 std::unique_ptr<AsyncClosure> closure,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200154 uint32_t id);
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700155 void DoInvokeDelayed(const Location& posted_from,
156 Thread* thread,
deadbeefa8bc1a12017-02-17 18:06:26 -0800157 std::unique_ptr<AsyncClosure> closure,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200158 uint32_t delay_ms,
159 uint32_t id);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000160 bool destroying_;
161
henrikg3c089d72015-09-16 05:37:44 -0700162 RTC_DISALLOW_COPY_AND_ASSIGN(AsyncInvoker);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000163};
164
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200165// Similar to AsyncInvoker, but guards against the Thread being destroyed while
166// there are outstanding dangling pointers to it. It will connect to the current
167// thread in the constructor, and will get notified when that thread is
168// destroyed. After GuardedAsyncInvoker is constructed, it can be used from
169// other threads to post functors to the thread it was constructed on. If that
170// thread dies, any further calls to AsyncInvoke() will be safely ignored.
171class GuardedAsyncInvoker : public sigslot::has_slots<> {
172 public:
173 GuardedAsyncInvoker();
174 ~GuardedAsyncInvoker() override;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000175
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200176 // Synchronously execute all outstanding calls we own, and wait for calls to
177 // complete before returning. Optionally filter by message id. The destructor
178 // will not wait for outstanding calls, so if that behavior is desired, call
179 // Flush() first. Returns false if the thread has died.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200180 bool Flush(uint32_t id = MQID_ANY);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200181
182 // Call |functor| asynchronously with no callback upon completion. Returns
183 // immediately. Returns false if the thread has died.
184 template <class ReturnT, class FunctorT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700185 bool AsyncInvoke(const Location& posted_from,
186 const FunctorT& functor,
187 uint32_t id = 0) {
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200188 rtc::CritScope cs(&crit_);
189 if (thread_ == nullptr)
190 return false;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700191 invoker_.AsyncInvoke<ReturnT, FunctorT>(posted_from, thread_, functor, id);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200192 return true;
193 }
194
195 // Call |functor| asynchronously with |delay_ms|, with no callback upon
196 // completion. Returns immediately. Returns false if the thread has died.
197 template <class ReturnT, class FunctorT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700198 bool AsyncInvokeDelayed(const Location& posted_from,
199 const FunctorT& functor,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200200 uint32_t delay_ms,
201 uint32_t id = 0) {
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200202 rtc::CritScope cs(&crit_);
203 if (thread_ == nullptr)
204 return false;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700205 invoker_.AsyncInvokeDelayed<ReturnT, FunctorT>(posted_from, thread_,
206 functor, delay_ms, id);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200207 return true;
208 }
209
210 // Call |functor| asynchronously, calling |callback| when done. Returns false
211 // if the thread has died.
212 template <class ReturnT, class FunctorT, class HostT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700213 bool AsyncInvoke(const Location& posted_from,
214 const Location& callback_posted_from,
215 const FunctorT& functor,
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200216 void (HostT::*callback)(ReturnT),
217 HostT* callback_host,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200218 uint32_t id = 0) {
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200219 rtc::CritScope cs(&crit_);
220 if (thread_ == nullptr)
221 return false;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700222 invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(
223 posted_from, callback_posted_from, thread_, functor, callback,
224 callback_host, id);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200225 return true;
226 }
227
228 // Call |functor| asynchronously calling |callback| when done. Overloaded for
229 // void return. Returns false if the thread has died.
230 template <class ReturnT, class FunctorT, class HostT>
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700231 bool AsyncInvoke(const Location& posted_from,
232 const Location& callback_posted_from,
233 const FunctorT& functor,
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200234 void (HostT::*callback)(),
235 HostT* callback_host,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200236 uint32_t id = 0) {
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200237 rtc::CritScope cs(&crit_);
238 if (thread_ == nullptr)
239 return false;
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700240 invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(
241 posted_from, callback_posted_from, thread_, functor, callback,
242 callback_host, id);
Magnus Jedverta1f590f2015-08-20 16:42:42 +0200243 return true;
244 }
245
246 private:
247 // Callback when |thread_| is destroyed.
248 void ThreadDestroyed();
249
250 CriticalSection crit_;
251 Thread* thread_ GUARDED_BY(crit_);
252 AsyncInvoker invoker_ GUARDED_BY(crit_);
253};
254
255} // namespace rtc
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000256
257#endif // WEBRTC_BASE_ASYNCINVOKER_H_