OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 // Bind() is an overloaded function that converts method calls into function | 11 // Bind() is an overloaded function that converts method calls into function |
12 // objects (aka functors). The method object is captured as a scoped_refptr<> if | 12 // objects (aka functors). The method object is captured as a scoped_refptr<> if |
13 // possible, and as a raw pointer otherwise. Any arguments to the method are | 13 // possible, and as a raw pointer otherwise. Any arguments to the method are |
14 // captured by value. The return value of Bind is a stateful, nullary function | 14 // captured by value. The return value of Bind is a stateful, nullary function |
15 // object. Care should be taken about the lifetime of objects captured by | 15 // object. Care should be taken about the lifetime of objects captured by |
16 // Bind(); the returned functor knows nothing about the lifetime of a non | 16 // Bind(); the returned functor knows nothing about the lifetime of a non |
17 // ref-counted method object or any arguments passed by pointer, and calling the | 17 // ref-counted method object or any arguments passed by pointer, and calling the |
18 // functor with a destroyed object will surely do bad things. | 18 // functor with a destroyed object will surely do bad things. |
19 // | 19 // |
| 20 // To prevent the method object from being captured as a scoped_refptr<>, you |
| 21 // can use Unretained. But this should only be done when absolutely necessary, |
| 22 // and when the caller knows the extra reference isn't needed. |
| 23 // |
20 // Example usage: | 24 // Example usage: |
21 // struct Foo { | 25 // struct Foo { |
22 // int Test1() { return 42; } | 26 // int Test1() { return 42; } |
23 // int Test2() const { return 52; } | 27 // int Test2() const { return 52; } |
24 // int Test3(int x) { return x*x; } | 28 // int Test3(int x) { return x*x; } |
25 // float Test4(int x, float y) { return x + y; } | 29 // float Test4(int x, float y) { return x + y; } |
26 // }; | 30 // }; |
27 // | 31 // |
28 // int main() { | 32 // int main() { |
29 // Foo foo; | 33 // Foo foo; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 | 122 |
119 // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T* | 123 // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T* |
120 // otherwise. | 124 // otherwise. |
121 template <class T> | 125 template <class T> |
122 struct PointerType { | 126 struct PointerType { |
123 typedef typename TernaryTypeOperator<IsRefCounted<T>::value, | 127 typedef typename TernaryTypeOperator<IsRefCounted<T>::value, |
124 scoped_refptr<T>, | 128 scoped_refptr<T>, |
125 T*>::type type; | 129 T*>::type type; |
126 }; | 130 }; |
127 | 131 |
| 132 template <typename T> |
| 133 class UnretainedWrapper { |
| 134 public: |
| 135 explicit UnretainedWrapper(T* o) : ptr_(o) {} |
| 136 T* get() const { return ptr_; } |
| 137 |
| 138 private: |
| 139 T* ptr_; |
| 140 }; |
| 141 |
128 } // namespace detail | 142 } // namespace detail |
129 | 143 |
| 144 template <typename T> |
| 145 static inline detail::UnretainedWrapper<T> Unretained(T* o) { |
| 146 return detail::UnretainedWrapper<T>(o); |
| 147 } |
| 148 |
130 template <class ObjectT, class MethodT, class R, typename... Args> | 149 template <class ObjectT, class MethodT, class R, typename... Args> |
131 class MethodFunctor { | 150 class MethodFunctor { |
132 public: | 151 public: |
133 MethodFunctor(MethodT method, ObjectT* object, Args... args) | 152 MethodFunctor(MethodT method, ObjectT* object, Args... args) |
134 : method_(method), object_(object), args_(args...) {} | 153 : method_(method), object_(object), args_(args...) {} |
135 R operator()() const { | 154 R operator()() const { |
136 return CallMethod(typename sequence_generator<sizeof...(Args)>::type()); | 155 return CallMethod(typename sequence_generator<sizeof...(Args)>::type()); |
137 } | 156 } |
138 | 157 |
139 private: | 158 private: |
140 // Use sequence_generator (see template_util.h) to expand a MethodFunctor | 159 // Use sequence_generator (see template_util.h) to expand a MethodFunctor |
141 // with 2 arguments to (std::get<0>(args_), std::get<1>(args_)), for | 160 // with 2 arguments to (std::get<0>(args_), std::get<1>(args_)), for |
142 // instance. | 161 // instance. |
143 template <int... S> | 162 template <int... S> |
144 R CallMethod(sequence<S...>) const { | 163 R CallMethod(sequence<S...>) const { |
145 return (object_->*method_)(std::get<S>(args_)...); | 164 return (object_->*method_)(std::get<S>(args_)...); |
146 } | 165 } |
147 | 166 |
148 MethodT method_; | 167 MethodT method_; |
149 typename detail::PointerType<ObjectT>::type object_; | 168 typename detail::PointerType<ObjectT>::type object_; |
150 typename std::tuple<typename std::remove_reference<Args>::type...> args_; | 169 typename std::tuple<typename std::remove_reference<Args>::type...> args_; |
151 }; | 170 }; |
152 | 171 |
| 172 template <class ObjectT, class MethodT, class R, typename... Args> |
| 173 class UnretainedMethodFunctor { |
| 174 public: |
| 175 UnretainedMethodFunctor(MethodT method, |
| 176 detail::UnretainedWrapper<ObjectT> object, |
| 177 Args... args) |
| 178 : method_(method), object_(object.get()), args_(args...) {} |
| 179 R operator()() const { |
| 180 return CallMethod(typename sequence_generator<sizeof...(Args)>::type()); |
| 181 } |
| 182 |
| 183 private: |
| 184 // Use sequence_generator (see template_util.h) to expand an |
| 185 // UnretainedMethodFunctor with 2 arguments to (std::get<0>(args_), |
| 186 // std::get<1>(args_)), for instance. |
| 187 template <int... S> |
| 188 R CallMethod(sequence<S...>) const { |
| 189 return (object_->*method_)(std::get<S>(args_)...); |
| 190 } |
| 191 |
| 192 MethodT method_; |
| 193 ObjectT* object_; |
| 194 typename std::tuple<typename std::remove_reference<Args>::type...> args_; |
| 195 }; |
| 196 |
153 template <class FunctorT, class R, typename... Args> | 197 template <class FunctorT, class R, typename... Args> |
154 class Functor { | 198 class Functor { |
155 public: | 199 public: |
156 Functor(const FunctorT& functor, Args... args) | 200 Functor(const FunctorT& functor, Args... args) |
157 : functor_(functor), args_(args...) {} | 201 : functor_(functor), args_(args...) {} |
158 R operator()() const { | 202 R operator()() const { |
159 return CallFunction(typename sequence_generator<sizeof...(Args)>::type()); | 203 return CallFunction(typename sequence_generator<sizeof...(Args)>::type()); |
160 } | 204 } |
161 | 205 |
162 private: | 206 private: |
(...skipping 13 matching lines...) Expand all Loading... |
176 | 220 |
177 template <class ObjectT, class R, typename... Args> | 221 template <class ObjectT, class R, typename... Args> |
178 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( | 222 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( |
179 FP_T(method), | 223 FP_T(method), |
180 ObjectT* object, | 224 ObjectT* object, |
181 typename detail::identity<Args>::type... args) { | 225 typename detail::identity<Args>::type... args) { |
182 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object, | 226 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object, |
183 args...); | 227 args...); |
184 } | 228 } |
185 | 229 |
| 230 template <class ObjectT, class R, typename... Args> |
| 231 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 232 FP_T(method), |
| 233 const scoped_refptr<ObjectT>& object, |
| 234 typename detail::identity<Args>::type... args) { |
| 235 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(), |
| 236 args...); |
| 237 } |
| 238 |
| 239 template <class ObjectT, class R, typename... Args> |
| 240 UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 241 FP_T(method), |
| 242 detail::UnretainedWrapper<ObjectT> object, |
| 243 typename detail::identity<Args>::type... args) { |
| 244 return UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...>( |
| 245 method, object, args...); |
| 246 } |
| 247 |
186 #undef FP_T | 248 #undef FP_T |
187 #define FP_T(x) R (ObjectT::*x)(Args...) const | 249 #define FP_T(x) R (ObjectT::*x)(Args...) const |
188 | 250 |
189 template <class ObjectT, class R, typename... Args> | 251 template <class ObjectT, class R, typename... Args> |
190 MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind( | 252 MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind( |
191 FP_T(method), | 253 FP_T(method), |
192 const ObjectT* object, | 254 const ObjectT* object, |
193 typename detail::identity<Args>::type... args) { | 255 typename detail::identity<Args>::type... args) { |
194 return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object, | 256 return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object, |
195 args...); | 257 args...); |
196 } | 258 } |
197 | |
198 #undef FP_T | |
199 #define FP_T(x) R (ObjectT::*x)(Args...) | |
200 | |
201 template <class ObjectT, class R, typename... Args> | 259 template <class ObjectT, class R, typename... Args> |
202 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( | 260 UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind( |
203 FP_T(method), | 261 FP_T(method), |
204 const scoped_refptr<ObjectT>& object, | 262 detail::UnretainedWrapper<const ObjectT> object, |
205 typename detail::identity<Args>::type... args) { | 263 typename detail::identity<Args>::type... args) { |
206 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(), | 264 return UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>( |
207 args...); | 265 method, object, args...); |
208 } | 266 } |
209 | 267 |
210 #undef FP_T | 268 #undef FP_T |
211 #define FP_T(x) R (*x)(Args...) | 269 #define FP_T(x) R (*x)(Args...) |
212 | 270 |
213 template <class R, typename... Args> | 271 template <class R, typename... Args> |
214 Functor<FP_T(NONAME), R, Args...> Bind( | 272 Functor<FP_T(NONAME), R, Args...> Bind( |
215 FP_T(function), | 273 FP_T(function), |
216 typename detail::identity<Args>::type... args) { | 274 typename detail::identity<Args>::type... args) { |
217 return Functor<FP_T(NONAME), R, Args...>(function, args...); | 275 return Functor<FP_T(NONAME), R, Args...>(function, args...); |
218 } | 276 } |
219 | 277 |
220 #undef FP_T | 278 #undef FP_T |
221 | 279 |
222 } // namespace rtc | 280 } // namespace rtc |
223 | 281 |
224 #undef NONAME | 282 #undef NONAME |
225 | 283 |
226 #endif // WEBRTC_BASE_BIND_H_ | 284 #endif // WEBRTC_BASE_BIND_H_ |
OLD | NEW |