http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/bind_internal.h.pump ---------------------------------------------------------------------- diff --git a/be/src/gutil/bind_internal.h.pump b/be/src/gutil/bind_internal.h.pump new file mode 100644 index 0000000..1c8ad61 --- /dev/null +++ b/be/src/gutil/bind_internal.h.pump @@ -0,0 +1,464 @@ +$$ 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 gutil/bind.h.pump. +$var MAX_ARITY = 7 +$range ARITY 0..MAX_ARITY + +// Copyright (c) 2011 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 GUTIL_BIND_INTERNAL_H_ +#define GUTIL_BIND_INTERNAL_H_ + +#include "gutil/bind_helpers.h" +#include "gutil/callback_internal.h" +#include "gutil/raw_scoped_refptr_mismatch_checker.h" +#include "gutil/template_util.h" + +#if defined(OS_WIN) +#include "gutil/bind_internal_win.h" +#endif + +// During Chromium import, WeakPtr-related code was removed. + +namespace kudu { +namespace internal { + +// See gutil/callback.h for user documentation. +// +// +// CONCEPTS: +// Runnable -- A type (really a type class) that has a single Run() method +// and a RunType typedef that corresponds to the type of Run(). +// A Runnable can declare that it should treated like a method +// call by including a typedef named IsMethod. The value of +// this typedef is NOT inspected, only the existence. When a +// Runnable declares itself a method, Bind() will enforce special +// refcounting + WeakPtr handling semantics for the first +// parameter which is expected to be an object. +// Functor -- A copyable type representing something that should be called. +// All function pointers, Callback<>, and Runnables are functors +// even if the invocation syntax differs. +// RunType -- A function type (as opposed to function _pointer_ type) for +// a Run() function. Usually just a convenience typedef. +// (Bound)ArgsType -- A function type that is being (ab)used to store the +// types of set of arguments. The "return" type is always +// void here. We use this hack so that we do not need +// a new type name for each arity of type. (eg., +// BindState1, BindState2). This makes forward +// declarations and friending much much easier. +// +// Types: +// RunnableAdapter<> -- Wraps the various "function" pointer types into an +// object that adheres to the Runnable interface. +// There are |3*ARITY| RunnableAdapter types. +// FunctionTraits<> -- Type traits that unwrap a function signature into a +// a set of easier to use typedefs. Used mainly for +// compile time asserts. +// There are |ARITY| FunctionTraits types. +// ForceVoidReturn<> -- Helper class for translating function signatures to +// equivalent forms with a "void" return type. +// There are |ARITY| ForceVoidReturn types. +// FunctorTraits<> -- Type traits used determine the correct RunType and +// RunnableType for a Functor. This is where function +// signature adapters are applied. +// There are |ARITY| ForceVoidReturn types. +// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable +// type class that represents the underlying Functor. +// There are |O(1)| MakeRunnable types. +// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. +// Handle the differing syntaxes needed for WeakPtr<> support, +// and for ignoring return values. This is separate from +// Invoker to avoid creating multiple version of Invoker<> +// which grows at O(n^2) with the arity. +// There are |k*ARITY| InvokeHelper types. +// Invoker<> -- Unwraps the curried parameters and executes the Runnable. +// There are |(ARITY^2 + ARITY)/2| Invoketypes. +// BindState<> -- Stores the curried parameters, and is the main entry point +// into the Bind() system, doing most of the type resolution. +// There are ARITY BindState types. + +// RunnableAdapter<> +// +// The RunnableAdapter<> templates provide a uniform interface for invoking +// a function pointer, method pointer, or const method pointer. The adapter +// exposes a Run() method with an appropriate signature. Using this wrapper +// allows for writing code that supports all three pointer types without +// undue repetition. Without it, a lot of code would need to be repeated 3 +// times. +// +// For method pointers and const method pointers the first argument to Run() +// is considered to be the received of the method. This is similar to STL's +// mem_fun(). +// +// This class also exposes a RunType typedef that is the function type of the +// Run() function. +// +// If and only if the wrapper contains a method or const method pointer, an +// IsMethod typedef is exposed. The existence of this typedef (NOT the value) +// marks that the wrapper should be considered a method wrapper. + +template <typename Functor> +class RunnableAdapter; + +$for ARITY [[ +$range ARG 1..ARITY + +// Function: Arity $(ARITY). +template <typename R[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(*)($for ARG , [[A$(ARG)]])> { + public: + typedef R (RunType)($for ARG , [[A$(ARG)]]); + + explicit RunnableAdapter(R(*function)($for ARG , [[A$(ARG)]])) + : function_(function) { + } + + R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return function_($for ARG , [[CallbackForward(a$(ARG))]]); + } + + private: + R (*function_)($for ARG , [[A$(ARG)]]); +}; + +// Method: Arity $(ARITY). +template <typename R, typename T[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]])> { + public: + typedef R (RunType)(T*[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]); + typedef base::true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]])) + : method_(method) { + } + + R Run(T* object[[]] +$if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]); + } + + private: + R (T::*method_)($for ARG , [[A$(ARG)]]); +}; + +// Const Method: Arity $(ARITY). +template <typename R, typename T[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]]) const> { + public: + typedef R (RunType)(const T*[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]); + typedef base::true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]) const) + : method_(method) { + } + + R Run(const T* object[[]] +$if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return (object->*method_)($for ARG , [[CallbackForward(a$(ARG))]]); + } + + private: + R (T::*method_)($for ARG , [[A$(ARG)]]) const; +}; + +]] $$ for ARITY + + +// FunctionTraits<> +// +// Breaks a function signature apart into typedefs for easier introspection. +template <typename Sig> +struct FunctionTraits; + +$for ARITY [[ +$range ARG 1..ARITY + +template <typename R[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +struct FunctionTraits<R($for ARG , [[A$(ARG)]])> { + typedef R ReturnType; +$for ARG [[ + + typedef A$(ARG) A$(ARG)Type; +]] + +}; + +]] + + +// ForceVoidReturn<> +// +// Set of templates that support forcing the function return type to void. +template <typename Sig> +struct ForceVoidReturn; + +$for ARITY [[ +$range ARG 1..ARITY + +template <typename R[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +struct ForceVoidReturn<R($for ARG , [[A$(ARG)]])> { + typedef void(RunType)($for ARG , [[A$(ARG)]]); +}; + +]] $$ for ARITY + + +// FunctorTraits<> +// +// See description at top of file. +template <typename T> +struct FunctorTraits { + typedef RunnableAdapter<T> RunnableType; + typedef typename RunnableType::RunType RunType; +}; + +template <typename T> +struct FunctorTraits<IgnoreResultHelper<T> > { + typedef typename FunctorTraits<T>::RunnableType RunnableType; + typedef typename ForceVoidReturn< + typename RunnableType::RunType>::RunType RunType; +}; + +template <typename T> +struct FunctorTraits<Callback<T> > { + typedef Callback<T> RunnableType; + typedef typename Callback<T>::RunType RunType; +}; + + +// MakeRunnable<> +// +// Converts a passed in functor to a RunnableType using type inference. + +template <typename T> +typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { + return RunnableAdapter<T>(t); +} + +template <typename T> +typename FunctorTraits<T>::RunnableType +MakeRunnable(const IgnoreResultHelper<T>& t) { + return MakeRunnable(t.functor_); +} + +template <typename T> +const typename FunctorTraits<Callback<T> >::RunnableType& +MakeRunnable(const Callback<T>& t) { + DCHECK(!t.is_null()); + return t; +} + + +// InvokeHelper<> +// +// There are 3 logical InvokeHelper<> specializations: normal, void-return, +// WeakCalls. +// +// The normal type just calls the underlying runnable. +// +// We need a InvokeHelper to handle void return types in order to support +// IgnoreResult(). Normally, if the Runnable's RunType had a void return, +// the template system would just accept "return functor.Run()" ignoring +// the fact that a void function is being used with return. This piece of +// sugar breaks though when the Runnable's RunType is not void. Thus, we +// need a partial specialization to change the syntax to drop the "return" +// from the invocation call. +// +// WeakCalls similarly need special syntax that is applied to the first +// argument to check if they should no-op themselves. +template <bool IsWeakCall, typename ReturnType, typename Runnable, + typename ArgsType> +struct InvokeHelper; + +$for ARITY [[ +$range ARG 1..ARITY +$range WEAKCALL_ARG 2..ARITY + +template <typename ReturnType, typename Runnable[[]] +$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]> +struct InvokeHelper<false, ReturnType, Runnable, + void($for ARG , [[A$(ARG)]])> { + static ReturnType MakeItSo(Runnable runnable[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { + return runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]); + } +}; + +template <typename Runnable[[]] +$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]> +struct InvokeHelper<false, void, Runnable, + void($for ARG , [[A$(ARG)]])> { + static void MakeItSo(Runnable runnable[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { + runnable.Run($for ARG , [[CallbackForward(a$(ARG))]]); + } +}; + +]] $$ for ARITY + +// Invoker<> +// +// See description at the top of the file. +template <int NumBound, typename Storage, typename RunType> +struct Invoker; + +$for ARITY [[ + +$$ Number of bound arguments. +$range BOUND 0..ARITY +$for BOUND [[ + +$var UNBOUND = ARITY - BOUND +$range ARG 1..ARITY +$range BOUND_ARG 1..BOUND +$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY + +// Arity $(ARITY) -> $(UNBOUND). +template <typename StorageType, typename R[[]] +$if ARITY > 0 [[,]][[]] +$for ARG , [[typename X$(ARG)]]> +struct Invoker<$(BOUND), StorageType, R($for ARG , [[X$(ARG)]])> { + typedef R(RunType)(BindStateBase*[[]] +$if UNBOUND != 0 [[, ]] +$for UNBOUND_ARG , [[typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType]]); + + typedef R(UnboundRunType)($for UNBOUND_ARG , [[X$(UNBOUND_ARG)]]); + + static R Run(BindStateBase* base[[]] +$if UNBOUND != 0 [[, ]][[]] +$for UNBOUND_ARG , [[ +typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG) +]][[]] +) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. +$for BOUND_ARG +[[ + + typedef typename StorageType::Bound$(BOUND_ARG)UnwrapTraits Bound$(BOUND_ARG)UnwrapTraits; +]] + + +$for BOUND_ARG +[[ + + typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType x$(BOUND_ARG) = + Bound$(BOUND_ARG)UnwrapTraits::Unwrap(storage->p$(BOUND_ARG)_); +]] + + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void( +$for BOUND_ARG , [[ +typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType +]] + +$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]] + +$for UNBOUND_ARG , [[ +typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG) +]] +)> + ::MakeItSo(storage->runnable_ +$if ARITY > 0[[, ]] $for ARG , [[CallbackForward(x$(ARG))]]); + } +}; + +]] $$ for BOUND +]] $$ for ARITY + + +// BindState<> +// +// This stores all the state passed into Bind() and is also where most +// of the template resolution magic occurs. +// +// Runnable is the functor we are binding arguments to. +// RunType is type of the Run() function that the Invoker<> should use. +// Normally, this is the same as the RunType of the Runnable, but it can +// be different if an adapter like IgnoreResult() has been used. +// +// BoundArgsType contains the storage type for all the bound arguments by +// (ab)using a function type. +template <typename Runnable, typename RunType, typename BoundArgsType> +struct BindState; + +$for ARITY [[ +$range ARG 1..ARITY + +template <typename Runnable, typename RunType[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename P$(ARG)]]> +struct BindState<Runnable, RunType, void($for ARG , [[P$(ARG)]])> : public BindStateBase { + typedef Runnable RunnableType; + + typedef base::false_type IsWeakCall; + + typedef Invoker<$(ARITY), BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + +$if ARITY > 0 [[ + + // Convenience typedefs for bound argument types. + +$for ARG [[ + typedef UnwrapTraits<P$(ARG)> Bound$(ARG)UnwrapTraits; + +]] $$ for ARG + + +]] $$ if ARITY > 0 + +$$ The extra [[ ]] is needed to massage spacing. Silly pump.py. +[[ ]]$if ARITY == 0 [[explicit ]]BindState(const Runnable& runnable +$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]]) + : runnable_(runnable)[[]] +$if ARITY == 0 [[ + { + +]] $else [[ +, $for ARG , [[ + + p$(ARG)_(p$(ARG)) +]] { + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_); + +]] + } + + virtual ~BindState() { +$if ARITY > 0 [[ + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_); +]] + } + + RunnableType runnable_; + +$for ARG [[ + P$(ARG) p$(ARG)_; + +]] +}; + +]] $$ for ARITY + +} // namespace internal +} // namespace kudu + +#endif // GUTIL_BIND_INTERNAL_H_
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/bits.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/bits.cc b/be/src/gutil/bits.cc index dec6f51..333e464 100644 --- a/be/src/gutil/bits.cc +++ b/be/src/gutil/bits.cc @@ -2,7 +2,7 @@ // // Derived from code by Moses Charikar -#include "gutil/bits.h" +#include "kudu/gutil/bits.h" #include <assert.h> @@ -71,6 +71,22 @@ int Bits::Log2Floor_Portable(uint32 n) { return log; } +int Bits::Log2Ceiling(uint32 n) { + int floor = Log2Floor(n); + if (n == (n &~ (n - 1))) // zero or a power of two + return floor; + else + return floor + 1; +} + +int Bits::Log2Ceiling64(uint64 n) { + int floor = Log2Floor64(n); + if (n == (n &~ (n - 1))) // zero or a power of two + return floor; + else + return floor + 1; +} + int Bits::FindLSBSetNonZero_Portable(uint32 n) { int rc = 31; for (int i = 4, shift = 1 << 4; i >= 0; --i) { http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/bits.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/bits.h b/be/src/gutil/bits.h index bce7f69..639186e 100644 --- a/be/src/gutil/bits.h +++ b/be/src/gutil/bits.h @@ -2,8 +2,12 @@ // // A collection of useful (static) bit-twiddling functions. -#include "gutil/basictypes.h" -#include "gutil/integral_types.h" +#include <glog/logging.h> + +#include "kudu/gutil/basictypes.h" +#include "kudu/gutil/integral_types.h" +#include "kudu/gutil/logging-inl.h" +#include "kudu/gutil/macros.h" #ifndef _BITS_H_ #define _BITS_H_ @@ -76,10 +80,6 @@ class Bits { static int Log2Ceiling(uint32 n); static int Log2Ceiling64(uint64 n); - // Potentially faster version of Log2Ceiling() that returns an - // undefined value if n == 0 - static int Log2CeilingNonZero64(uint64 n); - // Return the first set least / most significant bit, 0-indexed. Returns an // undefined value if n == 0. FindLSBSetNonZero() is similar to ffs() except // that it's 0-indexed, while FindMSBSetNonZero() is the same as @@ -140,36 +140,6 @@ inline int Bits::Log2FloorNonZero(uint32 n) { return 31 ^ __builtin_clz(n); } -inline int Bits::Log2Ceiling(uint32 n) { - int floor = Log2Floor(n); - // Check if zero or a power of two. This pattern is recognised by gcc and optimised - // into branch-free code. - if (0 == (n & (n - 1))) - return floor; - else - return floor + 1; -} - -inline int Bits::Log2Ceiling64(uint64 n) { - int floor = Log2Floor64(n); - // Check if zero or a power of two. This pattern is recognised by gcc and optimised - // into branch-free code. - if (0 == (n & (n - 1))) - return floor; - else - return floor + 1; -} - -inline int Bits::Log2CeilingNonZero64(uint64 n) { - int floor = Log2FloorNonZero64(n); - // Check if zero or a power of two. This pattern is recognised by gcc and optimised - // into branch-free code. - if (0 == (n & (n - 1))) - return floor; - else - return floor + 1; -} - inline int Bits::FindLSBSetNonZero(uint32 n) { return __builtin_ctz(n); } @@ -186,9 +156,9 @@ inline int Bits::FindLSBSetNonZero64(uint64 n) { return __builtin_ctzll(n); } #elif defined(_MSC_VER) -#include "gutil/bits-internal-windows.h" +#include "kudu/gutil/bits-internal-windows.h" #else -#include "gutil/bits-internal-unknown.h" +#include "kudu/gutil/bits-internal-unknown.h" #endif inline int Bits::CountOnesInByte(unsigned char n) { http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/callback.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/callback.h b/be/src/gutil/callback.h new file mode 100644 index 0000000..1a41622 --- /dev/null +++ b/be/src/gutil/callback.h @@ -0,0 +1,765 @@ +// This file was GENERATED by command: +// pump.py callback.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 KUDU_GUTIL_CALLBACK_H_ +#define KUDU_GUTIL_CALLBACK_H_ + +#include "kudu/gutil/callback_forward.h" +#include "kudu/gutil/callback_internal.h" +#include "kudu/gutil/template_util.h" + +// NOTE: Header files that do not require the full definition of Callback or +// Closure should #include "kudu/gutil/callback_forward.h" instead of this file. + +// ----------------------------------------------------------------------------- +// Introduction +// ----------------------------------------------------------------------------- +// +// The templated Callback class is a generalized function object. Together +// with the Bind() function in bind.h, they provide a type-safe method for +// performing partial application of functions. +// +// Partial application (or "currying") is the process of binding a subset of +// a function's arguments to produce another function that takes fewer +// arguments. This can be used to pass around a unit of delayed execution, +// much like lexical closures are used in other languages. For example, it +// is used in Chromium code to schedule tasks on different MessageLoops. +// +// A callback with no unbound input parameters (kudu::Callback<void(void)>) +// is called a kudu::Closure. Note that this is NOT the same as what other +// languages refer to as a closure -- it does not retain a reference to its +// enclosing environment. +// +// MEMORY MANAGEMENT AND PASSING +// +// The Callback objects themselves should be passed by const-reference, and +// stored by copy. They internally store their state via a refcounted class +// and thus do not need to be deleted. +// +// The reason to pass via a const-reference is to avoid unnecessary +// AddRef/Release pairs to the internal state. +// +// +// ----------------------------------------------------------------------------- +// Quick reference for basic stuff +// ----------------------------------------------------------------------------- +// +// BINDING A BARE FUNCTION +// +// int Return5() { return 5; } +// kudu::Callback<int(void)> func_cb = kudu::Bind(&Return5); +// LOG(INFO) << func_cb.Run(); // Prints 5. +// +// BINDING A CLASS METHOD +// +// The first argument to bind is the member function to call, the second is +// the object on which to call it. +// +// class Ref : public kudu::RefCountedThreadSafe<Ref> { +// public: +// int Foo() { return 3; } +// void PrintBye() { LOG(INFO) << "bye."; } +// }; +// scoped_refptr<Ref> ref = new Ref(); +// kudu::Callback<void(void)> ref_cb = kudu::Bind(&Ref::Foo, ref); +// LOG(INFO) << ref_cb.Run(); // Prints out 3. +// +// By default the object must support RefCounted or you will get a compiler +// error. If you're passing between threads, be sure it's +// RefCountedThreadSafe! See "Advanced binding of member functions" below if +// you don't want to use reference counting. +// +// RUNNING A CALLBACK +// +// Callbacks can be run with their "Run" method, which has the same +// signature as the template argument to the callback. +// +// void DoSomething(const kudu::Callback<void(int, std::string)>& callback) { +// callback.Run(5, "hello"); +// } +// +// Callbacks can be run more than once (they don't get deleted or marked when +// run). However, this precludes using kudu::Passed (see below). +// +// void DoSomething(const kudu::Callback<double(double)>& callback) { +// double myresult = callback.Run(3.14159); +// myresult += callback.Run(2.71828); +// } +// +// PASSING UNBOUND INPUT PARAMETERS +// +// Unbound parameters are specified at the time a callback is Run(). They are +// specified in the Callback template type: +// +// void MyFunc(int i, const std::string& str) {} +// kudu::Callback<void(int, const std::string&)> cb = kudu::Bind(&MyFunc); +// cb.Run(23, "hello, world"); +// +// PASSING BOUND INPUT PARAMETERS +// +// Bound parameters are specified when you create the callback as arguments +// to Bind(). They will be passed to the function and the Run()ner of the +// callback doesn't see those values or even know that the function it's +// calling. +// +// void MyFunc(int i, const std::string& str) {} +// kudu::Callback<void(void)> cb = kudu::Bind(&MyFunc, 23, "hello world"); +// cb.Run(); +// +// A callback with no unbound input parameters (kudu::Callback<void(void)>) +// is called a kudu::Closure. So we could have also written: +// +// kudu::Closure cb = kudu::Bind(&MyFunc, 23, "hello world"); +// +// When calling member functions, bound parameters just go after the object +// pointer. +// +// kudu::Closure cb = kudu::Bind(&MyClass::MyFunc, this, 23, "hello world"); +// +// PARTIAL BINDING OF PARAMETERS +// +// You can specify some parameters when you create the callback, and specify +// the rest when you execute the callback. +// +// void MyFunc(int i, const std::string& str) {} +// kudu::Callback<void(const std::string&)> cb = kudu::Bind(&MyFunc, 23); +// cb.Run("hello world"); +// +// When calling a function bound parameters are first, followed by unbound +// parameters. +// +// +// ----------------------------------------------------------------------------- +// Quick reference for advanced binding +// ----------------------------------------------------------------------------- +// +// BINDING A CLASS METHOD WITH WEAK POINTERS +// +// kudu::Bind(&MyClass::Foo, GetWeakPtr()); +// +// The callback will not be issued if the object is destroyed at the time +// it's issued. DANGER: weak pointers are not threadsafe, so don't use this +// when passing between threads! +// +// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT +// +// kudu::Bind(&MyClass::Foo, kudu::Unretained(this)); +// +// This disables all lifetime management on the object. You're responsible +// for making sure the object is alive at the time of the call. You break it, +// you own it! +// +// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS +// +// MyClass* myclass = new MyClass; +// kudu::Bind(&MyClass::Foo, kudu::Owned(myclass)); +// +// The object will be deleted when the callback is destroyed, even if it's +// not run (like if you post a task during shutdown). Potentially useful for +// "fire and forget" cases. +// +// IGNORING RETURN VALUES +// +// Sometimes you want to call a function that returns a value in a callback +// that doesn't expect a return value. +// +// int DoSomething(int arg) { cout << arg << endl; } +// kudu::Callback<void<int>) cb = +// kudu::Bind(kudu::IgnoreResult(&DoSomething)); +// +// +// ----------------------------------------------------------------------------- +// Quick reference for binding parameters to Bind() +// ----------------------------------------------------------------------------- +// +// Bound parameters are specified as arguments to Bind() and are passed to the +// function. A callback with no parameters or no unbound parameters is called a +// Closure (kudu::Callback<void(void)> and kudu::Closure are the same thing). +// +// PASSING PARAMETERS OWNED BY THE CALLBACK +// +// void Foo(int* arg) { cout << *arg << endl; } +// int* pn = new int(1); +// kudu::Closure foo_callback = kudu::Bind(&foo, kudu::Owned(pn)); +// +// The parameter will be deleted when the callback is destroyed, even if it's +// not run (like if you post a task during shutdown). +// +// PASSING PARAMETERS AS A scoped_ptr +// +// void TakesOwnership(scoped_ptr<Foo> arg) {} +// scoped_ptr<Foo> f(new Foo); +// // f becomes null during the following call. +// kudu::Closure cb = kudu::Bind(&TakesOwnership, kudu::Passed(&f)); +// +// Ownership of the parameter will be with the callback until the it is run, +// when ownership is passed to the callback function. This means the callback +// can only be run once. If the callback is never run, it will delete the +// object when it's destroyed. +// +// PASSING PARAMETERS AS A scoped_refptr +// +// void TakesOneRef(scoped_refptr<Foo> arg) {} +// scoped_refptr<Foo> f(new Foo) +// kudu::Closure cb = kudu::Bind(&TakesOneRef, f); +// +// This should "just work." The closure will take a reference as long as it +// is alive, and another reference will be taken for the called function. +// +// PASSING PARAMETERS BY REFERENCE +// +// void foo(int arg) { cout << arg << endl } +// int n = 1; +// kudu::Closure has_ref = kudu::Bind(&foo, kudu::ConstRef(n)); +// n = 2; +// has_ref.Run(); // Prints "2" +// +// Normally parameters are copied in the closure. DANGER: ConstRef stores a +// const reference instead, referencing the original parameter. This means +// that you must ensure the object outlives the callback! +// +// +// ----------------------------------------------------------------------------- +// Implementation notes +// ----------------------------------------------------------------------------- +// +// WHERE IS THIS DESIGN FROM: +// +// The design Callback and Bind is heavily influenced by C++'s +// tr1::function/tr1::bind, and by the "Google Callback" system used inside +// Google. +// +// +// HOW THE IMPLEMENTATION WORKS: +// +// There are three main components to the system: +// 1) The Callback classes. +// 2) The Bind() functions. +// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). +// +// The Callback classes represent a generic function pointer. Internally, +// it stores a refcounted piece of state that represents the target function +// and all its bound parameters. Each Callback specialization has a templated +// constructor that takes an BindState<>*. In the context of the constructor, +// the static type of this BindState<> pointer uniquely identifies the +// function it is representing, all its bound parameters, and a Run() method +// that is capable of invoking the target. +// +// Callback's constructor takes the BindState<>* that has the full static type +// and erases the target function type as well as the types of the bound +// parameters. It does this by storing a pointer to the specific Run() +// function, and upcasting the state of BindState<>* to a +// BindStateBase*. This is safe as long as this BindStateBase pointer +// is only used with the stored Run() pointer. +// +// To BindState<> objects are created inside the Bind() functions. +// These functions, along with a set of internal templates, are responsible for +// +// - Unwrapping the function signature into return type, and parameters +// - Determining the number of parameters that are bound +// - Creating the BindState storing the bound parameters +// - Performing compile-time asserts to avoid error-prone behavior +// - Returning an Callback<> with an arity matching the number of unbound +// parameters and that knows the correct refcounting semantics for the +// target object if we are binding a method. +// +// The Bind functions do the above using type-inference, and template +// specializations. +// +// By default Bind() will store copies of all bound parameters, and attempt +// to refcount a target object if the function being bound is a class method. +// These copies are created even if the function takes parameters as const +// references. (Binding to non-const references is forbidden, see bind.h.) +// +// To change this behavior, we introduce a set of argument wrappers +// (e.g., Unretained(), and ConstRef()). These are simple container templates +// that are passed by value, and wrap a pointer to argument. See the +// file-level comment in kudu/gutil/bind_helpers.h for more info. +// +// These types are passed to the Unwrap() functions, and the MaybeRefcount() +// functions respectively to modify the behavior of Bind(). The Unwrap() +// and MaybeRefcount() functions change behavior by doing partial +// specialization based on whether or not a parameter is a wrapper type. +// +// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. +// +// +// WHY NOT TR1 FUNCTION/BIND? +// +// Direct use of tr1::function and tr1::bind was considered, but ultimately +// rejected because of the number of copy constructors invocations involved +// in the binding of arguments during construction, and the forwarding of +// arguments during invocation. These copies will no longer be an issue in +// C++0x because C++0x will support rvalue reference allowing for the compiler +// to avoid these copies. However, waiting for C++0x is not an option. +// +// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the +// tr1::bind call itself will invoke a non-trivial copy constructor three times +// for each bound parameter. Also, each when passing a tr1::function, each +// bound argument will be copied again. +// +// In addition to the copies taken at binding and invocation, copying a +// tr1::function causes a copy to be made of all the bound parameters and +// state. +// +// Furthermore, in Chromium, it is desirable for the Callback to take a +// reference on a target object when representing a class method call. This +// is not supported by tr1. +// +// Lastly, tr1::function and tr1::bind has a more general and flexible API. +// This includes things like argument reordering by use of +// tr1::bind::placeholder, support for non-const reference parameters, and some +// limited amount of subtyping of the tr1::function object (e.g., +// tr1::function<int(int)> is convertible to tr1::function<void(int)>). +// +// These are not features that are required in Chromium. Some of them, such as +// allowing for reference parameters, and subtyping of functions, may actually +// become a source of errors. Removing support for these features actually +// allows for a simpler implementation, and a terser Currying API. +// +// +// WHY NOT GOOGLE CALLBACKS? +// +// The Google callback system also does not support refcounting. Furthermore, +// its implementation has a number of strange edge cases with respect to type +// conversion of its arguments. In particular, the argument's constness must +// at times match exactly the function signature, or the type-inference might +// break. Given the above, writing a custom solution was easier. +// +// +// MISSING FUNCTIONALITY +// - Invoking the return of Bind. Bind(&foo).Run() does not work; +// - Binding arrays to functions that take a non-const pointer. +// Example: +// void Foo(const char* ptr); +// void Bar(char* ptr); +// Bind(&Foo, "test"); +// Bind(&Bar, "test"); // This fails because ptr is not const. + +namespace kudu { + +// First, we forward declare the Callback class template. This informs the +// compiler that the template only has 1 type parameter which is the function +// signature that the Callback is representing. +// +// After this, create template specializations for 0-7 parameters. Note that +// even though the template typelist grows, the specialization still +// only has one type: the function signature. +// +// If you are thinking of forward declaring Callback in your own header file, +// please include "base/callback_forward.h" instead. +template <typename Sig> +class Callback; + +namespace internal { +template <typename Runnable, typename RunType, typename BoundArgsType> +struct BindState; +} // namespace internal + +template <typename R> +class Callback<R(void)> : public internal::CallbackBase { + public: + typedef R(RunType)(); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run() const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get()); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*); + +}; + +template <typename R, typename A1> +class Callback<R(A1)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType); + +}; + +template <typename R, typename A1, typename A2> +class Callback<R(A1, A2)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType); + +}; + +template <typename R, typename A1, typename A2, typename A3> +class Callback<R(A1, A2, A3)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType); + +}; + +template <typename R, typename A1, typename A2, typename A3, typename A4> +class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType, + typename internal::CallbackParamTraits<A4>::ForwardType); + +}; + +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5> +class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType, + typename internal::CallbackParamTraits<A4>::ForwardType, + typename internal::CallbackParamTraits<A5>::ForwardType); + +}; + +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5, A6); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5, + typename internal::CallbackParamTraits<A6>::ForwardType a6) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5), + internal::CallbackForward(a6)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType, + typename internal::CallbackParamTraits<A4>::ForwardType, + typename internal::CallbackParamTraits<A5>::ForwardType, + typename internal::CallbackParamTraits<A6>::ForwardType); + +}; + +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5, + typename internal::CallbackParamTraits<A6>::ForwardType a6, + typename internal::CallbackParamTraits<A7>::ForwardType a7) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), internal::CallbackForward(a1), + internal::CallbackForward(a2), + internal::CallbackForward(a3), + internal::CallbackForward(a4), + internal::CallbackForward(a5), + internal::CallbackForward(a6), + internal::CallbackForward(a7)); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType, + typename internal::CallbackParamTraits<A4>::ForwardType, + typename internal::CallbackParamTraits<A5>::ForwardType, + typename internal::CallbackParamTraits<A6>::ForwardType, + typename internal::CallbackParamTraits<A7>::ForwardType); + +}; + + +// Syntactic sugar to make Callbacks<void(void)> easier to declare since it +// will be used in a lot of APIs with delayed execution. +typedef Callback<void(void)> Closure; + +} // namespace kudu + +#endif // KUDU_GUTIL_CALLBACK_H http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/callback.h.pump ---------------------------------------------------------------------- diff --git a/be/src/gutil/callback.h.pump b/be/src/gutil/callback.h.pump new file mode 100644 index 0000000..b96c6c9 --- /dev/null +++ b/be/src/gutil/callback.h.pump @@ -0,0 +1,436 @@ +$$ 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 gutil/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 GUTIL_CALLBACK_H_ +#define GUTIL_CALLBACK_H_ + +#include "gutil/callback_forward.h" +#include "gutil/callback_internal.h" +#include "gutil/template_util.h" + +// NOTE: Header files that do not require the full definition of Callback or +// Closure should #include "gutil/callback_forward.h" instead of this file. + +// ----------------------------------------------------------------------------- +// Introduction +// ----------------------------------------------------------------------------- +// +// The templated Callback class is a generalized function object. Together +// with the Bind() function in bind.h, they provide a type-safe method for +// performing partial application of functions. +// +// Partial application (or "currying") is the process of binding a subset of +// a function's arguments to produce another function that takes fewer +// arguments. This can be used to pass around a unit of delayed execution, +// much like lexical closures are used in other languages. For example, it +// is used in Chromium code to schedule tasks on different MessageLoops. +// +// A callback with no unbound input parameters (kudu::Callback<void(void)>) +// is called a kudu::Closure. Note that this is NOT the same as what other +// languages refer to as a closure -- it does not retain a reference to its +// enclosing environment. +// +// MEMORY MANAGEMENT AND PASSING +// +// The Callback objects themselves should be passed by const-reference, and +// stored by copy. They internally store their state via a refcounted class +// and thus do not need to be deleted. +// +// The reason to pass via a const-reference is to avoid unnecessary +// AddRef/Release pairs to the internal state. +// +// +// ----------------------------------------------------------------------------- +// Quick reference for basic stuff +// ----------------------------------------------------------------------------- +// +// BINDING A BARE FUNCTION +// +// int Return5() { return 5; } +// kudu::Callback<int(void)> func_cb = kudu::Bind(&Return5); +// LOG(INFO) << func_cb.Run(); // Prints 5. +// +// BINDING A CLASS METHOD +// +// The first argument to bind is the member function to call, the second is +// the object on which to call it. +// +// class Ref : public kudu::RefCountedThreadSafe<Ref> { +// public: +// int Foo() { return 3; } +// void PrintBye() { LOG(INFO) << "bye."; } +// }; +// scoped_refptr<Ref> ref = new Ref(); +// kudu::Callback<void(void)> ref_cb = kudu::Bind(&Ref::Foo, ref); +// LOG(INFO) << ref_cb.Run(); // Prints out 3. +// +// By default the object must support RefCounted or you will get a compiler +// error. If you're passing between threads, be sure it's +// RefCountedThreadSafe! See "Advanced binding of member functions" below if +// you don't want to use reference counting. +// +// RUNNING A CALLBACK +// +// Callbacks can be run with their "Run" method, which has the same +// signature as the template argument to the callback. +// +// void DoSomething(const kudu::Callback<void(int, std::string)>& callback) { +// callback.Run(5, "hello"); +// } +// +// Callbacks can be run more than once (they don't get deleted or marked when +// run). However, this precludes using kudu::Passed (see below). +// +// void DoSomething(const kudu::Callback<double(double)>& callback) { +// double myresult = callback.Run(3.14159); +// myresult += callback.Run(2.71828); +// } +// +// PASSING UNBOUND INPUT PARAMETERS +// +// Unbound parameters are specified at the time a callback is Run(). They are +// specified in the Callback template type: +// +// void MyFunc(int i, const std::string& str) {} +// kudu::Callback<void(int, const std::string&)> cb = kudu::Bind(&MyFunc); +// cb.Run(23, "hello, world"); +// +// PASSING BOUND INPUT PARAMETERS +// +// Bound parameters are specified when you create the callback as arguments +// to Bind(). They will be passed to the function and the Run()ner of the +// callback doesn't see those values or even know that the function it's +// calling. +// +// void MyFunc(int i, const std::string& str) {} +// kudu::Callback<void(void)> cb = kudu::Bind(&MyFunc, 23, "hello world"); +// cb.Run(); +// +// A callback with no unbound input parameters (kudu::Callback<void(void)>) +// is called a kudu::Closure. So we could have also written: +// +// kudu::Closure cb = kudu::Bind(&MyFunc, 23, "hello world"); +// +// When calling member functions, bound parameters just go after the object +// pointer. +// +// kudu::Closure cb = kudu::Bind(&MyClass::MyFunc, this, 23, "hello world"); +// +// PARTIAL BINDING OF PARAMETERS +// +// You can specify some parameters when you create the callback, and specify +// the rest when you execute the callback. +// +// void MyFunc(int i, const std::string& str) {} +// kudu::Callback<void(const std::string&)> cb = kudu::Bind(&MyFunc, 23); +// cb.Run("hello world"); +// +// When calling a function bound parameters are first, followed by unbound +// parameters. +// +// +// ----------------------------------------------------------------------------- +// Quick reference for advanced binding +// ----------------------------------------------------------------------------- +// +// BINDING A CLASS METHOD WITH WEAK POINTERS +// +// kudu::Bind(&MyClass::Foo, GetWeakPtr()); +// +// The callback will not be issued if the object is destroyed at the time +// it's issued. DANGER: weak pointers are not threadsafe, so don't use this +// when passing between threads! +// +// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT +// +// kudu::Bind(&MyClass::Foo, kudu::Unretained(this)); +// +// This disables all lifetime management on the object. You're responsible +// for making sure the object is alive at the time of the call. You break it, +// you own it! +// +// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS +// +// MyClass* myclass = new MyClass; +// kudu::Bind(&MyClass::Foo, kudu::Owned(myclass)); +// +// The object will be deleted when the callback is destroyed, even if it's +// not run (like if you post a task during shutdown). Potentially useful for +// "fire and forget" cases. +// +// IGNORING RETURN VALUES +// +// Sometimes you want to call a function that returns a value in a callback +// that doesn't expect a return value. +// +// int DoSomething(int arg) { cout << arg << endl; } +// kudu::Callback<void<int>) cb = +// kudu::Bind(kudu::IgnoreResult(&DoSomething)); +// +// +// ----------------------------------------------------------------------------- +// Quick reference for binding parameters to Bind() +// ----------------------------------------------------------------------------- +// +// Bound parameters are specified as arguments to Bind() and are passed to the +// function. A callback with no parameters or no unbound parameters is called a +// Closure (kudu::Callback<void(void)> and kudu::Closure are the same thing). +// +// PASSING PARAMETERS OWNED BY THE CALLBACK +// +// void Foo(int* arg) { cout << *arg << endl; } +// int* pn = new int(1); +// kudu::Closure foo_callback = kudu::Bind(&foo, kudu::Owned(pn)); +// +// The parameter will be deleted when the callback is destroyed, even if it's +// not run (like if you post a task during shutdown). +// +// PASSING PARAMETERS AS A scoped_ptr +// +// void TakesOwnership(scoped_ptr<Foo> arg) {} +// scoped_ptr<Foo> f(new Foo); +// // f becomes null during the following call. +// kudu::Closure cb = kudu::Bind(&TakesOwnership, kudu::Passed(&f)); +// +// Ownership of the parameter will be with the callback until the it is run, +// when ownership is passed to the callback function. This means the callback +// can only be run once. If the callback is never run, it will delete the +// object when it's destroyed. +// +// PASSING PARAMETERS AS A scoped_refptr +// +// void TakesOneRef(scoped_refptr<Foo> arg) {} +// scoped_refptr<Foo> f(new Foo) +// kudu::Closure cb = kudu::Bind(&TakesOneRef, f); +// +// This should "just work." The closure will take a reference as long as it +// is alive, and another reference will be taken for the called function. +// +// PASSING PARAMETERS BY REFERENCE +// +// void foo(int arg) { cout << arg << endl } +// int n = 1; +// kudu::Closure has_ref = kudu::Bind(&foo, kudu::ConstRef(n)); +// n = 2; +// has_ref.Run(); // Prints "2" +// +// Normally parameters are copied in the closure. DANGER: ConstRef stores a +// const reference instead, referencing the original parameter. This means +// that you must ensure the object outlives the callback! +// +// +// ----------------------------------------------------------------------------- +// Implementation notes +// ----------------------------------------------------------------------------- +// +// WHERE IS THIS DESIGN FROM: +// +// The design Callback and Bind is heavily influenced by C++'s +// tr1::function/tr1::bind, and by the "Google Callback" system used inside +// Google. +// +// +// HOW THE IMPLEMENTATION WORKS: +// +// There are three main components to the system: +// 1) The Callback classes. +// 2) The Bind() functions. +// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). +// +// The Callback classes represent a generic function pointer. Internally, +// it stores a refcounted piece of state that represents the target function +// and all its bound parameters. Each Callback specialization has a templated +// constructor that takes an BindState<>*. In the context of the constructor, +// the static type of this BindState<> pointer uniquely identifies the +// function it is representing, all its bound parameters, and a Run() method +// that is capable of invoking the target. +// +// Callback's constructor takes the BindState<>* that has the full static type +// and erases the target function type as well as the types of the bound +// parameters. It does this by storing a pointer to the specific Run() +// function, and upcasting the state of BindState<>* to a +// BindStateBase*. This is safe as long as this BindStateBase pointer +// is only used with the stored Run() pointer. +// +// To BindState<> objects are created inside the Bind() functions. +// These functions, along with a set of internal templates, are responsible for +// +// - Unwrapping the function signature into return type, and parameters +// - Determining the number of parameters that are bound +// - Creating the BindState storing the bound parameters +// - Performing compile-time asserts to avoid error-prone behavior +// - Returning an Callback<> with an arity matching the number of unbound +// parameters and that knows the correct refcounting semantics for the +// target object if we are binding a method. +// +// The Bind functions do the above using type-inference, and template +// specializations. +// +// By default Bind() will store copies of all bound parameters, and attempt +// to refcount a target object if the function being bound is a class method. +// These copies are created even if the function takes parameters as const +// references. (Binding to non-const references is forbidden, see bind.h.) +// +// To change this behavior, we introduce a set of argument wrappers +// (e.g., Unretained(), and ConstRef()). These are simple container templates +// that are passed by value, and wrap a pointer to argument. See the +// file-level comment in gutil/bind_helpers.h for more info. +// +// These types are passed to the Unwrap() functions, and the MaybeRefcount() +// functions respectively to modify the behavior of Bind(). The Unwrap() +// and MaybeRefcount() functions change behavior by doing partial +// specialization based on whether or not a parameter is a wrapper type. +// +// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. +// +// +// WHY NOT TR1 FUNCTION/BIND? +// +// Direct use of tr1::function and tr1::bind was considered, but ultimately +// rejected because of the number of copy constructors invocations involved +// in the binding of arguments during construction, and the forwarding of +// arguments during invocation. These copies will no longer be an issue in +// C++0x because C++0x will support rvalue reference allowing for the compiler +// to avoid these copies. However, waiting for C++0x is not an option. +// +// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the +// tr1::bind call itself will invoke a non-trivial copy constructor three times +// for each bound parameter. Also, each when passing a tr1::function, each +// bound argument will be copied again. +// +// In addition to the copies taken at binding and invocation, copying a +// tr1::function causes a copy to be made of all the bound parameters and +// state. +// +// Furthermore, in Chromium, it is desirable for the Callback to take a +// reference on a target object when representing a class method call. This +// is not supported by tr1. +// +// Lastly, tr1::function and tr1::bind has a more general and flexible API. +// This includes things like argument reordering by use of +// tr1::bind::placeholder, support for non-const reference parameters, and some +// limited amount of subtyping of the tr1::function object (e.g., +// tr1::function<int(int)> is convertible to tr1::function<void(int)>). +// +// These are not features that are required in Chromium. Some of them, such as +// allowing for reference parameters, and subtyping of functions, may actually +// become a source of errors. Removing support for these features actually +// allows for a simpler implementation, and a terser Currying API. +// +// +// WHY NOT GOOGLE CALLBACKS? +// +// The Google callback system also does not support refcounting. Furthermore, +// its implementation has a number of strange edge cases with respect to type +// conversion of its arguments. In particular, the argument's constness must +// at times match exactly the function signature, or the type-inference might +// break. Given the above, writing a custom solution was easier. +// +// +// MISSING FUNCTIONALITY +// - Invoking the return of Bind. Bind(&foo).Run() does not work; +// - Binding arrays to functions that take a non-const pointer. +// Example: +// void Foo(const char* ptr); +// void Bar(char* ptr); +// Bind(&Foo, "test"); +// Bind(&Bar, "test"); // This fails because ptr is not const. + +namespace kudu { + +// First, we forward declare the Callback class template. This informs the +// compiler that the template only has 1 type parameter which is the function +// signature that the Callback is representing. +// +// After this, create template specializations for 0-$(MAX_ARITY) parameters. Note that +// even though the template typelist grows, the specialization still +// only has one type: the function signature. +// +// If you are thinking of forward declaring Callback in your own header file, +// please include "base/callback_forward.h" instead. +template <typename Sig> +class Callback; + +namespace internal { +template <typename Runnable, typename RunType, typename BoundArgsType> +struct BindState; +} // namespace internal + + +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +$if ARITY == 0 [[ +template <typename R> +class Callback<R(void)> : public internal::CallbackBase { +]] $else [[ +template <typename R, $for ARG , [[typename A$(ARG)]]> +class Callback<R($for ARG , [[A$(ARG)]])> : public internal::CallbackBase { +]] + + public: + typedef R(RunType)($for ARG , [[A$(ARG)]]); + + Callback() : CallbackBase(NULL) { } + + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename Runnable, typename BindRunType, typename BoundArgsType> + Callback(internal::BindState<Runnable, BindRunType, + BoundArgsType>* bind_state) + : CallbackBase(bind_state) { + + // Force the assignment to a local variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = + &internal::BindState<Runnable, BindRunType, BoundArgsType> + ::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run($for ARG , + [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get()[[]] +$if ARITY != 0 [[, ]] +$for ARG , + [[internal::CallbackForward(a$(ARG))]]); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*[[]] +$if ARITY != 0 [[, ]] +$for ARG , [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType]]); + +}; + + +]] $$ for ARITY + +// Syntactic sugar to make Callbacks<void(void)> easier to declare since it +// will be used in a lot of APIs with delayed execution. +typedef Callback<void(void)> Closure; + +} // namespace kudu + +#endif // GUTIL_CALLBACK_H http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/callback_forward.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/callback_forward.h b/be/src/gutil/callback_forward.h new file mode 100644 index 0000000..956ff73 --- /dev/null +++ b/be/src/gutil/callback_forward.h @@ -0,0 +1,17 @@ +// Copyright (c) 2011 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 KUDU_GUTIL_CALLBACK_FORWARD_H_ +#define KUDU_GUTIL_CALLBACK_FORWARD_H_ + +namespace kudu { + +template <typename Sig> +class Callback; + +typedef Callback<void(void)> Closure; + +} // namespace kudu + +#endif // KUDU_GUTIL_CALLBACK_FORWARD_H http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/callback_internal.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/callback_internal.cc b/be/src/gutil/callback_internal.cc new file mode 100644 index 0000000..05b9e8f --- /dev/null +++ b/be/src/gutil/callback_internal.cc @@ -0,0 +1,36 @@ +// 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 "kudu/gutil/callback_internal.h" + +namespace kudu { +namespace internal { + +bool CallbackBase::is_null() const { + return bind_state_.get() == nullptr; +} + +void CallbackBase::Reset() { + polymorphic_invoke_ = nullptr; + // NULL the bind_state_ last, since it may be holding the last ref to whatever + // object owns us, and we may be deleted after that. + bind_state_ = nullptr; +} + +bool CallbackBase::Equals(const CallbackBase& other) const { + return bind_state_.get() == other.bind_state_.get() && + polymorphic_invoke_ == other.polymorphic_invoke_; +} + +CallbackBase::CallbackBase(BindStateBase* bind_state) + : bind_state_(bind_state), + polymorphic_invoke_(nullptr) { + DCHECK(!bind_state_.get() || bind_state_->HasOneRef()); +} + +CallbackBase::~CallbackBase() { +} + +} // namespace internal +} // namespace kudu http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/callback_internal.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/callback_internal.h b/be/src/gutil/callback_internal.h new file mode 100644 index 0000000..47b5655 --- /dev/null +++ b/be/src/gutil/callback_internal.h @@ -0,0 +1,177 @@ +// 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. + +// This file contains utility functions and classes that help the +// implementation, and management of the Callback objects. + +#ifndef KUDU_GUTIL_CALLBACK_INTERNAL_H_ +#define KUDU_GUTIL_CALLBACK_INTERNAL_H_ + +#include <stddef.h> + +#include "kudu/gutil/gscoped_ptr.h" +#include "kudu/gutil/ref_counted.h" + +template <typename T> +class ScopedVector; + +namespace kudu { +namespace internal { + +// BindStateBase is used to provide an opaque handle that the Callback +// class can use to represent a function object with bound arguments. It +// behaves as an existential type that is used by a corresponding +// DoInvoke function to perform the function execution. This allows +// us to shield the Callback class from the types of the bound argument via +// "type erasure." +class BindStateBase : public RefCountedThreadSafe<BindStateBase> { + protected: + friend class RefCountedThreadSafe<BindStateBase>; + virtual ~BindStateBase() {} +}; + +// Holds the Callback methods that don't require specialization to reduce +// template bloat. +class CallbackBase { + public: + // Returns true if Callback is null (doesn't refer to anything). + bool is_null() const; + + // Returns the Callback into an uninitialized state. + void Reset(); + + protected: + // In C++, it is safe to cast function pointers to function pointers of + // another type. It is not okay to use void*. We create a InvokeFuncStorage + // that that can store our function pointer, and then cast it back to + // the original type on usage. + typedef void(*InvokeFuncStorage)(void); + + // Returns true if this callback equals |other|. |other| may be null. + bool Equals(const CallbackBase& other) const; + + // Allow initializing of |bind_state_| via the constructor to avoid default + // initialization of the scoped_refptr. We do not also initialize + // |polymorphic_invoke_| here because doing a normal assignment in the + // derived Callback templates makes for much nicer compiler errors. + explicit CallbackBase(BindStateBase* bind_state); + + // Force the destructor to be instantiated inside this translation unit so + // that our subclasses will not get inlined versions. Avoids more template + // bloat. + ~CallbackBase(); + + scoped_refptr<BindStateBase> bind_state_; + InvokeFuncStorage polymorphic_invoke_; +}; + +// A helper template to determine if given type is non-const move-only-type, +// i.e. if a value of the given type should be passed via .Pass() in a +// destructive way. +template <typename T> struct IsMoveOnlyType { + template <typename U> + static base::YesType Test(const typename U::MoveOnlyTypeForCPP03*); + + template <typename U> + static base::NoType Test(...); + + static const bool value = sizeof(Test<T>(0)) == sizeof(base::YesType) && + !base::is_const<T>::value; +}; + +// This is a typetraits object that's used to take an argument type, and +// extract a suitable type for storing and forwarding arguments. +// +// In particular, it strips off references, and converts arrays to +// pointers for storage; and it avoids accidentally trying to create a +// "reference of a reference" if the argument is a reference type. +// +// This array type becomes an issue for storage because we are passing bound +// parameters by const reference. In this case, we end up passing an actual +// array type in the initializer list which C++ does not allow. This will +// break passing of C-string literals. +template <typename T, bool is_move_only = IsMoveOnlyType<T>::value> +struct CallbackParamTraits { + typedef const T& ForwardType; + typedef T StorageType; +}; + +// The Storage should almost be impossible to trigger unless someone manually +// specifies type of the bind parameters. However, in case they do, +// this will guard against us accidentally storing a reference parameter. +// +// The ForwardType should only be used for unbound arguments. +template <typename T> +struct CallbackParamTraits<T&, false> { + typedef T& ForwardType; + typedef T StorageType; +}; + +// Note that for array types, we implicitly add a const in the conversion. This +// means that it is not possible to bind array arguments to functions that take +// a non-const pointer. Trying to specialize the template based on a "const +// T[n]" does not seem to match correctly, so we are stuck with this +// restriction. +template <typename T, size_t n> +struct CallbackParamTraits<T[n], false> { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// See comment for CallbackParamTraits<T[n]>. +template <typename T> +struct CallbackParamTraits<T[], false> { + typedef const T* ForwardType; + typedef const T* StorageType; +}; + +// Parameter traits for movable-but-not-copyable scopers. +// +// Callback<>/Bind() understands movable-but-not-copyable semantics where +// the type cannot be copied but can still have its state destructively +// transferred (aka. moved) to another instance of the same type by calling a +// helper function. When used with Bind(), this signifies transferal of the +// object's state to the target function. +// +// For these types, the ForwardType must not be a const reference, or a +// reference. A const reference is inappropriate, and would break const +// correctness, because we are implementing a destructive move. A non-const +// reference cannot be used with temporaries which means the result of a +// function or a cast would not be usable with Callback<> or Bind(). +template <typename T> +struct CallbackParamTraits<T, true> { + typedef T ForwardType; + typedef T StorageType; +}; + +// CallbackForward() is a very limited simulation of C++11's std::forward() +// used by the Callback/Bind system for a set of movable-but-not-copyable +// types. It is needed because forwarding a movable-but-not-copyable +// argument to another function requires us to invoke the proper move +// operator to create a rvalue version of the type. The supported types are +// whitelisted below as overloads of the CallbackForward() function. The +// default template compiles out to be a no-op. +// +// In C++11, std::forward would replace all uses of this function. However, it +// is impossible to implement a general std::forward with C++11 due to a lack +// of rvalue references. +// +// In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to +// simulate std::forward() and forward the result of one Callback as a +// parameter to another callback. This is to support Callbacks that return +// the movable-but-not-copyable types whitelisted above. +template <typename T> +typename base::enable_if<!IsMoveOnlyType<T>::value, T>::type& CallbackForward(T& t) { + return t; +} + +template <typename T> +typename base::enable_if<IsMoveOnlyType<T>::value, T>::type CallbackForward(T& t) { + return t.Pass(); +} + +} // namespace internal +} // namespace kudu + +#endif // KUDU_GUTIL_CALLBACK_INTERNAL_H_ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/casts.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/casts.h b/be/src/gutil/casts.h index fe3d7b4..474e083 100644 --- a/be/src/gutil/casts.h +++ b/be/src/gutil/casts.h @@ -14,9 +14,11 @@ #include <string.h> // for memcpy #include <limits.h> // for enumeration casts and tests -#include "gutil/macros.h" -#include "gutil/template_util.h" -#include "gutil/type_traits.h" +#include <glog/logging.h> + +#include "kudu/gutil/macros.h" +#include "kudu/gutil/template_util.h" +#include "kudu/gutil/type_traits.h" // Use implicit_cast as a safe version of static_cast or const_cast // for implicit conversions. For example: @@ -164,7 +166,7 @@ template <class Dest, class Source> inline Dest bit_cast(const Source& source) { // Compile time assertion: sizeof(Dest) == sizeof(Source) // A compile error here means your Dest and Source have different sizes. - typedef char VerifySizesAreEqual [sizeof(Dest) == sizeof(Source) ? 1 : -1]; + COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual); Dest dest; memcpy(&dest, &source, sizeof(dest)); @@ -361,14 +363,12 @@ inline bool tight_enum_test_cast(int e_val, Enum* e_var) { } } -// The plain casts require logging, and we get header recursion if -// it is done directly. So, we do it indirectly. -// The following function is defined in logging.cc. - namespace base { namespace internal { -void WarnEnumCastError(int value_of_int); +inline void WarnEnumCastError(int value_of_int) { + LOG(DFATAL) << "Bad enum value " << value_of_int; +} } // namespace internal } // namespace base http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/charmap.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/charmap.h b/be/src/gutil/charmap.h index b3a75c9..2698bbe 100644 --- a/be/src/gutil/charmap.h +++ b/be/src/gutil/charmap.h @@ -18,9 +18,9 @@ #include <string.h> -#include "gutil/basictypes.h" -#include "gutil/integral_types.h" -#include "gutil/type_traits.h" +#include "kudu/gutil/basictypes.h" +#include "kudu/gutil/integral_types.h" +#include "kudu/gutil/type_traits.h" class Charmap { public: @@ -64,8 +64,8 @@ class Charmap { } bool IsZero() const { - for (int i = 0; i < 8; ++i) { - if (m_[i] != 0) + for (uint32 c : m_) { + if (c != 0) return false; } return true;
