diff options
author | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-18 04:10:19 +0000 |
---|---|---|
committer | fischman@chromium.org <fischman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-18 04:10:19 +0000 |
commit | 2c539b896f7cd8e1ff6a1209418a5c7d15b3b6bc (patch) | |
tree | 71507e063e3510e1de2c30a41169f13359391e8d /media | |
parent | 546fc9db98435eb806293d51d824cec8388a4008 (diff) | |
download | chromium_src-2c539b896f7cd8e1ff6a1209418a5c7d15b3b6bc.zip chromium_src-2c539b896f7cd8e1ff6a1209418a5c7d15b3b6bc.tar.gz chromium_src-2c539b896f7cd8e1ff6a1209418a5c7d15b3b6bc.tar.bz2 |
media::BindToLoop() is born, with example uses to slim down WebMediaPlayerProxy.
WMPP could use further slimming-down / flamethrowering, but this pass just removes
the lowest-hanging fruit, where WMPP is used as a silent trampoline to WMPI on
the render thread.
Review URL: https://chromiumcodereview.appspot.com/10855188
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152239 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/bind_to_loop.h | 159 | ||||
-rw-r--r-- | media/base/bind_to_loop.h.pump | 71 | ||||
-rw-r--r-- | media/base/bind_to_loop_unittest.cc | 98 | ||||
-rw-r--r-- | media/media.gyp | 2 |
4 files changed, 330 insertions, 0 deletions
diff --git a/media/base/bind_to_loop.h b/media/base/bind_to_loop.h new file mode 100644 index 0000000..24f9419 --- /dev/null +++ b/media/base/bind_to_loop.h @@ -0,0 +1,159 @@ +// This file was GENERATED by command: +// pump.py bind_to_loop.h.pump +// DO NOT EDIT BY HAND!!! + + +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_BIND_TO_LOOP_H_ +#define MEDIA_BASE_BIND_TO_LOOP_H_ + +#include "base/bind.h" +#include "base/callback_internal.h" // Avoid re-inventing CallbackForward. +#include "base/location.h" +#include "base/message_loop_proxy.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 +// callback such as base::Bind(&A::AMethod, a) to |b|, but needs to ensure that +// when |b| executes the callback, it does so on a particular MessageLoop. +// +// Typical usage: request to be called back on the current thread: +// other->StartAsyncProcessAndCallMeBack( +// 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. + +namespace media { + +template <typename T> struct TrampolineHelper; + +template <> +struct TrampolineHelper<void()> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void()>& cb) { + loop->PostTask(FROM_HERE, base::Bind(cb)); + } +}; + + +template <typename A1> +struct TrampolineHelper<void(A1)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1)>& cb, A1 a1) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1))); + } +}; + + +template <typename A1, typename A2> +struct TrampolineHelper<void(A1, A2)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1, A2)>& cb, A1 a1, A2 a2) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1), + base::internal::CallbackForward(a2))); + } +}; + + +template <typename A1, typename A2, typename A3> +struct TrampolineHelper<void(A1, A2, A3)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1, A2, A3)>& cb, A1 a1, A2 a2, A3 a3) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1), + base::internal::CallbackForward(a2), + base::internal::CallbackForward(a3))); + } +}; + + +template <typename A1, typename A2, typename A3, typename A4> +struct TrampolineHelper<void(A1, A2, A3, A4)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1, A2, A3, A4)>& cb, A1 a1, A2 a2, A3 a3, + A4 a4) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1), + base::internal::CallbackForward(a2), + base::internal::CallbackForward(a3), + base::internal::CallbackForward(a4))); + } +}; + + +template <typename A1, typename A2, typename A3, typename A4, typename A5> +struct TrampolineHelper<void(A1, A2, A3, A4, A5)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1, A2, A3, A4, A5)>& cb, A1 a1, A2 a2, A3 a3, + A4 a4, A5 a5) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1), + base::internal::CallbackForward(a2), + base::internal::CallbackForward(a3), + base::internal::CallbackForward(a4), + base::internal::CallbackForward(a5))); + } +}; + + +template <typename A1, typename A2, typename A3, typename A4, typename A5, + typename A6> +struct TrampolineHelper<void(A1, A2, A3, A4, A5, A6)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1, A2, A3, A4, A5, A6)>& cb, A1 a1, A2 a2, + A3 a3, A4 a4, A5 a5, A6 a6) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1), + base::internal::CallbackForward(a2), + base::internal::CallbackForward(a3), + base::internal::CallbackForward(a4), + base::internal::CallbackForward(a5), + base::internal::CallbackForward(a6))); + } +}; + + +template <typename A1, typename A2, typename A3, typename A4, typename A5, + typename A6, typename A7> +struct TrampolineHelper<void(A1, A2, A3, A4, A5, A6, A7)> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void(A1, A2, A3, A4, A5, A6, A7)>& cb, A1 a1, A2 a2, + A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { + loop->PostTask(FROM_HERE, base::Bind(cb, + base::internal::CallbackForward(a1), + base::internal::CallbackForward(a2), + base::internal::CallbackForward(a3), + base::internal::CallbackForward(a4), + base::internal::CallbackForward(a5), + base::internal::CallbackForward(a6), + base::internal::CallbackForward(a7))); + } +}; + + +template<typename T> +static base::Callback<T> BindToLoop( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<T>& cb) { + return base::Bind(&TrampolineHelper<T>::Run, loop, cb); +} + +} // namespace media + +#endif // MEDIA_BASE_BIND_TO_LOOP_H_ diff --git a/media/base/bind_to_loop.h.pump b/media/base/bind_to_loop.h.pump new file mode 100644 index 0000000..a2b48bf --- /dev/null +++ b/media/base/bind_to_loop.h.pump @@ -0,0 +1,71 @@ +$$ This is a pump file for generating file templates. Pump is a python +$$ script that is part of the Google Test suite of utilities. Description +$$ can be found here: +$$ +$$ http://code.google.com/p/googletest/wiki/PumpManual +$$ + +$$ See comment for MAX_ARITY in base/bind.h.pump. +$var MAX_ARITY = 7 + +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_BIND_TO_LOOP_H_ +#define MEDIA_BASE_BIND_TO_LOOP_H_ + +#include "base/bind.h" +#include "base/callback_internal.h" // Avoid re-inventing CallbackForward. +#include "base/location.h" +#include "base/message_loop_proxy.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 +// callback such as base::Bind(&A::AMethod, a) to |b|, but needs to ensure that +// when |b| executes the callback, it does so on a particular MessageLoop. +// +// Typical usage: request to be called back on the current thread: +// other->StartAsyncProcessAndCallMeBack( +// 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. + +namespace media { + +template <typename T> struct TrampolineHelper; + +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +template <$for ARG , [[typename A$(ARG)]]> +struct TrampolineHelper<void($for ARG , [[A$(ARG)]])> { + static void Run( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<void($for ARG , [[A$(ARG)]])>& cb +$if ARITY != 0 [[, ]] +$for ARG , [[A$(ARG) a$(ARG)]] +) { + loop->PostTask(FROM_HERE, base::Bind(cb +$if ARITY != 0 [[, ]] +$for ARG , [[base::internal::CallbackForward(a$(ARG))]])); + } +}; + + +]] $$ for ARITY + +template<typename T> +static base::Callback<T> BindToLoop( + const scoped_refptr<base::MessageLoopProxy>& loop, + const base::Callback<T>& cb) { + return base::Bind(&TrampolineHelper<T>::Run, loop, cb); +} + +} // namespace media + +#endif // MEDIA_BASE_BIND_TO_LOOP_H_ diff --git a/media/base/bind_to_loop_unittest.cc b/media/base/bind_to_loop_unittest.cc new file mode 100644 index 0000000..fd9c93c --- /dev/null +++ b/media/base/bind_to_loop_unittest.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/bind_to_loop.h" + +#include "base/message_loop.h" +#include "base/synchronization/waitable_event.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +void BoundBoolSet(bool* var, bool val) { + *var = val; +} + +void BoundBoolSetFromScopedPtr(bool* var, scoped_ptr<bool> val) { + *var = *val; +} + +void BoundBoolSetFromConstRef(bool* var, const bool& val) { + *var = val; +} + +void BoundIntegersSet(int* a_var, int* b_var, int a_val, int b_val) { + *a_var = a_val; + *b_var = b_val; +} + +// Various tests that check that the bound function is only actually executed +// on the message loop, not during the original Run. +class BindToLoopTest : public ::testing::Test { + public: + BindToLoopTest() : proxy_(loop_.message_loop_proxy()) {} + + protected: + MessageLoop loop_; + scoped_refptr<base::MessageLoopProxy> proxy_; +}; + +TEST_F(BindToLoopTest, Closure) { + // Test the closure is run inside the loop, not outside it. + base::WaitableEvent waiter(false, false); + base::Closure cb = BindToLoop(proxy_, base::Bind( + &base::WaitableEvent::Signal, base::Unretained(&waiter))); + cb.Run(); + EXPECT_FALSE(waiter.IsSignaled()); + loop_.RunUntilIdle(); + EXPECT_TRUE(waiter.IsSignaled()); +} + +TEST_F(BindToLoopTest, Bool) { + bool bool_var = false; + base::Callback<void(bool)> cb = BindToLoop(proxy_, base::Bind( + &BoundBoolSet, &bool_var)); + cb.Run(true); + EXPECT_FALSE(bool_var); + loop_.RunUntilIdle(); + EXPECT_TRUE(bool_var); +} + +TEST_F(BindToLoopTest, ScopedPtrBool) { + bool bool_val = false; + scoped_ptr<bool> scoped_ptr_bool(new bool(true)); + base::Closure cb = BindToLoop(proxy_, base::Bind( + &BoundBoolSetFromScopedPtr, &bool_val, base::Passed(&scoped_ptr_bool))); + cb.Run(); + EXPECT_FALSE(bool_val); + loop_.RunUntilIdle(); + EXPECT_TRUE(bool_val); +} + +TEST_F(BindToLoopTest, BoolConstRef) { + bool bool_var = false; + bool true_var = true; + const bool& true_ref = true_var; + base::Closure cb = BindToLoop(proxy_, base::Bind( + &BoundBoolSetFromConstRef, &bool_var, true_ref)); + cb.Run(); + EXPECT_FALSE(bool_var); + loop_.RunUntilIdle(); + EXPECT_TRUE(bool_var); +} + +TEST_F(BindToLoopTest, Integers) { + int a = 0; + int b = 0; + base::Callback<void(int, int)> cb = BindToLoop(proxy_, base::Bind( + &BoundIntegersSet, &a, &b)); + cb.Run(1, -1); + EXPECT_EQ(a, 0); + EXPECT_EQ(b, 0); + loop_.RunUntilIdle(); + EXPECT_EQ(a, 1); + EXPECT_EQ(b, -1); +} + +} // namespace media diff --git a/media/media.gyp b/media/media.gyp index 89467dc..17e3c39 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -149,6 +149,7 @@ 'base/audio_renderer_mixer.h', 'base/audio_renderer_mixer_input.cc', 'base/audio_renderer_mixer_input.h', + 'base/bind_to_loop.h', 'base/bitstream_buffer.h', 'base/bit_reader.cc', 'base/bit_reader.h', @@ -702,6 +703,7 @@ 'base/audio_renderer_mixer_input_unittest.cc', 'base/audio_renderer_mixer_unittest.cc', 'base/bit_reader_unittest.cc', + 'base/bind_to_loop_unittest.cc', 'base/buffers_unittest.cc', 'base/clock_unittest.cc', 'base/data_buffer_unittest.cc', |