summaryrefslogtreecommitdiffstats
path: root/mojo/public/cpp/bindings/callback.h
blob: 60dea1c61f51f6836c91b7e4e3dcf306cd95114c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2014 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 MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_
#define MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_

#include <utility>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "mojo/public/cpp/bindings/lib/callback_internal.h"
#include "mojo/public/cpp/bindings/lib/template_util.h"

namespace mojo {

template <typename Sig>
class Callback;

// Represents a callback with any number of parameters and no return value. The
// callback is executed by calling its Run() method. The callback may be "null",
// meaning it does nothing.
template <typename... Args>
class Callback<void(Args...)> {
 public:
  // An interface that may be implemented to define the Run() method.
  struct Runnable {
    virtual ~Runnable() {}
    virtual void Run(
        // ForwardType ensures String is passed as a const reference. Can't use
        // universal refs (Args&&) here since this method itself isn't templated
        // because it is a virtual interface. So we have to take the arguments
        // all by value (except String which we take as a const reference due to
        // ForwardType).
        typename internal::Callback_ParamTraits<Args>::ForwardType...)
        const = 0;
  };

  // Constructs a "null" callback that does nothing.
  Callback() {}

  // Constructs a callback that will run |runnable|. The callback takes
  // ownership of |runnable|.
  explicit Callback(Runnable* runnable) : sink_(new RunnableHolder(runnable)) {}

  // As above, but can take an object that isn't derived from Runnable, so long
  // as it has a compatible operator() or Run() method. operator() will be
  // preferred if the type has both.
  template <typename Sink>
  Callback(const Sink& sink) {
    using sink_type = typename internal::Conditional<
        internal::HasCompatibleCallOperator<Sink, Args...>::value,
        FunctorAdapter<Sink>, RunnableAdapter<Sink>>::type;
    sink_ = new RunnableHolder(new sink_type(sink));
  }

  // As above, but can take a compatible function pointer.
  Callback(void (*function_ptr)(
      typename internal::Callback_ParamTraits<Args>::ForwardType...))
      : sink_(new RunnableHolder(new FunctionPtrAdapter(function_ptr))) {}

  // Executes the callback function.
  void Run(typename internal::Callback_ParamTraits<Args>::ForwardType... args)
      const {
    if (sink_)
      sink_->runnable->Run(std::forward<
                 typename internal::Callback_ParamTraits<Args>::ForwardType>(
          args)...);
  }

  bool is_null() const { return !sink_.get(); }

  // Resets the callback to the "null" state.
  void reset() { sink_ = nullptr; }

 private:
  // Adapts a class that has a Run() method but is not derived from Runnable to
  // be callable by Callback.
  template <typename Sink>
  struct RunnableAdapter : public Runnable {
    explicit RunnableAdapter(const Sink& sink) : sink(sink) {}
    virtual void Run(
        typename internal::Callback_ParamTraits<Args>::ForwardType... args)
        const override {
      sink.Run(std::forward<
               typename internal::Callback_ParamTraits<Args>::ForwardType>(
          args)...);
    }
    Sink sink;
  };

  // Adapts a class that has a compatible operator() to be callable by Callback.
  template <typename Sink>
  struct FunctorAdapter : public Runnable {
    explicit FunctorAdapter(const Sink& sink) : sink(sink) {}
    virtual void Run(
        typename internal::Callback_ParamTraits<Args>::ForwardType... args)
        const override {
      sink.operator()(
          std::forward<
              typename internal::Callback_ParamTraits<Args>::ForwardType>(
              args)...);
    }
    Sink sink;
  };

  // Adapts a function pointer.
  struct FunctionPtrAdapter : public Runnable {
   private:
    using FunctionPtr =
        void (*)(typename internal::Callback_ParamTraits<Args>::ForwardType...);

   public:
    explicit FunctionPtrAdapter(FunctionPtr function_ptr)
        : function_ptr(function_ptr) {}
    virtual void Run(
        typename internal::Callback_ParamTraits<Args>::ForwardType... args)
        const override {
      (*function_ptr)(
          std::forward<
              typename internal::Callback_ParamTraits<Args>::ForwardType>(
              args)...);
    }
    FunctionPtr function_ptr;
  };

  struct RunnableHolder : public base::RefCountedThreadSafe<RunnableHolder> {
    explicit RunnableHolder(Runnable* runnable) : runnable(runnable) {}

    scoped_ptr<Runnable> runnable;

   private:
    friend class base::RefCountedThreadSafe<RunnableHolder>;
    ~RunnableHolder() {}
  };

  scoped_refptr<RunnableHolder> sink_;
};

// A specialization of Callback which takes no parameters.
typedef Callback<void()> Closure;

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_CALLBACK_H_