[go: nahoru, domu]

blob: 9bb0c0f6679dbd09d1e2cfcdd1d38ac85ec8f287 [file] [log] [blame]
ajwong@chromium.orgac4c6682012-01-04 00:57:391// Copyright (c) 2012 The Chromium Authors. All rights reserved.
akalin@chromium.org2041cf342010-02-19 03:15:592// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_CALLBACK_H_
6#define BASE_CALLBACK_H_
7
erikwright@chromium.orgd7f75242011-12-07 21:44:068#include "base/callback_forward.h"
ajwong@chromium.org59eff912011-02-18 23:29:319#include "base/callback_internal.h"
erikwright@chromium.orgd7f75242011-12-07 21:44:0610
11// NOTE: Header files that do not require the full definition of Callback or
12// Closure should #include "base/callback_forward.h" instead of this file.
akalin@chromium.org2041cf342010-02-19 03:15:5913
brettw@chromium.org24292642012-07-12 20:06:4014// -----------------------------------------------------------------------------
tzik703f1562016-09-02 07:36:5515// Usage documentation
brettw@chromium.org24292642012-07-12 20:06:4016// -----------------------------------------------------------------------------
akalin@chromium.org2041cf342010-02-19 03:15:5917//
tzik703f1562016-09-02 07:36:5518// See //docs/callback.md for documentation.
ajwong@chromium.org4346ef912011-02-19 00:52:1519
tzik77d411392016-03-09 09:47:0320namespace base {
ajwong@chromium.orge24f8762011-12-20 00:10:0421
tzik27d1e312016-09-13 05:28:5922namespace internal {
tzikcaf1d84b2016-06-28 12:22:2123
dcheng77172b92016-11-22 07:46:0624template <typename CallbackType>
25struct IsOnceCallback : std::false_type {};
26
27template <typename Signature>
28struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {};
29
tzik27d1e312016-09-13 05:28:5930// RunMixin provides different variants of `Run()` function to `Callback<>`
31// based on the type of callback.
32template <typename CallbackType>
33class RunMixin;
34
35// Specialization for OnceCallback.
36template <typename R, typename... Args>
dcheng77172b92016-11-22 07:46:0637class RunMixin<OnceCallback<R(Args...)>> {
tzik27d1e312016-09-13 05:28:5938 private:
dcheng77172b92016-11-22 07:46:0639 using CallbackType = OnceCallback<R(Args...)>;
tzik27d1e312016-09-13 05:28:5940
41 public:
42 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
dcheng77172b92016-11-22 07:46:0643
dcheng3f2fd66e2016-12-20 23:56:5944 R Run(Args... args) const & {
dcheng77172b92016-11-22 07:46:0645 // Note: even though this static_assert will trivially always fail, it
46 // cannot be simply replaced with static_assert(false, ...) because:
47 // - Per [dcl.dcl]/p4, a program is ill-formed if the constant-expression
48 // argument does not evaluate to true.
49 // - Per [temp.res]/p8, if no valid specialization can be generated for a
50 // template definition, and that template is not instantiated, the
51 // template definition is ill-formed, no diagnostic required.
52 // These two clauses, taken together, would allow a conforming C++ compiler
53 // to immediately reject static_assert(false, ...), even inside an
54 // uninstantiated template.
55 static_assert(!IsOnceCallback<CallbackType>::value,
dcheng3f2fd66e2016-12-20 23:56:5956 "OnceCallback::Run() may only be invoked on a non-const "
57 "rvalue, i.e. std::move(callback).Run().");
dcheng77172b92016-11-22 07:46:0658 }
tzik27d1e312016-09-13 05:28:5959
60 R Run(Args... args) && {
61 // Move the callback instance into a local variable before the invocation,
62 // that ensures the internal state is cleared after the invocation.
63 // It's not safe to touch |this| after the invocation, since running the
64 // bound function may destroy |this|.
65 CallbackType cb = static_cast<CallbackType&&>(*this);
66 PolymorphicInvoke f =
67 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
68 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
69 }
70};
71
72// Specialization for RepeatingCallback.
dcheng77172b92016-11-22 07:46:0673template <typename R, typename... Args>
74class RunMixin<RepeatingCallback<R(Args...)>> {
tzik27d1e312016-09-13 05:28:5975 private:
dcheng77172b92016-11-22 07:46:0676 using CallbackType = RepeatingCallback<R(Args...)>;
tzik27d1e312016-09-13 05:28:5977
78 public:
79 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
80
81 R Run(Args... args) const {
82 const CallbackType& cb = static_cast<const CallbackType&>(*this);
83 PolymorphicInvoke f =
84 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
85 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
86 }
87};
88
89template <typename From, typename To>
90struct IsCallbackConvertible : std::false_type {};
91
92template <typename Signature>
dcheng77172b92016-11-22 07:46:0693struct IsCallbackConvertible<RepeatingCallback<Signature>,
94 OnceCallback<Signature>> : std::true_type {};
tzik27d1e312016-09-13 05:28:5995
96} // namespace internal
97
98template <typename R,
99 typename... Args,
100 internal::CopyMode copy_mode,
101 internal::RepeatMode repeat_mode>
102class Callback<R(Args...), copy_mode, repeat_mode>
103 : public internal::CallbackBase<copy_mode>,
104 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> {
105 public:
106 static_assert(repeat_mode != internal::RepeatMode::Once ||
107 copy_mode == internal::CopyMode::MoveOnly,
108 "OnceCallback must be MoveOnly.");
109
110 using RunType = R(Args...);
ajwong@chromium.orgb38d3572011-02-15 01:27:38111
tzik77d411392016-03-09 09:47:03112 Callback() : internal::CallbackBase<copy_mode>(nullptr) {}
ajwong@chromium.orgb38d3572011-02-15 01:27:38113
tzik1886c272016-09-08 05:45:38114 explicit Callback(internal::BindStateBase* bind_state)
tzik77d411392016-03-09 09:47:03115 : internal::CallbackBase<copy_mode>(bind_state) {
akalin@chromium.org2041cf342010-02-19 03:15:59116 }
117
tzik27d1e312016-09-13 05:28:59118 template <typename OtherCallback,
119 typename = typename std::enable_if<
120 internal::IsCallbackConvertible<OtherCallback, Callback>::value
121 >::type>
122 Callback(OtherCallback other)
123 : internal::CallbackBase<copy_mode>(std::move(other)) {}
124
125 template <typename OtherCallback,
126 typename = typename std::enable_if<
127 internal::IsCallbackConvertible<OtherCallback, Callback>::value
128 >::type>
129 Callback& operator=(OtherCallback other) {
130 static_cast<internal::CallbackBase<copy_mode>&>(*this) = std::move(other);
131 return *this;
132 }
133
ajwong@chromium.org481915a772011-09-10 03:14:35134 bool Equals(const Callback& other) const {
tzik77d411392016-03-09 09:47:03135 return this->EqualsInternal(other);
ajwong@chromium.org481915a772011-09-10 03:14:35136 }
137
tzik27d1e312016-09-13 05:28:59138 friend class internal::RunMixin<Callback>;
akalin@chromium.org2041cf342010-02-19 03:15:59139};
ajwong@chromium.orgb38d3572011-02-15 01:27:38140
141} // namespace base
akalin@chromium.org2041cf342010-02-19 03:15:59142
tzikc87149e2014-11-20 01:08:20143#endif // BASE_CALLBACK_H_