Let EventBase::runInEventBaseThreadAndWait consume its argument
authorYedidya Feldblum <yfeldblum@fb.com>
Sat, 7 Oct 2017 01:04:56 +0000 (18:04 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sat, 7 Oct 2017 01:11:44 +0000 (18:11 -0700)
Summary:
[Folly] Let `EventBase::runInEventBaseThreadAndWait` consume its argument.

Likewise `EventBase::runImmediatelyOrRunInEventBaseThreadAndWait`.

And enforce that the function is destructed before returning, so that, in the case of a wrapped lambda, all captured objects' destructors run before returning from the function.

Reviewed By: elsteveogrande

Differential Revision: D5994106

fbshipit-source-id: 816c9431a85a3d41e4fda321065614f4c18f0697

folly/io/async/EventBase.cpp
folly/io/async/EventBase.h

index 7ef3c8a3fe24ee7d438664eb721d7f2dd2b268e4..56f92c8debd90ac4fa2cca29f2e6c89fc4b7acfe 100644 (file)
@@ -566,7 +566,7 @@ bool EventBase::runInEventBaseThread(Func fn) {
   return true;
 }
 
-bool EventBase::runInEventBaseThreadAndWait(FuncRef fn) {
+bool EventBase::runInEventBaseThreadAndWait(Func fn) {
   if (inRunningEventBaseThread()) {
     LOG(ERROR) << "EventBase " << this << ": Waiting in the event loop is not "
                << "allowed";
@@ -574,18 +574,20 @@ bool EventBase::runInEventBaseThreadAndWait(FuncRef fn) {
   }
 
   Baton<> ready;
-  runInEventBaseThread([&] {
+  runInEventBaseThread([&ready, fn = std::move(fn)]() mutable {
     SCOPE_EXIT {
       ready.post();
     };
-    fn();
+    // A trick to force the stored functor to be executed and then destructed
+    // before posting the baton and waking the waiting thread.
+    copy(std::move(fn))();
   });
   ready.wait();
 
   return true;
 }
 
-bool EventBase::runImmediatelyOrRunInEventBaseThreadAndWait(FuncRef fn) {
+bool EventBase::runImmediatelyOrRunInEventBaseThreadAndWait(Func fn) {
   if (isInEventBaseThread()) {
     fn();
     return true;
index fff75adb00527d7938c528a07b4894ff4d730ef5..ee7ceca7d06c7fa9d0ee782c3bae8f198ec3e05e 100644 (file)
@@ -127,7 +127,6 @@ class EventBase : private boost::noncopyable,
                   public DrivableExecutor {
  public:
   using Func = folly::Function<void()>;
-  using FuncRef = folly::FunctionRef<void()>;
 
   /**
    * A callback interface to use with runInLoop()
@@ -417,7 +416,7 @@ class EventBase : private boost::noncopyable,
    * Like runInEventBaseThread, but the caller waits for the callback to be
    * executed.
    */
-  bool runInEventBaseThreadAndWait(FuncRef fn);
+  bool runInEventBaseThreadAndWait(Func fn);
 
   /*
    * Like runInEventBaseThreadAndWait, except if the caller is already in the
@@ -430,7 +429,7 @@ class EventBase : private boost::noncopyable,
    * Like runInEventBaseThreadAndWait, except if the caller is already in the
    * event base thread, the functor is simply run inline.
    */
-  bool runImmediatelyOrRunInEventBaseThreadAndWait(FuncRef fn);
+  bool runImmediatelyOrRunInEventBaseThreadAndWait(Func fn);
 
   /**
    * Set the maximum desired latency in us and provide a callback which will be