Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Unified Diff: webrtc/base/bind.h

Issue 2711113008: Adding rtc::Unretained to allow avoiding rtc::Bind reference capture. (Closed)
Patch Set: Rebase onto master Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | webrtc/base/bind_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/base/bind.h
diff --git a/webrtc/base/bind.h b/webrtc/base/bind.h
index 397a4d5c876608a07ecc5584c2f7f06d42250304..94eb164986f9b717766a68f6c85d4c10b2e1501a 100644
--- a/webrtc/base/bind.h
+++ b/webrtc/base/bind.h
@@ -17,6 +17,10 @@
// ref-counted method object or any arguments passed by pointer, and calling the
// functor with a destroyed object will surely do bad things.
//
+// To prevent the method object from being captured as a scoped_refptr<>, you
+// can use Unretained. But this should only be done when absolutely necessary,
+// and when the caller knows the extra reference isn't needed.
+//
// Example usage:
// struct Foo {
// int Test1() { return 42; }
@@ -125,8 +129,23 @@ struct PointerType {
T*>::type type;
};
+template <typename T>
+class UnretainedWrapper {
+ public:
+ explicit UnretainedWrapper(T* o) : ptr_(o) {}
+ T* get() const { return ptr_; }
+
+ private:
+ T* ptr_;
+};
+
} // namespace detail
+template <typename T>
+static inline detail::UnretainedWrapper<T> Unretained(T* o) {
+ return detail::UnretainedWrapper<T>(o);
+}
+
template <class ObjectT, class MethodT, class R, typename... Args>
class MethodFunctor {
public:
@@ -150,6 +169,31 @@ class MethodFunctor {
typename std::tuple<typename std::remove_reference<Args>::type...> args_;
};
+template <class ObjectT, class MethodT, class R, typename... Args>
+class UnretainedMethodFunctor {
+ public:
+ UnretainedMethodFunctor(MethodT method,
+ detail::UnretainedWrapper<ObjectT> object,
+ Args... args)
+ : method_(method), object_(object.get()), args_(args...) {}
+ R operator()() const {
+ return CallMethod(typename sequence_generator<sizeof...(Args)>::type());
+ }
+
+ private:
+ // Use sequence_generator (see template_util.h) to expand an
+ // UnretainedMethodFunctor with 2 arguments to (std::get<0>(args_),
+ // std::get<1>(args_)), for instance.
+ template <int... S>
+ R CallMethod(sequence<S...>) const {
+ return (object_->*method_)(std::get<S>(args_)...);
+ }
+
+ MethodT method_;
+ ObjectT* object_;
+ typename std::tuple<typename std::remove_reference<Args>::type...> args_;
+};
+
template <class FunctorT, class R, typename... Args>
class Functor {
public:
@@ -183,6 +227,24 @@ MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
args...);
}
+template <class ObjectT, class R, typename... Args>
+MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
+ FP_T(method),
+ const scoped_refptr<ObjectT>& object,
+ typename detail::identity<Args>::type... args) {
+ return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(),
+ args...);
+}
+
+template <class ObjectT, class R, typename... Args>
+UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
+ FP_T(method),
+ detail::UnretainedWrapper<ObjectT> object,
+ typename detail::identity<Args>::type... args) {
+ return UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(
+ method, object, args...);
+}
+
#undef FP_T
#define FP_T(x) R (ObjectT::*x)(Args...) const
@@ -194,17 +256,13 @@ MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind(
return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object,
args...);
}
-
-#undef FP_T
-#define FP_T(x) R (ObjectT::*x)(Args...)
-
template <class ObjectT, class R, typename... Args>
-MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
+UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind(
FP_T(method),
- const scoped_refptr<ObjectT>& object,
+ detail::UnretainedWrapper<const ObjectT> object,
typename detail::identity<Args>::type... args) {
- return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(),
- args...);
+ return UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(
+ method, object, args...);
}
#undef FP_T
« no previous file with comments | « no previous file | webrtc/base/bind_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698