Index: media/base/bind_to_loop.h.pump |
diff --git a/media/base/bind_to_loop.h.pump b/media/base/bind_to_loop.h.pump |
index 8490413eb1cc333cb2279712014f825c7487779c..b7e90714647ce8b7cc89cd489b5590c45ad07b1b 100644 |
--- a/media/base/bind_to_loop.h.pump |
+++ b/media/base/bind_to_loop.h.pump |
@@ -18,6 +18,7 @@ $var MAX_ARITY = 7 |
#include "base/bind.h" |
#include "base/location.h" |
#include "base/message_loop/message_loop_proxy.h" |
+#include "base/synchronization/waitable_event.h" |
// This is a helper utility for base::Bind()ing callbacks on to particular |
// MessageLoops. A typical use is when |a| (of class |A|) wants to hand a |
@@ -29,9 +30,19 @@ $var MAX_ARITY = 7 |
// media::BindToLoop(MessageLoopProxy::current(), |
// base::Bind(&MyClass::MyMethod, this))); |
// |
-// Note that like base::Bind(), BindToLoop() can't bind non-constant references, |
-// and that *unlike* base::Bind(), BindToLoop() makes copies of its arguments, |
-// and thus can't be used with arrays. |
+// For synchronous usage, where the callback needs to be executed on another |
+// MessageLoop, but the calling thread should block until the callback has been |
+// completed, there is BindToLoopSync(), as below: |
+// |
+// Typical usage: make a request to another thread, and wait for it: |
+// do_something_callback = |
+// media::BindToLoopSync(other_message_loop, &OtherClass::DoRequest, other); |
+// // ... |
+// do_something_callback.Run(); // will block until completion |
+// |
+// Note that like base::Bind(), BindToLoop() and BindToLoopSync() can't bind |
+// non-constant references, and that *unlike* base::Bind(), BindToLoop*() makes |
+// copies of its arguments, and thus can't be used with arrays. |
namespace media { |
@@ -55,6 +66,10 @@ base::internal::PassedWrapper<ScopedVector<T> > TrampolineForward( |
template <typename T> struct TrampolineHelper; |
+// Caller helper to call a base::Closure synchronously |
+void TrampolineSyncCaller(const base::Closure& closure, |
+ base::WaitableEvent* waiter); |
+ |
$range ARITY 0..MAX_ARITY |
$for ARITY [[ |
$range ARG 1..ARITY |
@@ -71,6 +86,24 @@ $for ARG , [[A$(ARG) a$(ARG)]] |
$if ARITY != 0 [[, ]] |
$for ARG , [[internal::TrampolineForward(a$(ARG))]])); |
} |
+ static void RunSync( |
+ const scoped_refptr<base::MessageLoopProxy>& loop, |
+ const base::Callback<void($for ARG , [[A$(ARG)]])>& cb |
+$if ARITY != 0 [[, ]] |
+$for ARG , [[A$(ARG) a$(ARG)]] |
+) { |
+ DCHECK(!loop->BelongsToCurrentThread()); |
+ base::WaitableEvent waiter(false, false); |
+ loop->PostTask( |
+ FROM_HERE, |
+ base::Bind( |
+ &TrampolineSyncCaller, |
+ base::Bind(cb |
+$if ARITY != 0 [[, ]] |
+$for ARG , [[internal::TrampolineForward(a$(ARG))]]), |
+ &waiter)); |
+ waiter.Wait(); |
+ } |
}; |
@@ -86,6 +119,13 @@ static base::Callback<T> BindToLoop( |
} |
template<typename T> |
+static base::Callback<T> BindToLoopSync( |
+ const scoped_refptr<base::MessageLoopProxy>& loop, |
+ const base::Callback<T>& cb) { |
+ return base::Bind(&internal::TrampolineHelper<T>::RunSync, loop, cb); |
+} |
+ |
+template<typename T> |
static base::Callback<T> BindToCurrentLoop( |
const base::Callback<T>& cb) { |
return BindToLoop(base::MessageLoopProxy::current(), cb); |