Update Bind to match its comments and always capture by value. Also update the generated count to 9 args.
The existing comment is wrong, and the test even ensures it: Bind will capture reference values by reference. That makes it hard to use with AsyncInvoker, because you can't safely Bind to a function that takes (const) reference params. The new version of this code strips references in the bound object, so it captures by value, but can bind against functions that take const references, they'll just be references to the copy. As the class comment implies, actual by-reference args should be passed as pointers or things that safely share (e.g. scoped_refptr) and not references directly. A new test case ensures the pointer reference works. The new code will also give a compiler error if you try to bind to a non-const reference. BUG= Review URL: https://codereview.webrtc.org/1291543006 Cr-Commit-Position: refs/heads/master@{#10397}
This commit is contained in:
@ -382,10 +382,12 @@ void WebRtcVideoCapturer::OnIncomingCapturedFrame(
|
||||
// consistency with other capturers such as in Chrome, we need to do a
|
||||
// thread hop.
|
||||
// Note that Stop() can cause the async invoke call to be cancelled.
|
||||
async_invoker_->AsyncInvoke<void>(start_thread_,
|
||||
// Note that this results in a shallow copying of the frame.
|
||||
rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread,
|
||||
this, sample));
|
||||
async_invoker_->AsyncInvoke<void>(
|
||||
start_thread_,
|
||||
// Note that Bind captures by value, so there's an intermediate copy
|
||||
// of sample.
|
||||
rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread, this,
|
||||
sample));
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,7 +397,7 @@ void WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id,
|
||||
}
|
||||
|
||||
void WebRtcVideoCapturer::SignalFrameCapturedOnStartThread(
|
||||
const webrtc::VideoFrame frame) {
|
||||
const webrtc::VideoFrame& frame) {
|
||||
// This can only happen between Start() and Stop().
|
||||
RTC_DCHECK(start_thread_);
|
||||
RTC_DCHECK(start_thread_->IsCurrent());
|
||||
|
@ -92,7 +92,7 @@ class WebRtcVideoCapturer : public VideoCapturer,
|
||||
// directly from OnIncomingCapturedFrame.
|
||||
// TODO(tommi): Remove this workaround when we've updated the WebRTC capturers
|
||||
// to follow the same contract.
|
||||
void SignalFrameCapturedOnStartThread(const webrtc::VideoFrame frame);
|
||||
void SignalFrameCapturedOnStartThread(const webrtc::VideoFrame& frame);
|
||||
|
||||
rtc::scoped_ptr<WebRtcVcmFactoryInterface> factory_;
|
||||
webrtc::VideoCaptureModule* module_;
|
||||
|
@ -65,6 +65,7 @@
|
||||
#define WEBRTC_BASE_BIND_H_
|
||||
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
#include "webrtc/base/template_util.h"
|
||||
|
||||
#define NONAME
|
||||
|
||||
@ -128,18 +129,6 @@ struct PointerType {
|
||||
T*>::type type;
|
||||
};
|
||||
|
||||
// RemoveScopedPtrRef will capture scoped_refptr by-value instead of
|
||||
// by-reference.
|
||||
template <class T> struct RemoveScopedPtrRef { typedef T type; };
|
||||
template <class T>
|
||||
struct RemoveScopedPtrRef<const scoped_refptr<T>&> {
|
||||
typedef scoped_refptr<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct RemoveScopedPtrRef<scoped_refptr<T>&> {
|
||||
typedef scoped_refptr<T> type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class ObjectT, class MethodT, class R>
|
||||
@ -220,7 +209,7 @@ class MethodFunctor1 {
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
};
|
||||
|
||||
template <class FunctorT, class R,
|
||||
@ -234,7 +223,7 @@ class Functor1 {
|
||||
return functor_(p1_); }
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
};
|
||||
|
||||
|
||||
@ -303,8 +292,8 @@ class MethodFunctor2 {
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
};
|
||||
|
||||
template <class FunctorT, class R,
|
||||
@ -320,8 +309,8 @@ class Functor2 {
|
||||
return functor_(p1_, p2_); }
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
};
|
||||
|
||||
|
||||
@ -401,9 +390,9 @@ class MethodFunctor3 {
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
};
|
||||
|
||||
template <class FunctorT, class R,
|
||||
@ -421,9 +410,9 @@ class Functor3 {
|
||||
return functor_(p1_, p2_, p3_); }
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
};
|
||||
|
||||
|
||||
@ -514,10 +503,10 @@ class MethodFunctor4 {
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename detail::RemoveScopedPtrRef<P4>::type p4_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
};
|
||||
|
||||
template <class FunctorT, class R,
|
||||
@ -537,10 +526,10 @@ class Functor4 {
|
||||
return functor_(p1_, p2_, p3_, p4_); }
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename detail::RemoveScopedPtrRef<P4>::type p4_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
};
|
||||
|
||||
|
||||
@ -642,11 +631,11 @@ class MethodFunctor5 {
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename detail::RemoveScopedPtrRef<P4>::type p4_;
|
||||
typename detail::RemoveScopedPtrRef<P5>::type p5_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
};
|
||||
|
||||
template <class FunctorT, class R,
|
||||
@ -668,11 +657,11 @@ class Functor5 {
|
||||
return functor_(p1_, p2_, p3_, p4_, p5_); }
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename detail::RemoveScopedPtrRef<P4>::type p4_;
|
||||
typename detail::RemoveScopedPtrRef<P5>::type p5_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
};
|
||||
|
||||
|
||||
@ -785,12 +774,12 @@ class MethodFunctor6 {
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename detail::RemoveScopedPtrRef<P4>::type p4_;
|
||||
typename detail::RemoveScopedPtrRef<P5>::type p5_;
|
||||
typename detail::RemoveScopedPtrRef<P6>::type p6_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
};
|
||||
|
||||
template <class FunctorT, class R,
|
||||
@ -814,12 +803,12 @@ class Functor6 {
|
||||
return functor_(p1_, p2_, p3_, p4_, p5_, p6_); }
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename detail::RemoveScopedPtrRef<P1>::type p1_;
|
||||
typename detail::RemoveScopedPtrRef<P2>::type p2_;
|
||||
typename detail::RemoveScopedPtrRef<P3>::type p3_;
|
||||
typename detail::RemoveScopedPtrRef<P4>::type p4_;
|
||||
typename detail::RemoveScopedPtrRef<P5>::type p5_;
|
||||
typename detail::RemoveScopedPtrRef<P6>::type p6_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
};
|
||||
|
||||
|
||||
@ -912,6 +901,640 @@ Bind(FP_T(function),
|
||||
|
||||
#undef FP_T
|
||||
|
||||
template <class ObjectT,
|
||||
class MethodT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7>
|
||||
class MethodFunctor7 {
|
||||
public:
|
||||
MethodFunctor7(MethodT method,
|
||||
ObjectT* object,
|
||||
P1 p1,
|
||||
P2 p2,
|
||||
P3 p3,
|
||||
P4 p4,
|
||||
P5 p5,
|
||||
P6 p6,
|
||||
P7 p7)
|
||||
: method_(method),
|
||||
object_(object),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6),
|
||||
p7_(p7) {}
|
||||
R operator()() const {
|
||||
return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_);
|
||||
}
|
||||
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
typename rtc::remove_reference<P7>::type p7_;
|
||||
};
|
||||
|
||||
template <class FunctorT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7>
|
||||
class Functor7 {
|
||||
public:
|
||||
Functor7(const FunctorT& functor,
|
||||
P1 p1,
|
||||
P2 p2,
|
||||
P3 p3,
|
||||
P4 p4,
|
||||
P5 p5,
|
||||
P6 p6,
|
||||
P7 p7)
|
||||
: functor_(functor),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6),
|
||||
p7_(p7) {}
|
||||
R operator()() const { return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_); }
|
||||
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
typename rtc::remove_reference<P7>::type p7_;
|
||||
};
|
||||
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7)
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7>
|
||||
MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
|
||||
FP_T(method),
|
||||
ObjectT* object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7) {
|
||||
return MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7>(
|
||||
method, object, p1, p2, p3, p4, p5, p6, p7);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7) const
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7>
|
||||
MethodFunctor7<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
|
||||
FP_T(method),
|
||||
const ObjectT* object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7) {
|
||||
return MethodFunctor7<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6,
|
||||
P7>(method, object, p1, p2, p3, p4, p5, p6, p7);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7)
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7>
|
||||
MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
|
||||
FP_T(method),
|
||||
const scoped_refptr<ObjectT>& object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7) {
|
||||
return MethodFunctor7<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7>(
|
||||
method, object.get(), p1, p2, p3, p4, p5, p6, p7);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7)
|
||||
|
||||
template <class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7>
|
||||
Functor7<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7> Bind(
|
||||
FP_T(function),
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7) {
|
||||
return Functor7<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7>(
|
||||
function, p1, p2, p3, p4, p5, p6, p7);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
|
||||
template <class ObjectT,
|
||||
class MethodT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8>
|
||||
class MethodFunctor8 {
|
||||
public:
|
||||
MethodFunctor8(MethodT method,
|
||||
ObjectT* object,
|
||||
P1 p1,
|
||||
P2 p2,
|
||||
P3 p3,
|
||||
P4 p4,
|
||||
P5 p5,
|
||||
P6 p6,
|
||||
P7 p7,
|
||||
P8 p8)
|
||||
: method_(method),
|
||||
object_(object),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6),
|
||||
p7_(p7),
|
||||
p8_(p8) {}
|
||||
R operator()() const {
|
||||
return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_);
|
||||
}
|
||||
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
typename rtc::remove_reference<P7>::type p7_;
|
||||
typename rtc::remove_reference<P8>::type p8_;
|
||||
};
|
||||
|
||||
template <class FunctorT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8>
|
||||
class Functor8 {
|
||||
public:
|
||||
Functor8(const FunctorT& functor,
|
||||
P1 p1,
|
||||
P2 p2,
|
||||
P3 p3,
|
||||
P4 p4,
|
||||
P5 p5,
|
||||
P6 p6,
|
||||
P7 p7,
|
||||
P8 p8)
|
||||
: functor_(functor),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6),
|
||||
p7_(p7),
|
||||
p8_(p8) {}
|
||||
R operator()() const {
|
||||
return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_);
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
typename rtc::remove_reference<P7>::type p7_;
|
||||
typename rtc::remove_reference<P8>::type p8_;
|
||||
};
|
||||
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8)
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8>
|
||||
MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8> Bind(
|
||||
FP_T(method),
|
||||
ObjectT* object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8) {
|
||||
return MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
|
||||
P8>(method, object, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8) const
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8>
|
||||
MethodFunctor8<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8>
|
||||
Bind(FP_T(method),
|
||||
const ObjectT* object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8) {
|
||||
return MethodFunctor8<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6,
|
||||
P7, P8>(method, object, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8)
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8>
|
||||
MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8> Bind(
|
||||
FP_T(method),
|
||||
const scoped_refptr<ObjectT>& object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8) {
|
||||
return MethodFunctor8<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
|
||||
P8>(method, object.get(), p1, p2, p3, p4, p5, p6, p7,
|
||||
p8);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7, P8)
|
||||
|
||||
template <class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8>
|
||||
Functor8<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8> Bind(
|
||||
FP_T(function),
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8) {
|
||||
return Functor8<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8>(
|
||||
function, p1, p2, p3, p4, p5, p6, p7, p8);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
|
||||
template <class ObjectT,
|
||||
class MethodT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8,
|
||||
class P9>
|
||||
class MethodFunctor9 {
|
||||
public:
|
||||
MethodFunctor9(MethodT method,
|
||||
ObjectT* object,
|
||||
P1 p1,
|
||||
P2 p2,
|
||||
P3 p3,
|
||||
P4 p4,
|
||||
P5 p5,
|
||||
P6 p6,
|
||||
P7 p7,
|
||||
P8 p8,
|
||||
P9 p9)
|
||||
: method_(method),
|
||||
object_(object),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6),
|
||||
p7_(p7),
|
||||
p8_(p8),
|
||||
p9_(p9) {}
|
||||
R operator()() const {
|
||||
return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_, p9_);
|
||||
}
|
||||
|
||||
private:
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
typename rtc::remove_reference<P7>::type p7_;
|
||||
typename rtc::remove_reference<P8>::type p8_;
|
||||
typename rtc::remove_reference<P9>::type p9_;
|
||||
};
|
||||
|
||||
template <class FunctorT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8,
|
||||
class P9>
|
||||
class Functor9 {
|
||||
public:
|
||||
Functor9(const FunctorT& functor,
|
||||
P1 p1,
|
||||
P2 p2,
|
||||
P3 p3,
|
||||
P4 p4,
|
||||
P5 p5,
|
||||
P6 p6,
|
||||
P7 p7,
|
||||
P8 p8,
|
||||
P9 p9)
|
||||
: functor_(functor),
|
||||
p1_(p1),
|
||||
p2_(p2),
|
||||
p3_(p3),
|
||||
p4_(p4),
|
||||
p5_(p5),
|
||||
p6_(p6),
|
||||
p7_(p7),
|
||||
p8_(p8),
|
||||
p9_(p9) {}
|
||||
R operator()() const {
|
||||
return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_, p9_);
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorT functor_;
|
||||
typename rtc::remove_reference<P1>::type p1_;
|
||||
typename rtc::remove_reference<P2>::type p2_;
|
||||
typename rtc::remove_reference<P3>::type p3_;
|
||||
typename rtc::remove_reference<P4>::type p4_;
|
||||
typename rtc::remove_reference<P5>::type p5_;
|
||||
typename rtc::remove_reference<P6>::type p6_;
|
||||
typename rtc::remove_reference<P7>::type p7_;
|
||||
typename rtc::remove_reference<P8>::type p8_;
|
||||
typename rtc::remove_reference<P9>::type p9_;
|
||||
};
|
||||
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9)
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8,
|
||||
class P9>
|
||||
MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9>
|
||||
Bind(FP_T(method),
|
||||
ObjectT* object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8,
|
||||
typename detail::identity<P9>::type p9) {
|
||||
return MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
|
||||
P8, P9>(method, object, p1, p2, p3, p4, p5, p6, p7, p8,
|
||||
p9);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8,
|
||||
class P9>
|
||||
MethodFunctor9<const ObjectT,
|
||||
FP_T(NONAME),
|
||||
R,
|
||||
P1,
|
||||
P2,
|
||||
P3,
|
||||
P4,
|
||||
P5,
|
||||
P6,
|
||||
P7,
|
||||
P8,
|
||||
P9>
|
||||
Bind(FP_T(method),
|
||||
const ObjectT* object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8,
|
||||
typename detail::identity<P9>::type p9) {
|
||||
return MethodFunctor9<const ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6,
|
||||
P7, P8, P9>(method, object, p1, p2, p3, p4, p5, p6, p7,
|
||||
p8, p9);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9)
|
||||
|
||||
template <class ObjectT,
|
||||
class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8,
|
||||
class P9>
|
||||
MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9>
|
||||
Bind(FP_T(method),
|
||||
const scoped_refptr<ObjectT>& object,
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8,
|
||||
typename detail::identity<P9>::type p9) {
|
||||
return MethodFunctor9<ObjectT, FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7,
|
||||
P8, P9>(method, object.get(), p1, p2, p3, p4, p5, p6,
|
||||
p7, p8, p9);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9)
|
||||
|
||||
template <class R,
|
||||
class P1,
|
||||
class P2,
|
||||
class P3,
|
||||
class P4,
|
||||
class P5,
|
||||
class P6,
|
||||
class P7,
|
||||
class P8,
|
||||
class P9>
|
||||
Functor9<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9> Bind(
|
||||
FP_T(function),
|
||||
typename detail::identity<P1>::type p1,
|
||||
typename detail::identity<P2>::type p2,
|
||||
typename detail::identity<P3>::type p3,
|
||||
typename detail::identity<P4>::type p4,
|
||||
typename detail::identity<P5>::type p5,
|
||||
typename detail::identity<P6>::type p6,
|
||||
typename detail::identity<P7>::type p7,
|
||||
typename detail::identity<P8>::type p8,
|
||||
typename detail::identity<P9>::type p9) {
|
||||
return Functor9<FP_T(NONAME), R, P1, P2, P3, P4, P5, P6, P7, P8, P9>(
|
||||
function, p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#undef NONAME
|
||||
|
@ -61,6 +61,7 @@
|
||||
#define WEBRTC_BASE_BIND_H_
|
||||
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
#include "webrtc/base/template_util.h"
|
||||
|
||||
#define NONAME
|
||||
|
||||
@ -124,21 +125,9 @@ struct PointerType {
|
||||
T*>::type type;
|
||||
};
|
||||
|
||||
// RemoveScopedPtrRef will capture scoped_refptr by-value instead of
|
||||
// by-reference.
|
||||
template <class T> struct RemoveScopedPtrRef { typedef T type; };
|
||||
template <class T>
|
||||
struct RemoveScopedPtrRef<const scoped_refptr<T>&> {
|
||||
typedef scoped_refptr<T> type;
|
||||
};
|
||||
template <class T>
|
||||
struct RemoveScopedPtrRef<scoped_refptr<T>&> {
|
||||
typedef scoped_refptr<T> type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
$var n = 6
|
||||
$var n = 9
|
||||
$range i 0..n
|
||||
$for i [[
|
||||
$range j 1..i
|
||||
@ -157,7 +146,7 @@ class MethodFunctor$i {
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;$for j [[
|
||||
|
||||
typename detail::RemoveScopedPtrRef<P$j>::type p$(j)_;]]
|
||||
typename rtc::remove_reference<P$j>::type p$(j)_;]]
|
||||
|
||||
};
|
||||
|
||||
@ -174,7 +163,7 @@ Functor$i(const FunctorT& functor$for j [[, P$j p$j]])
|
||||
private:
|
||||
FunctorT functor_;$for j [[
|
||||
|
||||
typename detail::RemoveScopedPtrRef<P$j>::type p$(j)_;]]
|
||||
typename rtc::remove_reference<P$j>::type p$(j)_;]]
|
||||
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,14 @@ struct MethodBindTester {
|
||||
int NullaryConst() const { ++call_count; return 2; }
|
||||
void UnaryVoid(int dummy) { ++call_count; }
|
||||
template <class T> T Identity(T value) { ++call_count; return value; }
|
||||
int UnaryByRef(int& value) const { ++call_count; return ++value; } // NOLINT
|
||||
int UnaryByPointer(int* value) const {
|
||||
++call_count;
|
||||
return ++(*value);
|
||||
}
|
||||
int UnaryByRef(const int& value) const {
|
||||
++call_count;
|
||||
return ++const_cast<int&>(value);
|
||||
}
|
||||
int Multiply(int a, int b) const { ++call_count; return a * b; }
|
||||
void RefArgument(const scoped_refptr<LifeTimeCheck>& object) {
|
||||
EXPECT_TRUE(object.get() != nullptr);
|
||||
@ -64,26 +71,25 @@ int Multiply(int a, int b) { return a * b; }
|
||||
|
||||
// Try to catch any problem with scoped_refptr type deduction in rtc::Bind at
|
||||
// compile time.
|
||||
static_assert(is_same<detail::RemoveScopedPtrRef<
|
||||
const scoped_refptr<RefCountInterface>&>::type,
|
||||
scoped_refptr<RefCountInterface>>::value,
|
||||
static_assert(
|
||||
is_same<
|
||||
rtc::remove_reference<const scoped_refptr<RefCountInterface>&>::type,
|
||||
const scoped_refptr<RefCountInterface>>::value,
|
||||
"const scoped_refptr& should be captured by value");
|
||||
|
||||
static_assert(is_same<detail::RemoveScopedPtrRef<const scoped_refptr<F>&>::type,
|
||||
scoped_refptr<F>>::value,
|
||||
static_assert(is_same<rtc::remove_reference<const scoped_refptr<F>&>::type,
|
||||
const scoped_refptr<F>>::value,
|
||||
"const scoped_refptr& should be captured by value");
|
||||
|
||||
static_assert(
|
||||
is_same<detail::RemoveScopedPtrRef<const int&>::type, const int&>::value,
|
||||
"const int& should be captured as const int&");
|
||||
is_same<rtc::remove_reference<const int&>::type, const int>::value,
|
||||
"const int& should be captured as const int");
|
||||
|
||||
static_assert(
|
||||
is_same<detail::RemoveScopedPtrRef<const F&>::type, const F&>::value,
|
||||
"const F& should be captured as const F&");
|
||||
static_assert(is_same<rtc::remove_reference<const F&>::type, const F>::value,
|
||||
"const F& should be captured as const F");
|
||||
|
||||
static_assert(
|
||||
is_same<detail::RemoveScopedPtrRef<F&>::type, F&>::value,
|
||||
"F& should be captured as F&");
|
||||
static_assert(is_same<rtc::remove_reference<F&>::type, F>::value,
|
||||
"F& should be captured as F");
|
||||
|
||||
#define EXPECT_IS_CAPTURED_AS_PTR(T) \
|
||||
static_assert(is_same<detail::PointerType<T>::type, T*>::value, \
|
||||
@ -129,11 +135,20 @@ TEST(BindTest, BindToMethod) {
|
||||
&object, string_value)());
|
||||
EXPECT_EQ(6, object.call_count);
|
||||
int value = 11;
|
||||
EXPECT_EQ(12, Bind(&MethodBindTester::UnaryByRef, &object, value)());
|
||||
// Bind binds by value, even if the method signature is by reference, so
|
||||
// "reference" binds require pointers.
|
||||
EXPECT_EQ(12, Bind(&MethodBindTester::UnaryByPointer, &object, &value)());
|
||||
EXPECT_EQ(12, value);
|
||||
EXPECT_EQ(7, object.call_count);
|
||||
EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)());
|
||||
// It's possible to bind to a function that takes a const reference, though
|
||||
// the capture will be a copy. See UnaryByRef hackery above where it removes
|
||||
// the const to make sure the underlying storage is, in fact, a copy.
|
||||
EXPECT_EQ(13, Bind(&MethodBindTester::UnaryByRef, &object, value)());
|
||||
// But the original value is unmodified.
|
||||
EXPECT_EQ(12, value);
|
||||
EXPECT_EQ(8, object.call_count);
|
||||
EXPECT_EQ(56, Bind(&MethodBindTester::Multiply, &object, 7, 8)());
|
||||
EXPECT_EQ(9, object.call_count);
|
||||
}
|
||||
|
||||
TEST(BindTest, BindToFunction) {
|
||||
@ -210,13 +225,14 @@ const int* Ref(const int& a) { return &a; }
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Test Bind with non-scoped_refptr<> reference argument.
|
||||
// Test Bind with non-scoped_refptr<> reference argument, which should be
|
||||
// modified to a non-reference capture.
|
||||
TEST(BindTest, RefArgument) {
|
||||
const int x = 42;
|
||||
EXPECT_TRUE(Ref(x) == &x);
|
||||
// Bind() should not make a copy of |x|, i.e. the pointers should be the same.
|
||||
EXPECT_EQ(&x, Ref(x));
|
||||
// Bind() should make a copy of |x|, i.e. the pointers should be different.
|
||||
auto functor = Bind(&Ref, x);
|
||||
EXPECT_TRUE(functor() == &x);
|
||||
EXPECT_NE(&x, functor());
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
@ -48,6 +48,19 @@ template <class T> struct is_non_const_reference<const T&> : false_type {};
|
||||
template <class T> struct is_void : false_type {};
|
||||
template <> struct is_void<void> : true_type {};
|
||||
|
||||
template <class T>
|
||||
struct remove_reference {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_reference<T&> {
|
||||
typedef T type;
|
||||
};
|
||||
template <class T>
|
||||
struct remove_reference<T&&> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Types YesType and NoType are guaranteed such that sizeof(YesType) <
|
||||
|
@ -22,8 +22,6 @@
|
||||
|
||||
namespace cricket {
|
||||
|
||||
using rtc::Bind;
|
||||
|
||||
static bool VerifyIceParams(const TransportDescription& desc) {
|
||||
// For legacy protocols.
|
||||
if (desc.ice_ufrag.empty() && desc.ice_pwd.empty())
|
||||
|
Reference in New Issue
Block a user