diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-19 03:15:59 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-19 03:15:59 +0000 |
commit | 2041cf34db4b3b9e43f9c63a57975798c0677ad7 (patch) | |
tree | 5caa67abfd19b51f124c17ac0c6a68eca0d9e860 /base | |
parent | cf03da1cccdc0bae0ced1dcf599c8a74324a1577 (diff) | |
download | chromium_src-2041cf34db4b3b9e43f9c63a57975798c0677ad7.zip chromium_src-2041cf34db4b3b9e43f9c63a57975798c0677ad7.tar.gz chromium_src-2041cf34db4b3b9e43f9c63a57975798c0677ad7.tar.bz2 |
Pulled out Callback code into base/callback.h. This is the first step towards redoing the Callback interfaces.
Added and removed includes as needed.
BUG=35223
TEST=trybots
Review URL: http://codereview.chromium.org/646061
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39419 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gyp | 2 | ||||
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/callback.h | 252 | ||||
-rw-r--r-- | base/callback_unittest.cc (renamed from base/task_unittest.cc) | 6 | ||||
-rw-r--r-- | base/observer_list_threadsafe.h | 1 | ||||
-rw-r--r-- | base/task.h | 242 |
6 files changed, 258 insertions, 246 deletions
diff --git a/base/base.gyp b/base/base.gyp index f4720b4..478b0ca 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -52,6 +52,7 @@ 'atomicops_unittest.cc', 'base64_unittest.cc', 'bits_unittest.cc', + 'callback_unittest.cc', 'cancellation_flag_unittest.cc', 'command_line_unittest.cc', 'condition_variable_unittest.cc', @@ -114,7 +115,6 @@ 'sys_info_unittest.cc', 'sys_string_conversions_mac_unittest.mm', 'sys_string_conversions_unittest.cc', - 'task_unittest.cc', 'thread_collision_warner_unittest.cc', 'thread_local_storage_unittest.cc', 'thread_local_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index 9cd768b..66094b9d 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -40,6 +40,7 @@ 'basictypes.h', 'bits.h', 'bzip2_error_handler.cc', + 'callback.h', 'cancellation_flag.h', 'cancellation_flag.cc', 'chrome_application_mac.h', diff --git a/base/callback.h b/base/callback.h new file mode 100644 index 0000000..17a1adc --- /dev/null +++ b/base/callback.h @@ -0,0 +1,252 @@ +// Copyright (c) 2010 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 BASE_CALLBACK_H_ +#define BASE_CALLBACK_H_ + +#include "base/tuple.h" +#include "base/raw_scoped_refptr_mismatch_checker.h" + +// Callback -------------------------------------------------------------------- +// +// A Callback is like a Task but with unbound parameters. It is basically an +// object-oriented function pointer. +// +// Callbacks are designed to work with Tuples. A set of helper functions and +// classes is provided to hide the Tuple details from the consumer. Client +// code will generally work with the CallbackRunner base class, which merely +// provides a Run method and is returned by the New* functions. This allows +// users to not care which type of class implements the callback, only that it +// has a certain number and type of arguments. +// +// The implementation of this is done by CallbackImpl, which inherits +// CallbackStorage to store the data. This allows the storage of the data +// (requiring the class type T) to be hidden from users, who will want to call +// this regardless of the implementor's type T. +// +// Note that callbacks currently have no facility for cancelling or abandoning +// them. We currently handle this at a higher level for cases where this is +// necessary. The pointer in a callback must remain valid until the callback +// is made. +// +// Like Task, the callback executor is responsible for deleting the callback +// pointer once the callback has executed. +// +// Example client usage: +// void Object::DoStuff(int, string); +// Callback2<int, string>::Type* callback = +// NewCallback(obj, &Object::DoStuff); +// callback->Run(5, string("hello")); +// delete callback; +// or, equivalently, using tuples directly: +// CallbackRunner<Tuple2<int, string> >* callback = +// NewCallback(obj, &Object::DoStuff); +// callback->RunWithParams(MakeTuple(5, string("hello"))); +// +// There is also a 0-args version that returns a value. Example: +// int Object::GetNextInt(); +// CallbackWithReturnValue<int>::Type* callback = +// NewCallbackWithReturnValue(obj, &Object::GetNextInt); +// int next_int = callback->Run(); +// delete callback; + +// Base for all Callbacks that handles storage of the pointers. +template <class T, typename Method> +class CallbackStorage { + public: + CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) { + } + + protected: + T* obj_; + Method meth_; +}; + +// Interface that is exposed to the consumer, that does the actual calling +// of the method. +template <typename Params> +class CallbackRunner { + public: + typedef Params TupleType; + + virtual ~CallbackRunner() {} + virtual void RunWithParams(const Params& params) = 0; + + // Convenience functions so callers don't have to deal with Tuples. + inline void Run() { + RunWithParams(Tuple0()); + } + + template <typename Arg1> + inline void Run(const Arg1& a) { + RunWithParams(Params(a)); + } + + template <typename Arg1, typename Arg2> + inline void Run(const Arg1& a, const Arg2& b) { + RunWithParams(Params(a, b)); + } + + template <typename Arg1, typename Arg2, typename Arg3> + inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) { + RunWithParams(Params(a, b, c)); + } + + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> + inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) { + RunWithParams(Params(a, b, c, d)); + } + + template <typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> + inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, + const Arg4& d, const Arg5& e) { + RunWithParams(Params(a, b, c, d, e)); + } +}; + +template <class T, typename Method, typename Params> +class CallbackImpl : public CallbackStorage<T, Method>, + public CallbackRunner<Params> { + public: + CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) { + } + virtual void RunWithParams(const Params& params) { + // use "this->" to force C++ to look inside our templatized base class; see + // Effective C++, 3rd Ed, item 43, p210 for details. + DispatchToMethod(this->obj_, this->meth_, params); + } +}; + +// 0-arg implementation +struct Callback0 { + typedef CallbackRunner<Tuple0> Type; +}; + +template <class T> +typename Callback0::Type* NewCallback(T* object, void (T::*method)()) { + return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method); +} + +// 1-arg implementation +template <typename Arg1> +struct Callback1 { + typedef CallbackRunner<Tuple1<Arg1> > Type; +}; + +template <class T, typename Arg1> +typename Callback1<Arg1>::Type* NewCallback(T* object, + void (T::*method)(Arg1)) { + return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method); +} + +// 2-arg implementation +template <typename Arg1, typename Arg2> +struct Callback2 { + typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type; +}; + +template <class T, typename Arg1, typename Arg2> +typename Callback2<Arg1, Arg2>::Type* NewCallback( + T* object, + void (T::*method)(Arg1, Arg2)) { + return new CallbackImpl<T, void (T::*)(Arg1, Arg2), + Tuple2<Arg1, Arg2> >(object, method); +} + +// 3-arg implementation +template <typename Arg1, typename Arg2, typename Arg3> +struct Callback3 { + typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type; +}; + +template <class T, typename Arg1, typename Arg2, typename Arg3> +typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback( + T* object, + void (T::*method)(Arg1, Arg2, Arg3)) { + return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3), + Tuple3<Arg1, Arg2, Arg3> >(object, method); +} + +// 4-arg implementation +template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> +struct Callback4 { + typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type; +}; + +template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> +typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback( + T* object, + void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { + return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4), + Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method); +} + +// 5-arg implementation +template <typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +struct Callback5 { + typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type; +}; + +template <class T, typename Arg1, typename Arg2, + typename Arg3, typename Arg4, typename Arg5> +typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback( + T* object, + void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { + return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5), + Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method); +} + +// An UnboundMethod is a wrapper for a method where the actual object is +// provided at Run dispatch time. +template <class T, class Method, class Params> +class UnboundMethod { + public: + UnboundMethod(Method m, const Params& p) : m_(m), p_(p) { + COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value), + badunboundmethodparams); + } + void Run(T* obj) const { + DispatchToMethod(obj, m_, p_); + } + private: + Method m_; + Params p_; +}; + +// Return value implementation with no args. +template <typename ReturnValue> +struct CallbackWithReturnValue { + class Type { + public: + virtual ~Type() {} + virtual ReturnValue Run() = 0; + }; +}; + +template <class T, typename Method, typename ReturnValue> +class CallbackWithReturnValueImpl + : public CallbackStorage<T, Method>, + public CallbackWithReturnValue<ReturnValue>::Type { + public: + CallbackWithReturnValueImpl(T* obj, Method meth) + : CallbackStorage<T, Method>(obj, meth) {} + + virtual ReturnValue Run() { + return (this->obj_->*(this->meth_))(); + } + + protected: + virtual ~CallbackWithReturnValueImpl() {} +}; + +template <class T, typename ReturnValue> +typename CallbackWithReturnValue<ReturnValue>::Type* +NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) { + return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>( + object, method); +} + +#endif // BASE_CALLBACK_H diff --git a/base/task_unittest.cc b/base/callback_unittest.cc index 1fa7c9d..bc15927 100644 --- a/base/task_unittest.cc +++ b/base/callback_unittest.cc @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/callback.h" #include "base/scoped_ptr.h" -#include "base/task.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,7 +21,7 @@ class HelperObject { } // namespace -TEST(Task, OneArg) { +TEST(Callback, OneArg) { HelperObject obj; scoped_ptr<Callback1<int*>::Type> callback( NewCallback(&obj, &HelperObject::GetNextNumberArg)); @@ -31,7 +31,7 @@ TEST(Task, OneArg) { EXPECT_EQ(number, 1); } -TEST(Task, ReturnValue) { +TEST(Callback, ReturnValue) { HelperObject obj; scoped_ptr<CallbackWithReturnValue<int>::Type> callback( NewCallbackWithReturnValue(&obj, &HelperObject::GetNextNumber)); diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h index d0151f4..c0716dd 100644 --- a/base/observer_list_threadsafe.h +++ b/base/observer_list_threadsafe.h @@ -9,6 +9,7 @@ #include <algorithm> #include "base/basictypes.h" +#include "base/callback.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/observer_list.h" diff --git a/base/task.h b/base/task.h index 91ec520..0af79a4 100644 --- a/base/task.h +++ b/base/task.h @@ -454,246 +454,4 @@ inline CancelableTask* NewRunnableFunction(Function function, e)); } -// Callback -------------------------------------------------------------------- -// -// A Callback is like a Task but with unbound parameters. It is basically an -// object-oriented function pointer. -// -// Callbacks are designed to work with Tuples. A set of helper functions and -// classes is provided to hide the Tuple details from the consumer. Client -// code will generally work with the CallbackRunner base class, which merely -// provides a Run method and is returned by the New* functions. This allows -// users to not care which type of class implements the callback, only that it -// has a certain number and type of arguments. -// -// The implementation of this is done by CallbackImpl, which inherits -// CallbackStorage to store the data. This allows the storage of the data -// (requiring the class type T) to be hidden from users, who will want to call -// this regardless of the implementor's type T. -// -// Note that callbacks currently have no facility for cancelling or abandoning -// them. We currently handle this at a higher level for cases where this is -// necessary. The pointer in a callback must remain valid until the callback -// is made. -// -// Like Task, the callback executor is responsible for deleting the callback -// pointer once the callback has executed. -// -// Example client usage: -// void Object::DoStuff(int, string); -// Callback2<int, string>::Type* callback = -// NewCallback(obj, &Object::DoStuff); -// callback->Run(5, string("hello")); -// delete callback; -// or, equivalently, using tuples directly: -// CallbackRunner<Tuple2<int, string> >* callback = -// NewCallback(obj, &Object::DoStuff); -// callback->RunWithParams(MakeTuple(5, string("hello"))); -// -// There is also a 0-args version that returns a value. Example: -// int Object::GetNextInt(); -// CallbackWithReturnValue<int>::Type* callback = -// NewCallbackWithReturnValue(obj, &Object::GetNextInt); -// int next_int = callback->Run(); -// delete callback; - -// Base for all Callbacks that handles storage of the pointers. -template <class T, typename Method> -class CallbackStorage { - public: - CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) { - } - - protected: - T* obj_; - Method meth_; -}; - -// Interface that is exposed to the consumer, that does the actual calling -// of the method. -template <typename Params> -class CallbackRunner { - public: - typedef Params TupleType; - - virtual ~CallbackRunner() {} - virtual void RunWithParams(const Params& params) = 0; - - // Convenience functions so callers don't have to deal with Tuples. - inline void Run() { - RunWithParams(Tuple0()); - } - - template <typename Arg1> - inline void Run(const Arg1& a) { - RunWithParams(Params(a)); - } - - template <typename Arg1, typename Arg2> - inline void Run(const Arg1& a, const Arg2& b) { - RunWithParams(Params(a, b)); - } - - template <typename Arg1, typename Arg2, typename Arg3> - inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) { - RunWithParams(Params(a, b, c)); - } - - template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> - inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) { - RunWithParams(Params(a, b, c, d)); - } - - template <typename Arg1, typename Arg2, typename Arg3, - typename Arg4, typename Arg5> - inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, - const Arg4& d, const Arg5& e) { - RunWithParams(Params(a, b, c, d, e)); - } -}; - -template <class T, typename Method, typename Params> -class CallbackImpl : public CallbackStorage<T, Method>, - public CallbackRunner<Params> { - public: - CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) { - } - virtual void RunWithParams(const Params& params) { - // use "this->" to force C++ to look inside our templatized base class; see - // Effective C++, 3rd Ed, item 43, p210 for details. - DispatchToMethod(this->obj_, this->meth_, params); - } -}; - -// 0-arg implementation -struct Callback0 { - typedef CallbackRunner<Tuple0> Type; -}; - -template <class T> -typename Callback0::Type* NewCallback(T* object, void (T::*method)()) { - return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method); -} - -// 1-arg implementation -template <typename Arg1> -struct Callback1 { - typedef CallbackRunner<Tuple1<Arg1> > Type; -}; - -template <class T, typename Arg1> -typename Callback1<Arg1>::Type* NewCallback(T* object, - void (T::*method)(Arg1)) { - return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method); -} - -// 2-arg implementation -template <typename Arg1, typename Arg2> -struct Callback2 { - typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type; -}; - -template <class T, typename Arg1, typename Arg2> -typename Callback2<Arg1, Arg2>::Type* NewCallback( - T* object, - void (T::*method)(Arg1, Arg2)) { - return new CallbackImpl<T, void (T::*)(Arg1, Arg2), - Tuple2<Arg1, Arg2> >(object, method); -} - -// 3-arg implementation -template <typename Arg1, typename Arg2, typename Arg3> -struct Callback3 { - typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type; -}; - -template <class T, typename Arg1, typename Arg2, typename Arg3> -typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback( - T* object, - void (T::*method)(Arg1, Arg2, Arg3)) { - return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3), - Tuple3<Arg1, Arg2, Arg3> >(object, method); -} - -// 4-arg implementation -template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> -struct Callback4 { - typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type; -}; - -template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> -typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback( - T* object, - void (T::*method)(Arg1, Arg2, Arg3, Arg4)) { - return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4), - Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method); -} - -// 5-arg implementation -template <typename Arg1, typename Arg2, typename Arg3, - typename Arg4, typename Arg5> -struct Callback5 { - typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type; -}; - -template <class T, typename Arg1, typename Arg2, - typename Arg3, typename Arg4, typename Arg5> -typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback( - T* object, - void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) { - return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5), - Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method); -} - -// An UnboundMethod is a wrapper for a method where the actual object is -// provided at Run dispatch time. -template <class T, class Method, class Params> -class UnboundMethod { - public: - UnboundMethod(Method m, const Params& p) : m_(m), p_(p) { - COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value), - badunboundmethodparams); - } - void Run(T* obj) const { - DispatchToMethod(obj, m_, p_); - } - private: - Method m_; - Params p_; -}; - -// Return value implementation with no args. -template <typename ReturnValue> -struct CallbackWithReturnValue { - class Type { - public: - virtual ~Type() {} - virtual ReturnValue Run() = 0; - }; -}; - -template <class T, typename Method, typename ReturnValue> -class CallbackWithReturnValueImpl - : public CallbackStorage<T, Method>, - public CallbackWithReturnValue<ReturnValue>::Type { - public: - CallbackWithReturnValueImpl(T* obj, Method meth) - : CallbackStorage<T, Method>(obj, meth) {} - - virtual ReturnValue Run() { - return (this->obj_->*(this->meth_))(); - } - - protected: - virtual ~CallbackWithReturnValueImpl() {} -}; - -template <class T, typename ReturnValue> -typename CallbackWithReturnValue<ReturnValue>::Type* -NewCallbackWithReturnValue(T* object, ReturnValue (T::*method)()) { - return new CallbackWithReturnValueImpl<T, ReturnValue (T::*)(), ReturnValue>( - object, method); -} - - #endif // BASE_TASK_H_ |