Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 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 
     11 #include "base/atomic_ref_count.h"
     12 #include "base/base_export.h"
     13 #include "base/callback_forward.h"
     14 #include "base/macros.h"
     15 #include "base/memory/ref_counted.h"
     16 
     17 namespace base {
     18 namespace internal {
     19 template <CopyMode copy_mode>
     20 class CallbackBase;
     21 
     22 // BindStateBase is used to provide an opaque handle that the Callback
     23 // class can use to represent a function object with bound arguments.  It
     24 // behaves as an existential type that is used by a corresponding
     25 // DoInvoke function to perform the function execution.  This allows
     26 // us to shield the Callback class from the types of the bound argument via
     27 // "type erasure."
     28 // At the base level, the only task is to add reference counting data. Don't use
     29 // RefCountedThreadSafe since it requires the destructor to be a virtual method.
     30 // Creating a vtable for every BindState template instantiation results in a lot
     31 // of bloat. Its only task is to call the destructor which can be done with a
     32 // function pointer.
     33 class BindStateBase {
     34  protected:
     35   explicit BindStateBase(void (*destructor)(BindStateBase*))
     36       : ref_count_(0), destructor_(destructor) {}
     37   ~BindStateBase() = default;
     38 
     39  private:
     40   friend class scoped_refptr<BindStateBase>;
     41   template <CopyMode copy_mode>
     42   friend class CallbackBase;
     43 
     44   void AddRef();
     45   void Release();
     46 
     47   AtomicRefCount ref_count_;
     48 
     49   // Pointer to a function that will properly destroy |this|.
     50   void (*destructor_)(BindStateBase*);
     51 
     52   DISALLOW_COPY_AND_ASSIGN(BindStateBase);
     53 };
     54 
     55 // Holds the Callback methods that don't require specialization to reduce
     56 // template bloat.
     57 // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
     58 // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
     59 template <>
     60 class BASE_EXPORT CallbackBase<CopyMode::MoveOnly> {
     61  public:
     62   CallbackBase(CallbackBase&& c);
     63   CallbackBase& operator=(CallbackBase&& c);
     64 
     65   // Returns true if Callback is null (doesn't refer to anything).
     66   bool is_null() const { return bind_state_.get() == NULL; }
     67   explicit operator bool() const { return !is_null(); }
     68 
     69   // Returns the Callback into an uninitialized state.
     70   void Reset();
     71 
     72  protected:
     73   // In C++, it is safe to cast function pointers to function pointers of
     74   // another type. It is not okay to use void*. We create a InvokeFuncStorage
     75   // that that can store our function pointer, and then cast it back to
     76   // the original type on usage.
     77   using InvokeFuncStorage = void(*)();
     78 
     79   // Returns true if this callback equals |other|. |other| may be null.
     80   bool EqualsInternal(const CallbackBase& other) const;
     81 
     82   // Allow initializing of |bind_state_| via the constructor to avoid default
     83   // initialization of the scoped_refptr.  We do not also initialize
     84   // |polymorphic_invoke_| here because doing a normal assignment in the
     85   // derived Callback templates makes for much nicer compiler errors.
     86   explicit CallbackBase(BindStateBase* bind_state);
     87 
     88   // Force the destructor to be instantiated inside this translation unit so
     89   // that our subclasses will not get inlined versions.  Avoids more template
     90   // bloat.
     91   ~CallbackBase();
     92 
     93   scoped_refptr<BindStateBase> bind_state_;
     94   InvokeFuncStorage polymorphic_invoke_ = nullptr;
     95 };
     96 
     97 // CallbackBase<Copyable> is a direct base class of Copyable Callbacks.
     98 template <>
     99 class BASE_EXPORT CallbackBase<CopyMode::Copyable>
    100     : public CallbackBase<CopyMode::MoveOnly> {
    101  public:
    102   CallbackBase(const CallbackBase& c);
    103   CallbackBase(CallbackBase&& c);
    104   CallbackBase& operator=(const CallbackBase& c);
    105   CallbackBase& operator=(CallbackBase&& c);
    106  protected:
    107   explicit CallbackBase(BindStateBase* bind_state)
    108       : CallbackBase<CopyMode::MoveOnly>(bind_state) {}
    109   ~CallbackBase() {}
    110 };
    111 
    112 extern template class CallbackBase<CopyMode::MoveOnly>;
    113 extern template class CallbackBase<CopyMode::Copyable>;
    114 
    115 }  // namespace internal
    116 }  // namespace base
    117 
    118 #endif  // BASE_CALLBACK_INTERNAL_H_
    119