rtc::Thread::PostTask() added.
This method allows asynchronously posting tasks, in the form of
functors to be invoked, on the thread represented by rtc::Thread.
This CL removes PostMessageWithFunctor(), putting the implementation of
it directly into rtc::Thread::PostTask(), and moves & updates the test
coverage to thread_unittest.cc.
Bug: webrtc:10294, webrtc:10293
Change-Id: Ic6cc3e2533a4f7aaff141aff28e9bb3908ee3c96
Reviewed-on: https://webrtc-review.googlesource.com/c/124701
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26894}
diff --git a/rtc_base/thread.h b/rtc_base/thread.h
index 3ba3010..7bb7a3c 100644
--- a/rtc_base/thread.h
+++ b/rtc_base/thread.h
@@ -36,6 +36,29 @@
class Thread;
+namespace rtc_thread_internal {
+
+template <class FunctorT>
+class SingleMessageHandlerWithFunctor final : public MessageHandler {
+ public:
+ explicit SingleMessageHandlerWithFunctor(FunctorT&& functor)
+ : functor_(std::forward<FunctorT>(functor)) {}
+
+ void OnMessage(Message* msg) override {
+ functor_();
+ delete this;
+ }
+
+ private:
+ ~SingleMessageHandlerWithFunctor() override {}
+
+ typename std::remove_reference<FunctorT>::type functor_;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(SingleMessageHandlerWithFunctor);
+};
+
+} // namespace rtc_thread_internal
+
class ThreadManager {
public:
static const int kForever = -1;
@@ -183,6 +206,8 @@
// &MyFunctionReturningBool);
// NOTE: This function can only be called when synchronous calls are allowed.
// See ScopedDisallowBlockingCalls for details.
+ // NOTE: Blocking invokes are DISCOURAGED, consider if what you're doing can
+ // be achieved with PostTask() and callbacks instead.
template <class ReturnT, class FunctorT>
ReturnT Invoke(const Location& posted_from, FunctorT&& functor) {
FunctorMessageHandler<ReturnT, FunctorT> handler(
@@ -191,6 +216,44 @@
return handler.MoveResult();
}
+ // Posts a task to invoke the functor on |this| thread asynchronously, i.e.
+ // without blocking the thread that invoked PostTask(). Ownership of |functor|
+ // is passed and destroyed on |this| thread after it is invoked.
+ // Requirements of FunctorT:
+ // - FunctorT is movable.
+ // - FunctorT implements "T operator()()" or "T operator()() const" for some T
+ // (if T is not void, the return value is discarded on |this| thread).
+ // - FunctorT has a public destructor that can be invoked from |this| thread
+ // after operation() has been invoked.
+ // - The functor must not cause the thread to quit before PostTask() is done.
+ //
+ // Example - Calling a class method:
+ // class Foo {
+ // public:
+ // void DoTheThing();
+ // };
+ // Foo foo;
+ // thread->PostTask(RTC_FROM_HERE, Bind(&Foo::DoTheThing, &foo));
+ //
+ // Example - Calling a lambda function:
+ // thread->PostTask(RTC_FROM_HERE,
+ // [&x, &y] { x.TrackComputations(y.Compute()); });
+ template <class FunctorT>
+ void PostTask(const Location& posted_from, FunctorT&& functor) {
+ Post(posted_from,
+ new rtc_thread_internal::SingleMessageHandlerWithFunctor<FunctorT>(
+ std::forward<FunctorT>(functor)));
+ // This DCHECK guarantees that the post was successful.
+ // Post() doesn't say whether it succeeded, but it will only fail if the
+ // thread is quitting. DCHECKing that the thread is not quitting *after*
+ // posting might yield some false positives (where the thread did in fact
+ // quit, but only after posting), but if we have false positives here then
+ // we have a race condition anyway.
+ // TODO(https://crbug.com/webrtc/10364): When Post() returns a bool we can
+ // DCHECK the result instead of inferring success from IsQuitting().
+ RTC_DCHECK(!IsQuitting());
+ }
+
// From MessageQueue
bool IsProcessingMessagesForTesting() override;
void Clear(MessageHandler* phandler,