Add helper class GuardedAsyncInvoker to protect against thread dying
BUG=webrtc:4909 R=tommi@webrtc.org Review URL: https://codereview.webrtc.org/1303443003 . Cr-Commit-Position: refs/heads/master@{#9745}
This commit is contained in:
@ -144,7 +144,87 @@ class AsyncInvoker : public MessageHandler {
|
||||
DISALLOW_COPY_AND_ASSIGN(AsyncInvoker);
|
||||
};
|
||||
|
||||
// Similar to AsyncInvoker, but guards against the Thread being destroyed while
|
||||
// there are outstanding dangling pointers to it. It will connect to the current
|
||||
// thread in the constructor, and will get notified when that thread is
|
||||
// destroyed. After GuardedAsyncInvoker is constructed, it can be used from
|
||||
// other threads to post functors to the thread it was constructed on. If that
|
||||
// thread dies, any further calls to AsyncInvoke() will be safely ignored.
|
||||
class GuardedAsyncInvoker : public sigslot::has_slots<> {
|
||||
public:
|
||||
GuardedAsyncInvoker();
|
||||
~GuardedAsyncInvoker() override;
|
||||
|
||||
// Synchronously execute all outstanding calls we own, and wait for calls to
|
||||
// complete before returning. Optionally filter by message id. The destructor
|
||||
// will not wait for outstanding calls, so if that behavior is desired, call
|
||||
// Flush() first. Returns false if the thread has died.
|
||||
bool Flush(uint32 id = MQID_ANY);
|
||||
|
||||
// Call |functor| asynchronously with no callback upon completion. Returns
|
||||
// immediately. Returns false if the thread has died.
|
||||
template <class ReturnT, class FunctorT>
|
||||
bool AsyncInvoke(const FunctorT& functor, uint32 id = 0) {
|
||||
rtc::CritScope cs(&crit_);
|
||||
if (thread_ == nullptr)
|
||||
return false;
|
||||
invoker_.AsyncInvoke<ReturnT, FunctorT>(thread_, functor, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Call |functor| asynchronously with |delay_ms|, with no callback upon
|
||||
// completion. Returns immediately. Returns false if the thread has died.
|
||||
template <class ReturnT, class FunctorT>
|
||||
bool AsyncInvokeDelayed(const FunctorT& functor,
|
||||
uint32 delay_ms,
|
||||
uint32 id = 0) {
|
||||
rtc::CritScope cs(&crit_);
|
||||
if (thread_ == nullptr)
|
||||
return false;
|
||||
invoker_.AsyncInvokeDelayed<ReturnT, FunctorT>(thread_, functor, delay_ms,
|
||||
id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Call |functor| asynchronously, calling |callback| when done. Returns false
|
||||
// if the thread has died.
|
||||
template <class ReturnT, class FunctorT, class HostT>
|
||||
bool AsyncInvoke(const FunctorT& functor,
|
||||
void (HostT::*callback)(ReturnT),
|
||||
HostT* callback_host,
|
||||
uint32 id = 0) {
|
||||
rtc::CritScope cs(&crit_);
|
||||
if (thread_ == nullptr)
|
||||
return false;
|
||||
invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(thread_, functor, callback,
|
||||
callback_host, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Call |functor| asynchronously calling |callback| when done. Overloaded for
|
||||
// void return. Returns false if the thread has died.
|
||||
template <class ReturnT, class FunctorT, class HostT>
|
||||
bool AsyncInvoke(const FunctorT& functor,
|
||||
void (HostT::*callback)(),
|
||||
HostT* callback_host,
|
||||
uint32 id = 0) {
|
||||
rtc::CritScope cs(&crit_);
|
||||
if (thread_ == nullptr)
|
||||
return false;
|
||||
invoker_.AsyncInvoke<ReturnT, FunctorT, HostT>(thread_, functor, callback,
|
||||
callback_host, id);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// Callback when |thread_| is destroyed.
|
||||
void ThreadDestroyed();
|
||||
|
||||
CriticalSection crit_;
|
||||
Thread* thread_ GUARDED_BY(crit_);
|
||||
AsyncInvoker invoker_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
|
||||
#endif // WEBRTC_BASE_ASYNCINVOKER_H_
|
||||
|
||||
Reference in New Issue
Block a user