security/sandbox/chromium/base/callback_internal.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 // This file contains utility functions and classes that help the
michael@0 6 // implementation, and management of the Callback objects.
michael@0 7
michael@0 8 #ifndef BASE_CALLBACK_INTERNAL_H_
michael@0 9 #define BASE_CALLBACK_INTERNAL_H_
michael@0 10
michael@0 11 #include <stddef.h>
michael@0 12
michael@0 13 #include "base/base_export.h"
michael@0 14 #include "base/memory/ref_counted.h"
michael@0 15 #include "base/memory/scoped_ptr.h"
michael@0 16
michael@0 17 template <typename T>
michael@0 18 class ScopedVector;
michael@0 19
michael@0 20 namespace base {
michael@0 21 namespace internal {
michael@0 22
michael@0 23 // BindStateBase is used to provide an opaque handle that the Callback
michael@0 24 // class can use to represent a function object with bound arguments. It
michael@0 25 // behaves as an existential type that is used by a corresponding
michael@0 26 // DoInvoke function to perform the function execution. This allows
michael@0 27 // us to shield the Callback class from the types of the bound argument via
michael@0 28 // "type erasure."
michael@0 29 class BindStateBase : public RefCountedThreadSafe<BindStateBase> {
michael@0 30 protected:
michael@0 31 friend class RefCountedThreadSafe<BindStateBase>;
michael@0 32 virtual ~BindStateBase() {}
michael@0 33 };
michael@0 34
michael@0 35 // Holds the Callback methods that don't require specialization to reduce
michael@0 36 // template bloat.
michael@0 37 class BASE_EXPORT CallbackBase {
michael@0 38 public:
michael@0 39 // Returns true if Callback is null (doesn't refer to anything).
michael@0 40 bool is_null() const;
michael@0 41
michael@0 42 // Returns the Callback into an uninitialized state.
michael@0 43 void Reset();
michael@0 44
michael@0 45 protected:
michael@0 46 // In C++, it is safe to cast function pointers to function pointers of
michael@0 47 // another type. It is not okay to use void*. We create a InvokeFuncStorage
michael@0 48 // that that can store our function pointer, and then cast it back to
michael@0 49 // the original type on usage.
michael@0 50 typedef void(*InvokeFuncStorage)(void);
michael@0 51
michael@0 52 // Returns true if this callback equals |other|. |other| may be null.
michael@0 53 bool Equals(const CallbackBase& other) const;
michael@0 54
michael@0 55 // Allow initializing of |bind_state_| via the constructor to avoid default
michael@0 56 // initialization of the scoped_refptr. We do not also initialize
michael@0 57 // |polymorphic_invoke_| here because doing a normal assignment in the
michael@0 58 // derived Callback templates makes for much nicer compiler errors.
michael@0 59 explicit CallbackBase(BindStateBase* bind_state);
michael@0 60
michael@0 61 // Force the destructor to be instantiated inside this translation unit so
michael@0 62 // that our subclasses will not get inlined versions. Avoids more template
michael@0 63 // bloat.
michael@0 64 ~CallbackBase();
michael@0 65
michael@0 66 scoped_refptr<BindStateBase> bind_state_;
michael@0 67 InvokeFuncStorage polymorphic_invoke_;
michael@0 68 };
michael@0 69
michael@0 70 // This is a typetraits object that's used to take an argument type, and
michael@0 71 // extract a suitable type for storing and forwarding arguments.
michael@0 72 //
michael@0 73 // In particular, it strips off references, and converts arrays to
michael@0 74 // pointers for storage; and it avoids accidentally trying to create a
michael@0 75 // "reference of a reference" if the argument is a reference type.
michael@0 76 //
michael@0 77 // This array type becomes an issue for storage because we are passing bound
michael@0 78 // parameters by const reference. In this case, we end up passing an actual
michael@0 79 // array type in the initializer list which C++ does not allow. This will
michael@0 80 // break passing of C-string literals.
michael@0 81 template <typename T>
michael@0 82 struct CallbackParamTraits {
michael@0 83 typedef const T& ForwardType;
michael@0 84 typedef T StorageType;
michael@0 85 };
michael@0 86
michael@0 87 // The Storage should almost be impossible to trigger unless someone manually
michael@0 88 // specifies type of the bind parameters. However, in case they do,
michael@0 89 // this will guard against us accidentally storing a reference parameter.
michael@0 90 //
michael@0 91 // The ForwardType should only be used for unbound arguments.
michael@0 92 template <typename T>
michael@0 93 struct CallbackParamTraits<T&> {
michael@0 94 typedef T& ForwardType;
michael@0 95 typedef T StorageType;
michael@0 96 };
michael@0 97
michael@0 98 // Note that for array types, we implicitly add a const in the conversion. This
michael@0 99 // means that it is not possible to bind array arguments to functions that take
michael@0 100 // a non-const pointer. Trying to specialize the template based on a "const
michael@0 101 // T[n]" does not seem to match correctly, so we are stuck with this
michael@0 102 // restriction.
michael@0 103 template <typename T, size_t n>
michael@0 104 struct CallbackParamTraits<T[n]> {
michael@0 105 typedef const T* ForwardType;
michael@0 106 typedef const T* StorageType;
michael@0 107 };
michael@0 108
michael@0 109 // See comment for CallbackParamTraits<T[n]>.
michael@0 110 template <typename T>
michael@0 111 struct CallbackParamTraits<T[]> {
michael@0 112 typedef const T* ForwardType;
michael@0 113 typedef const T* StorageType;
michael@0 114 };
michael@0 115
michael@0 116 // Parameter traits for movable-but-not-copyable scopers.
michael@0 117 //
michael@0 118 // Callback<>/Bind() understands movable-but-not-copyable semantics where
michael@0 119 // the type cannot be copied but can still have its state destructively
michael@0 120 // transferred (aka. moved) to another instance of the same type by calling a
michael@0 121 // helper function. When used with Bind(), this signifies transferal of the
michael@0 122 // object's state to the target function.
michael@0 123 //
michael@0 124 // For these types, the ForwardType must not be a const reference, or a
michael@0 125 // reference. A const reference is inappropriate, and would break const
michael@0 126 // correctness, because we are implementing a destructive move. A non-const
michael@0 127 // reference cannot be used with temporaries which means the result of a
michael@0 128 // function or a cast would not be usable with Callback<> or Bind().
michael@0 129 //
michael@0 130 // TODO(ajwong): We might be able to use SFINAE to search for the existence of
michael@0 131 // a Pass() function in the type and avoid the whitelist in CallbackParamTraits
michael@0 132 // and CallbackForward.
michael@0 133 template <typename T, typename D>
michael@0 134 struct CallbackParamTraits<scoped_ptr<T, D> > {
michael@0 135 typedef scoped_ptr<T, D> ForwardType;
michael@0 136 typedef scoped_ptr<T, D> StorageType;
michael@0 137 };
michael@0 138
michael@0 139 template <typename T, typename R>
michael@0 140 struct CallbackParamTraits<scoped_ptr_malloc<T, R> > {
michael@0 141 typedef scoped_ptr_malloc<T, R> ForwardType;
michael@0 142 typedef scoped_ptr_malloc<T, R> StorageType;
michael@0 143 };
michael@0 144
michael@0 145 template <typename T>
michael@0 146 struct CallbackParamTraits<ScopedVector<T> > {
michael@0 147 typedef ScopedVector<T> ForwardType;
michael@0 148 typedef ScopedVector<T> StorageType;
michael@0 149 };
michael@0 150
michael@0 151 // CallbackForward() is a very limited simulation of C++11's std::forward()
michael@0 152 // used by the Callback/Bind system for a set of movable-but-not-copyable
michael@0 153 // types. It is needed because forwarding a movable-but-not-copyable
michael@0 154 // argument to another function requires us to invoke the proper move
michael@0 155 // operator to create a rvalue version of the type. The supported types are
michael@0 156 // whitelisted below as overloads of the CallbackForward() function. The
michael@0 157 // default template compiles out to be a no-op.
michael@0 158 //
michael@0 159 // In C++11, std::forward would replace all uses of this function. However, it
michael@0 160 // is impossible to implement a general std::forward with C++11 due to a lack
michael@0 161 // of rvalue references.
michael@0 162 //
michael@0 163 // In addition to Callback/Bind, this is used by PostTaskAndReplyWithResult to
michael@0 164 // simulate std::forward() and forward the result of one Callback as a
michael@0 165 // parameter to another callback. This is to support Callbacks that return
michael@0 166 // the movable-but-not-copyable types whitelisted above.
michael@0 167 template <typename T>
michael@0 168 T& CallbackForward(T& t) { return t; }
michael@0 169
michael@0 170 template <typename T, typename D>
michael@0 171 scoped_ptr<T, D> CallbackForward(scoped_ptr<T, D>& p) { return p.Pass(); }
michael@0 172
michael@0 173 template <typename T, typename R>
michael@0 174 scoped_ptr_malloc<T, R> CallbackForward(scoped_ptr_malloc<T, R>& p) {
michael@0 175 return p.Pass();
michael@0 176 }
michael@0 177
michael@0 178 template <typename T>
michael@0 179 ScopedVector<T> CallbackForward(ScopedVector<T>& p) { return p.Pass(); }
michael@0 180
michael@0 181 } // namespace internal
michael@0 182 } // namespace base
michael@0 183
michael@0 184 #endif // BASE_CALLBACK_INTERNAL_H_

mercurial