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