Delete rtc::Bind
Bug: webrtc:11339 Change-Id: Id53d17bbf37a15f482e9eb9f8762d2000c772dcc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/202250 Reviewed-by: Tommi <tommi@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Niels Moller <nisse@webrtc.org> Cr-Commit-Position: refs/heads/master@{#33099}
This commit is contained in:
4
api/DEPS
4
api/DEPS
@ -120,10 +120,6 @@ specific_include_rules = {
|
||||
"+rtc_base/async_packet_socket.h",
|
||||
],
|
||||
|
||||
"peer_connection_factory_proxy\.h": [
|
||||
"+rtc_base/bind.h",
|
||||
],
|
||||
|
||||
"peer_connection_interface\.h": [
|
||||
"+media/base/media_config.h",
|
||||
"+media/base/media_engine.h",
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "api/peer_connection_interface.h"
|
||||
#include "api/proxy.h"
|
||||
#include "rtc_base/bind.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "api/video/i010_buffer.h"
|
||||
#include "api/video/i420_buffer.h"
|
||||
#include "api/video/nv12_buffer.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
#include "test/fake_texture_frame.h"
|
||||
#include "test/frame_utils.h"
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "modules/audio_device/audio_device_buffer.h"
|
||||
#include "modules/audio_device/fine_audio_buffer.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "api/audio/audio_mixer.h"
|
||||
#include "modules/audio_mixer/default_output_rate_calculator.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
|
@ -73,8 +73,7 @@ class FakePacketTransport : public PacketTransportInternal {
|
||||
if (async_) {
|
||||
invoker_.AsyncInvokeDelayed<void>(
|
||||
RTC_FROM_HERE, Thread::Current(),
|
||||
Bind(&FakePacketTransport::SendPacketInternal, this, packet),
|
||||
async_delay_ms_);
|
||||
[this, packet] { SendPacketInternal(packet); }, async_delay_ms_);
|
||||
} else {
|
||||
SendPacketInternal(packet);
|
||||
}
|
||||
|
@ -4744,12 +4744,6 @@ void SdpOfferAnswerHandler::DestroyDataChannelTransport() {
|
||||
data_channel_controller()->set_rtp_data_channel(nullptr);
|
||||
}
|
||||
|
||||
// Note: Cannot use rtc::Bind to create a functor to invoke because it will
|
||||
// grab a reference to this PeerConnection. If this is called from the
|
||||
// PeerConnection destructor, the RefCountedObject vtable will have already
|
||||
// been destroyed (since it is a subclass of PeerConnection) and using
|
||||
// rtc::Bind will cause "Pure virtual function called" error to appear.
|
||||
|
||||
if (pc_->sctp_mid()) {
|
||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
||||
data_channel_controller()->OnTransportChannelClosed();
|
||||
|
@ -87,7 +87,6 @@ rtc_library("rtc_base_approved") {
|
||||
public_deps = [] # no-presubmit-check TODO(webrtc:8603)
|
||||
|
||||
sources = [
|
||||
"bind.h",
|
||||
"bit_buffer.cc",
|
||||
"bit_buffer.h",
|
||||
"buffer.h",
|
||||
@ -1323,7 +1322,6 @@ if (rtc_include_tests) {
|
||||
sources = [
|
||||
"atomic_ops_unittest.cc",
|
||||
"base64_unittest.cc",
|
||||
"bind_unittest.cc",
|
||||
"bit_buffer_unittest.cc",
|
||||
"bounded_inline_vector_unittest.cc",
|
||||
"buffer_queue_unittest.cc",
|
||||
|
@ -55,7 +55,7 @@ void AsyncInvoker::Flush(Thread* thread, uint32_t id /*= MQID_ANY*/) {
|
||||
// Run this on |thread| to reduce the number of context switches.
|
||||
if (Thread::Current() != thread) {
|
||||
thread->Invoke<void>(RTC_FROM_HERE,
|
||||
Bind(&AsyncInvoker::Flush, this, thread, id));
|
||||
[this, thread, id] { Flush(thread, id); });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/async_invoker_inl.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
|
@ -12,7 +12,6 @@
|
||||
#define RTC_BASE_ASYNC_INVOKER_INL_H_
|
||||
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/message_handler.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
|
282
rtc_base/bind.h
282
rtc_base/bind.h
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Bind() is an overloaded function that converts method calls into function
|
||||
// objects (aka functors). The method object is captured as a scoped_refptr<> if
|
||||
// possible, and as a raw pointer otherwise. Any arguments to the method are
|
||||
// captured by value. The return value of Bind is a stateful, nullary function
|
||||
// object. Care should be taken about the lifetime of objects captured by
|
||||
// Bind(); the returned functor knows nothing about the lifetime of a non
|
||||
// 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; }
|
||||
// int Test2() const { return 52; }
|
||||
// int Test3(int x) { return x*x; }
|
||||
// float Test4(int x, float y) { return x + y; }
|
||||
// };
|
||||
//
|
||||
// int main() {
|
||||
// Foo foo;
|
||||
// cout << rtc::Bind(&Foo::Test1, &foo)() << endl;
|
||||
// cout << rtc::Bind(&Foo::Test2, &foo)() << endl;
|
||||
// cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl;
|
||||
// cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl;
|
||||
// }
|
||||
//
|
||||
// Example usage of ref counted objects:
|
||||
// struct Bar {
|
||||
// int AddRef();
|
||||
// int Release();
|
||||
//
|
||||
// void Test() {}
|
||||
// void BindThis() {
|
||||
// // The functor passed to AsyncInvoke() will keep this object alive.
|
||||
// invoker.AsyncInvoke(RTC_FROM_HERE,rtc::Bind(&Bar::Test, this));
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// int main() {
|
||||
// rtc::scoped_refptr<Bar> bar = new rtc::RefCountedObject<Bar>();
|
||||
// auto functor = rtc::Bind(&Bar::Test, bar);
|
||||
// bar = nullptr;
|
||||
// // The functor stores an internal scoped_refptr<Bar>, so this is safe.
|
||||
// functor();
|
||||
// }
|
||||
//
|
||||
|
||||
#ifndef RTC_BASE_BIND_H_
|
||||
#define RTC_BASE_BIND_H_
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
#include "api/scoped_refptr.h"
|
||||
|
||||
#define NONAME
|
||||
|
||||
namespace rtc {
|
||||
namespace detail {
|
||||
// This is needed because the template parameters in Bind can't be resolved
|
||||
// if they're used both as parameters of the function pointer type and as
|
||||
// parameters to Bind itself: the function pointer parameters are exact
|
||||
// matches to the function prototype, but the parameters to bind have
|
||||
// references stripped. This trick allows the compiler to dictate the Bind
|
||||
// parameter types rather than deduce them.
|
||||
template <class T>
|
||||
struct identity {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
// IsRefCounted<T>::value will be true for types that can be used in
|
||||
// rtc::scoped_refptr<T>, i.e. types that implements nullary functions AddRef()
|
||||
// and Release(), regardless of their return types. AddRef() and Release() can
|
||||
// be defined in T or any superclass of T.
|
||||
template <typename T>
|
||||
class IsRefCounted {
|
||||
// This is a complex implementation detail done with SFINAE.
|
||||
|
||||
// Define types such that sizeof(Yes) != sizeof(No).
|
||||
struct Yes {
|
||||
char dummy[1];
|
||||
};
|
||||
struct No {
|
||||
char dummy[2];
|
||||
};
|
||||
// Define two overloaded template functions with return types of different
|
||||
// size. This way, we can use sizeof() on the return type to determine which
|
||||
// function the compiler would have chosen. One function will be preferred
|
||||
// over the other if it is possible to create it without compiler errors,
|
||||
// otherwise the compiler will simply remove it, and default to the less
|
||||
// preferred function.
|
||||
template <typename R>
|
||||
static Yes test(R* r, decltype(r->AddRef(), r->Release(), 42));
|
||||
template <typename C>
|
||||
static No test(...);
|
||||
|
||||
public:
|
||||
// Trick the compiler to tell if it's possible to call AddRef() and Release().
|
||||
static const bool value = sizeof(test<T>((T*)nullptr, 42)) == sizeof(Yes);
|
||||
};
|
||||
|
||||
// TernaryTypeOperator is a helper class to select a type based on a static bool
|
||||
// value.
|
||||
template <bool condition, typename IfTrueT, typename IfFalseT>
|
||||
struct TernaryTypeOperator {};
|
||||
|
||||
template <typename IfTrueT, typename IfFalseT>
|
||||
struct TernaryTypeOperator<true, IfTrueT, IfFalseT> {
|
||||
typedef IfTrueT type;
|
||||
};
|
||||
|
||||
template <typename IfTrueT, typename IfFalseT>
|
||||
struct TernaryTypeOperator<false, IfTrueT, IfFalseT> {
|
||||
typedef IfFalseT type;
|
||||
};
|
||||
|
||||
// PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T*
|
||||
// otherwise.
|
||||
template <class T>
|
||||
struct PointerType {
|
||||
typedef typename TernaryTypeOperator<IsRefCounted<T>::value,
|
||||
scoped_refptr<T>,
|
||||
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:
|
||||
MethodFunctor(MethodT method, ObjectT* object, Args... args)
|
||||
: method_(method), object_(object), args_(args...) {}
|
||||
R operator()() const {
|
||||
return CallMethod(std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
private:
|
||||
template <size_t... S>
|
||||
R CallMethod(std::index_sequence<S...>) const {
|
||||
return (object_->*method_)(std::get<S>(args_)...);
|
||||
}
|
||||
|
||||
MethodT method_;
|
||||
typename detail::PointerType<ObjectT>::type object_;
|
||||
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(std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
private:
|
||||
template <size_t... S>
|
||||
R CallMethod(std::index_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:
|
||||
Functor(const FunctorT& functor, Args... args)
|
||||
: functor_(functor), args_(args...) {}
|
||||
R operator()() const {
|
||||
return CallFunction(std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
private:
|
||||
template <size_t... S>
|
||||
R CallFunction(std::index_sequence<S...>) const {
|
||||
return functor_(std::get<S>(args_)...);
|
||||
}
|
||||
|
||||
FunctorT functor_;
|
||||
typename std::tuple<typename std::remove_reference<Args>::type...> args_;
|
||||
};
|
||||
|
||||
#define FP_T(x) R (ObjectT::*x)(Args...)
|
||||
|
||||
template <class ObjectT, class R, typename... Args>
|
||||
MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
|
||||
FP_T(method),
|
||||
ObjectT* object,
|
||||
typename detail::identity<Args>::type... args) {
|
||||
return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object,
|
||||
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
|
||||
|
||||
template <class ObjectT, class R, typename... Args>
|
||||
MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind(
|
||||
FP_T(method),
|
||||
const ObjectT* object,
|
||||
typename detail::identity<Args>::type... args) {
|
||||
return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object,
|
||||
args...);
|
||||
}
|
||||
template <class ObjectT, class R, typename... Args>
|
||||
UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind(
|
||||
FP_T(method),
|
||||
detail::UnretainedWrapper<const ObjectT> object,
|
||||
typename detail::identity<Args>::type... args) {
|
||||
return UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(
|
||||
method, object, args...);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
#define FP_T(x) R (*x)(Args...)
|
||||
|
||||
template <class R, typename... Args>
|
||||
Functor<FP_T(NONAME), R, Args...> Bind(
|
||||
FP_T(function),
|
||||
typename detail::identity<Args>::type... args) {
|
||||
return Functor<FP_T(NONAME), R, Args...>(function, args...);
|
||||
}
|
||||
|
||||
#undef FP_T
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#undef NONAME
|
||||
|
||||
#endif // RTC_BASE_BIND_H_
|
@ -1,248 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "rtc_base/bind.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/ref_count.h"
|
||||
#include "rtc_base/ref_counted_object.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace {
|
||||
|
||||
struct LifeTimeCheck;
|
||||
|
||||
struct MethodBindTester {
|
||||
void NullaryVoid() { ++call_count; }
|
||||
int NullaryInt() {
|
||||
++call_count;
|
||||
return 1;
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
|
||||
mutable int call_count;
|
||||
};
|
||||
|
||||
struct A {
|
||||
int dummy;
|
||||
};
|
||||
struct B : public RefCountInterface {
|
||||
int dummy;
|
||||
};
|
||||
struct C : public A, B {};
|
||||
struct D {
|
||||
int AddRef();
|
||||
};
|
||||
struct E : public D {
|
||||
int Release();
|
||||
};
|
||||
struct F {
|
||||
void AddRef();
|
||||
void Release();
|
||||
};
|
||||
|
||||
struct LifeTimeCheck {
|
||||
LifeTimeCheck() : ref_count_(0) {}
|
||||
void AddRef() { ++ref_count_; }
|
||||
void Release() { --ref_count_; }
|
||||
void NullaryVoid() {}
|
||||
int ref_count_;
|
||||
};
|
||||
|
||||
int Return42() {
|
||||
return 42;
|
||||
}
|
||||
int Negate(int a) {
|
||||
return -a;
|
||||
}
|
||||
int Multiply(int a, int b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Try to catch any problem with scoped_refptr type deduction in rtc::Bind at
|
||||
// compile time.
|
||||
#define EXPECT_IS_CAPTURED_AS_PTR(T) \
|
||||
static_assert(std::is_same<detail::PointerType<T>::type, T*>::value, \
|
||||
"PointerType")
|
||||
#define EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(T) \
|
||||
static_assert( \
|
||||
std::is_same<detail::PointerType<T>::type, scoped_refptr<T>>::value, \
|
||||
"PointerType")
|
||||
|
||||
EXPECT_IS_CAPTURED_AS_PTR(void);
|
||||
EXPECT_IS_CAPTURED_AS_PTR(int);
|
||||
EXPECT_IS_CAPTURED_AS_PTR(double);
|
||||
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);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(C);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(E);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(F);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<RefCountInterface>);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<B>);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(RefCountedObject<C>);
|
||||
EXPECT_IS_CAPTURED_AS_SCOPED_REFPTR(const RefCountedObject<RefCountInterface>);
|
||||
|
||||
TEST(BindTest, BindToMethod) {
|
||||
MethodBindTester object = {0};
|
||||
EXPECT_EQ(0, object.call_count);
|
||||
Bind(&MethodBindTester::NullaryVoid, &object)();
|
||||
EXPECT_EQ(1, object.call_count);
|
||||
EXPECT_EQ(1, Bind(&MethodBindTester::NullaryInt, &object)());
|
||||
EXPECT_EQ(2, object.call_count);
|
||||
EXPECT_EQ(2, Bind(&MethodBindTester::NullaryConst,
|
||||
static_cast<const MethodBindTester*>(&object))());
|
||||
EXPECT_EQ(3, object.call_count);
|
||||
Bind(&MethodBindTester::UnaryVoid, &object, 5)();
|
||||
EXPECT_EQ(4, object.call_count);
|
||||
EXPECT_EQ(100, Bind(&MethodBindTester::Identity<int>, &object, 100)());
|
||||
EXPECT_EQ(5, object.call_count);
|
||||
const std::string string_value("test string");
|
||||
EXPECT_EQ(string_value, Bind(&MethodBindTester::Identity<std::string>,
|
||||
&object, string_value)());
|
||||
EXPECT_EQ(6, object.call_count);
|
||||
int value = 11;
|
||||
// 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);
|
||||
// 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) {
|
||||
EXPECT_EQ(42, Bind(&Return42)());
|
||||
EXPECT_EQ(3, Bind(&Negate, -3)());
|
||||
EXPECT_EQ(56, Bind(&Multiply, 8, 7)());
|
||||
}
|
||||
|
||||
// Test Bind where method object implements RefCountInterface and is passed as a
|
||||
// pointer.
|
||||
TEST(BindTest, CapturePointerAsScopedRefPtr) {
|
||||
LifeTimeCheck object;
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
scoped_refptr<LifeTimeCheck> scoped_object(&object);
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
{
|
||||
auto functor = Bind(&LifeTimeCheck::NullaryVoid, &object);
|
||||
EXPECT_EQ(object.ref_count_, 2);
|
||||
scoped_object = nullptr;
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
}
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
}
|
||||
|
||||
// Test Bind where method object implements RefCountInterface and is passed as a
|
||||
// scoped_refptr<>.
|
||||
TEST(BindTest, CaptureScopedRefPtrAsScopedRefPtr) {
|
||||
LifeTimeCheck object;
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
scoped_refptr<LifeTimeCheck> scoped_object(&object);
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
{
|
||||
auto functor = Bind(&LifeTimeCheck::NullaryVoid, scoped_object);
|
||||
EXPECT_EQ(object.ref_count_, 2);
|
||||
scoped_object = nullptr;
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
}
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
}
|
||||
|
||||
// Test Bind where method object is captured as scoped_refptr<> and the functor
|
||||
// dies while there are references left.
|
||||
TEST(BindTest, FunctorReleasesObjectOnDestruction) {
|
||||
LifeTimeCheck object;
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
scoped_refptr<LifeTimeCheck> scoped_object(&object);
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
Bind(&LifeTimeCheck::NullaryVoid, &object)();
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
scoped_object = nullptr;
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
}
|
||||
|
||||
// Test Bind with scoped_refptr<> argument.
|
||||
TEST(BindTest, ScopedRefPointerArgument) {
|
||||
LifeTimeCheck object;
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
scoped_refptr<LifeTimeCheck> scoped_object(&object);
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
{
|
||||
MethodBindTester bind_tester;
|
||||
auto functor =
|
||||
Bind(&MethodBindTester::RefArgument, &bind_tester, scoped_object);
|
||||
EXPECT_EQ(object.ref_count_, 2);
|
||||
}
|
||||
EXPECT_EQ(object.ref_count_, 1);
|
||||
scoped_object = nullptr;
|
||||
EXPECT_EQ(object.ref_count_, 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const int* Ref(const int& a) {
|
||||
return &a;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// 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_EQ(&x, Ref(x));
|
||||
// Bind() should make a copy of |x|, i.e. the pointers should be different.
|
||||
auto functor = Bind(&Ref, x);
|
||||
EXPECT_NE(&x, functor());
|
||||
}
|
||||
|
||||
} // namespace rtc
|
@ -11,7 +11,6 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "api/function_view.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/callback_list.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
@ -209,8 +208,6 @@ TEST(CallbackList, MemberFunctionTest) {
|
||||
}
|
||||
|
||||
// todo(glahiru): Add a test case to catch some error for Karl's first fix
|
||||
// todo(glahiru): Add a test for rtc::Bind
|
||||
// which used the following code in the Send
|
||||
|
||||
TEST(CallbackList, RemoveOneReceiver) {
|
||||
int removal_tag[2];
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
#include "rtc_base/callback.h"
|
||||
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/keep_ref_until_done.h"
|
||||
#include "rtc_base/ref_count.h"
|
||||
#include "test/gtest.h"
|
||||
@ -30,11 +29,6 @@ void i(int& x) {
|
||||
x *= x;
|
||||
} // NOLINT: Testing refs
|
||||
|
||||
struct BindTester {
|
||||
int a() { return 24; }
|
||||
int b(int x) const { return x * x; }
|
||||
};
|
||||
|
||||
class RefCountedBindTester : public RefCountInterface {
|
||||
public:
|
||||
RefCountedBindTester() : count_(0) {}
|
||||
@ -89,19 +83,6 @@ TEST(CallbackTest, OneParam) {
|
||||
EXPECT_EQ(81, x);
|
||||
}
|
||||
|
||||
TEST(CallbackTest, WithBind) {
|
||||
BindTester t;
|
||||
Callback0<int> cb1 = Bind(&BindTester::a, &t);
|
||||
EXPECT_EQ(24, cb1());
|
||||
EXPECT_EQ(24, cb1());
|
||||
cb1 = Bind(&BindTester::b, &t, 10);
|
||||
EXPECT_EQ(100, cb1());
|
||||
EXPECT_EQ(100, cb1());
|
||||
cb1 = Bind(&BindTester::b, &t, 5);
|
||||
EXPECT_EQ(25, cb1());
|
||||
EXPECT_EQ(25, cb1());
|
||||
}
|
||||
|
||||
TEST(KeepRefUntilDoneTest, simple) {
|
||||
RefCountedBindTester t;
|
||||
EXPECT_EQ(0, t.RefCount());
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
#include "rtc_base/thread.h"
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
#include "rtc_base/time_utils.h"
|
||||
@ -67,7 +66,7 @@ TEST(TaskQueueTest, DISABLED_PostDelayedHighRes) {
|
||||
webrtc::TaskQueueForTest queue(kQueueName, TaskQueue::Priority::HIGH);
|
||||
|
||||
uint32_t start = Time();
|
||||
queue.PostDelayedTask(Bind(&CheckCurrent, &event, &queue), 3);
|
||||
queue.PostDelayedTask([&event, &queue] { CheckCurrent(&event, &queue); }, 3);
|
||||
EXPECT_TRUE(event.Wait(1000));
|
||||
uint32_t end = TimeMillis();
|
||||
// These tests are a little relaxed due to how "powerful" our test bots can
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
namespace webrtc_new_closure_impl {
|
||||
// Simple implementation of QueuedTask for use with rtc::Bind and lambdas.
|
||||
// Simple implementation of QueuedTask for use with lambdas.
|
||||
template <typename Closure>
|
||||
class ClosureTask : public QueuedTask {
|
||||
public:
|
||||
|
@ -433,7 +433,7 @@ TEST(ThreadTest, ThreeThreadsInvoke) {
|
||||
struct LocalFuncs {
|
||||
static void Set(LockedBool* out) { out->Set(true); }
|
||||
static void InvokeSet(Thread* thread, LockedBool* out) {
|
||||
thread->Invoke<void>(RTC_FROM_HERE, Bind(&Set, out));
|
||||
thread->Invoke<void>(RTC_FROM_HERE, [out] { Set(out); });
|
||||
}
|
||||
|
||||
// Set |out| true and call InvokeSet on |thread|.
|
||||
@ -453,8 +453,9 @@ TEST(ThreadTest, ThreeThreadsInvoke) {
|
||||
LockedBool async_invoked(false);
|
||||
|
||||
invoker->AsyncInvoke<void>(
|
||||
RTC_FROM_HERE, thread1,
|
||||
Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
|
||||
RTC_FROM_HERE, thread1, [&async_invoked, thread2, out] {
|
||||
SetAndInvokeSet(&async_invoked, thread2, out);
|
||||
});
|
||||
|
||||
EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
|
||||
}
|
||||
@ -466,9 +467,12 @@ TEST(ThreadTest, ThreeThreadsInvoke) {
|
||||
// Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A.
|
||||
// Thread B returns when C receives the call and C should be blocked until A
|
||||
// starts to process messages.
|
||||
thread_b->Invoke<void>(RTC_FROM_HERE,
|
||||
Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker,
|
||||
thread_c.get(), thread_a, &thread_a_called));
|
||||
Thread* thread_c_ptr = thread_c.get();
|
||||
thread_b->Invoke<void>(
|
||||
RTC_FROM_HERE, [&invoker, thread_c_ptr, thread_a, &thread_a_called] {
|
||||
LocalFuncs::AsyncInvokeSetAndWait(&invoker, thread_c_ptr, thread_a,
|
||||
&thread_a_called);
|
||||
});
|
||||
EXPECT_FALSE(thread_a_called.Get());
|
||||
|
||||
EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
|
||||
@ -519,8 +523,8 @@ class ThreadQueueTest : public ::testing::Test, public Thread {
|
||||
// succeed, since our critical sections are reentrant.
|
||||
std::unique_ptr<Thread> worker(Thread::CreateWithSocketServer());
|
||||
worker->Start();
|
||||
return worker->Invoke<bool>(
|
||||
RTC_FROM_HERE, rtc::Bind(&ThreadQueueTest::IsLocked_Worker, this));
|
||||
return worker->Invoke<bool>(RTC_FROM_HERE,
|
||||
[this] { return IsLocked_Worker(); });
|
||||
}
|
||||
};
|
||||
|
||||
@ -840,11 +844,6 @@ TEST_F(AsyncInvokeTest, FlushWithIds) {
|
||||
EXPECT_TRUE(flag2.get());
|
||||
}
|
||||
|
||||
void ThreadIsCurrent(Thread* thread, bool* result, Event* event) {
|
||||
*result = thread->IsCurrent();
|
||||
event->Set();
|
||||
}
|
||||
|
||||
void WaitAndSetEvent(Event* wait_event, Event* set_event) {
|
||||
wait_event->Wait(Event::kForever);
|
||||
set_event->Set();
|
||||
@ -909,15 +908,6 @@ class DestructionFunctor {
|
||||
bool was_invoked_ = false;
|
||||
};
|
||||
|
||||
TEST(ThreadPostTaskTest, InvokesWithBind) {
|
||||
std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
|
||||
background_thread->Start();
|
||||
|
||||
Event event;
|
||||
background_thread->PostTask(RTC_FROM_HERE, Bind(&Event::Set, &event));
|
||||
event.Wait(Event::kForever);
|
||||
}
|
||||
|
||||
TEST(ThreadPostTaskTest, InvokesWithLambda) {
|
||||
std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
|
||||
background_thread->Start();
|
||||
@ -1020,9 +1010,13 @@ TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
|
||||
|
||||
Event event;
|
||||
bool was_invoked_on_background_thread = false;
|
||||
background_thread->PostTask(RTC_FROM_HERE,
|
||||
Bind(&ThreadIsCurrent, background_thread.get(),
|
||||
&was_invoked_on_background_thread, &event));
|
||||
Thread* background_thread_ptr = background_thread.get();
|
||||
background_thread->PostTask(
|
||||
RTC_FROM_HERE,
|
||||
[background_thread_ptr, &was_invoked_on_background_thread, &event] {
|
||||
was_invoked_on_background_thread = background_thread_ptr->IsCurrent();
|
||||
event.Set();
|
||||
});
|
||||
event.Wait(Event::kForever);
|
||||
|
||||
EXPECT_TRUE(was_invoked_on_background_thread);
|
||||
@ -1036,9 +1030,10 @@ TEST(ThreadPostTaskTest, InvokesAsynchronously) {
|
||||
// thread. The second event ensures that the message is processed.
|
||||
Event event_set_by_test_thread;
|
||||
Event event_set_by_background_thread;
|
||||
background_thread->PostTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &event_set_by_test_thread,
|
||||
&event_set_by_background_thread));
|
||||
background_thread->PostTask(RTC_FROM_HERE, [&event_set_by_test_thread,
|
||||
&event_set_by_background_thread] {
|
||||
WaitAndSetEvent(&event_set_by_test_thread, &event_set_by_background_thread);
|
||||
});
|
||||
event_set_by_test_thread.Set();
|
||||
event_set_by_background_thread.Wait(Event::kForever);
|
||||
}
|
||||
@ -1052,12 +1047,12 @@ TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
|
||||
Event third;
|
||||
Event fourth;
|
||||
|
||||
background_thread->PostTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &first, &second));
|
||||
background_thread->PostTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &second, &third));
|
||||
background_thread->PostTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &third, &fourth));
|
||||
background_thread->PostTask(
|
||||
RTC_FROM_HERE, [&first, &second] { WaitAndSetEvent(&first, &second); });
|
||||
background_thread->PostTask(
|
||||
RTC_FROM_HERE, [&second, &third] { WaitAndSetEvent(&second, &third); });
|
||||
background_thread->PostTask(
|
||||
RTC_FROM_HERE, [&third, &fourth] { WaitAndSetEvent(&third, &fourth); });
|
||||
|
||||
// All tasks have been posted before the first one is unblocked.
|
||||
first.Set();
|
||||
@ -1075,8 +1070,10 @@ TEST(ThreadPostDelayedTaskTest, InvokesAsynchronously) {
|
||||
Event event_set_by_background_thread;
|
||||
background_thread->PostDelayedTask(
|
||||
RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &event_set_by_test_thread,
|
||||
&event_set_by_background_thread),
|
||||
[&event_set_by_test_thread, &event_set_by_background_thread] {
|
||||
WaitAndSetEvent(&event_set_by_test_thread,
|
||||
&event_set_by_background_thread);
|
||||
},
|
||||
/*milliseconds=*/10);
|
||||
event_set_by_test_thread.Set();
|
||||
event_set_by_background_thread.Wait(Event::kForever);
|
||||
@ -1092,14 +1089,14 @@ TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
|
||||
Event third;
|
||||
Event fourth;
|
||||
|
||||
background_thread->PostDelayedTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &third, &fourth),
|
||||
background_thread->PostDelayedTask(
|
||||
RTC_FROM_HERE, [&third, &fourth] { WaitAndSetEvent(&third, &fourth); },
|
||||
/*milliseconds=*/11);
|
||||
background_thread->PostDelayedTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &first, &second),
|
||||
background_thread->PostDelayedTask(
|
||||
RTC_FROM_HERE, [&first, &second] { WaitAndSetEvent(&first, &second); },
|
||||
/*milliseconds=*/9);
|
||||
background_thread->PostDelayedTask(RTC_FROM_HERE,
|
||||
Bind(&WaitAndSetEvent, &second, &third),
|
||||
background_thread->PostDelayedTask(
|
||||
RTC_FROM_HERE, [&second, &third] { WaitAndSetEvent(&second, &third); },
|
||||
/*milliseconds=*/10);
|
||||
|
||||
// All tasks have been posted before the first one is unblocked.
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
#include "api/scoped_refptr.h"
|
||||
#include "common_video/include/video_frame_buffer.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/keep_ref_until_done.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "helpers.h"
|
||||
#include "modules/audio_device/fine_audio_buffer.h"
|
||||
#include "rtc_base/atomic_ops.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/thread.h"
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/numerics/samples_stats_counter.h"
|
||||
#include "api/units/data_size.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
Reference in New Issue
Block a user