Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file contains utility functions and classes that help the
      6 // implementation, and management of the Callback objects.
      7 
      8 #ifndef BASE_CALLBACK_INTERNAL_H_
      9 #define BASE_CALLBACK_INTERNAL_H_
     10 #pragma once
     11 
     12 #include <stddef.h>
     13 
     14 #include "base/base_api.h"
     15 #include "base/memory/ref_counted.h"
     16 
     17 namespace base {
     18 namespace internal {
     19 
     20 // InvokerStorageBase is used to provide an opaque handle that the Callback
     21 // class can use to represent a function object with bound arguments.  It
     22 // behaves as an existential type that is used by a corresponding
     23 // DoInvoke function to perform the function execution.  This allows
     24 // us to shield the Callback class from the types of the bound argument via
     25 // "type erasure."
     26 class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> {
     27  protected:
     28   friend class RefCountedThreadSafe<InvokerStorageBase>;
     29   virtual ~InvokerStorageBase() {}
     30 };
     31 
     32 // This structure exists purely to pass the returned |invoker_storage_| from
     33 // Bind() to Callback while avoiding an extra AddRef/Release() pair.
     34 //
     35 // To do this, the constructor of Callback<> must take a const-ref.  The
     36 // reference must be to a const object otherwise the compiler will emit a
     37 // warning about taking a reference to a temporary.
     38 //
     39 // Unfortunately, this means that the internal |invoker_storage_| field must
     40 // be made mutable.
     41 template <typename T>
     42 struct InvokerStorageHolder {
     43   explicit InvokerStorageHolder(T* invoker_storage)
     44       : invoker_storage_(invoker_storage) {
     45   }
     46 
     47   mutable scoped_refptr<InvokerStorageBase> invoker_storage_;
     48 };
     49 
     50 template <typename T>
     51 InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) {
     52   return InvokerStorageHolder<T>(o);
     53 }
     54 
     55 // Holds the Callback methods that don't require specialization to reduce
     56 // template bloat.
     57 class BASE_API CallbackBase {
     58  public:
     59   // Returns true if Callback is null (doesn't refer to anything).
     60   bool is_null() const;
     61 
     62   // Returns the Callback into an uninitalized state.
     63   void Reset();
     64 
     65   bool Equals(const CallbackBase& other) const;
     66 
     67  protected:
     68   // In C++, it is safe to cast function pointers to function pointers of
     69   // another type. It is not okay to use void*. We create a InvokeFuncStorage
     70   // that that can store our function pointer, and then cast it back to
     71   // the original type on usage.
     72   typedef void(*InvokeFuncStorage)(void);
     73 
     74   CallbackBase(InvokeFuncStorage polymorphic_invoke,
     75                scoped_refptr<InvokerStorageBase>* invoker_storage);
     76 
     77   // Force the destructor to be instaniated inside this translation unit so
     78   // that our subclasses will not get inlined versions.  Avoids more template
     79   // bloat.
     80   ~CallbackBase();
     81 
     82   scoped_refptr<InvokerStorageBase> invoker_storage_;
     83   InvokeFuncStorage polymorphic_invoke_;
     84 };
     85 
     86 // This is a typetraits object that's used to take an argument type, and
     87 // extract a suitable type for storing and forwarding arguments.
     88 //
     89 // In particular, it strips off references, and converts arrays to
     90 // pointers for storage; and it avoids accidentally trying to create a
     91 // "reference of a reference" if the argument is a reference type.
     92 //
     93 // This array type becomes an issue for storage because we are passing bound
     94 // parameters by const reference. In this case, we end up passing an actual
     95 // array type in the initializer list which C++ does not allow.  This will
     96 // break passing of C-string literals.
     97 template <typename T>
     98 struct ParamTraits {
     99   typedef const T& ForwardType;
    100   typedef T StorageType;
    101 };
    102 
    103 // The Storage should almost be impossible to trigger unless someone manually
    104 // specifies type of the bind parameters.  However, in case they do,
    105 // this will guard against us accidentally storing a reference parameter.
    106 //
    107 // The ForwardType should only be used for unbound arguments.
    108 template <typename T>
    109 struct ParamTraits<T&> {
    110   typedef T& ForwardType;
    111   typedef T StorageType;
    112 };
    113 
    114 // Note that for array types, we implicitly add a const in the conversion. This
    115 // means that it is not possible to bind array arguments to functions that take
    116 // a non-const pointer. Trying to specialize the template based on a "const
    117 // T[n]" does not seem to match correctly, so we are stuck with this
    118 // restriction.
    119 template <typename T, size_t n>
    120 struct ParamTraits<T[n]> {
    121   typedef const T* ForwardType;
    122   typedef const T* StorageType;
    123 };
    124 
    125 // See comment for ParamTraits<T[n]>.
    126 template <typename T>
    127 struct ParamTraits<T[]> {
    128   typedef const T* ForwardType;
    129   typedef const T* StorageType;
    130 };
    131 
    132 }  // namespace internal
    133 }  // namespace base
    134 
    135 #endif  // BASE_CALLBACK_INTERNAL_H_
    136