Adding rtc::Unretained to allow avoiding rtc::Bind reference capture.

In some rare circumstances, capturing a reference may be undesired. For
example, when creating an asynchronous task owned by the object itself,
the object may not need or want this task to keep itself alive.

BUG=None

Review-Url: https://codereview.webrtc.org/2711113008
Cr-Commit-Position: refs/heads/master@{#16840}
diff --git a/webrtc/base/bind.h b/webrtc/base/bind.h
index 397a4d5..94eb164 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 @@
                                        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 @@
   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 @@
                                                           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 @@
   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
diff --git a/webrtc/base/bind_unittest.cc b/webrtc/base/bind_unittest.cc
index 3331591..c97a555 100644
--- a/webrtc/base/bind_unittest.cc
+++ b/webrtc/base/bind_unittest.cc
@@ -87,6 +87,8 @@
 EXPECT_IS_CAPTURED_AS_PTR(A);
 EXPECT_IS_CAPTURED_AS_PTR(D);
 EXPECT_IS_CAPTURED_AS_PTR(RefCountInterface*);
+EXPECT_IS_CAPTURED_AS_PTR(
+    decltype(Unretained<RefCountedObject<RefCountInterface>>));
 
 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountInterface);
 EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(B);