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",
|
"+rtc_base/async_packet_socket.h",
|
||||||
],
|
],
|
||||||
|
|
||||||
"peer_connection_factory_proxy\.h": [
|
|
||||||
"+rtc_base/bind.h",
|
|
||||||
],
|
|
||||||
|
|
||||||
"peer_connection_interface\.h": [
|
"peer_connection_interface\.h": [
|
||||||
"+media/base/media_config.h",
|
"+media/base/media_config.h",
|
||||||
"+media/base/media_engine.h",
|
"+media/base/media_engine.h",
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include "api/peer_connection_interface.h"
|
#include "api/peer_connection_interface.h"
|
||||||
#include "api/proxy.h"
|
#include "api/proxy.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include "api/video/i010_buffer.h"
|
#include "api/video/i010_buffer.h"
|
||||||
#include "api/video/i420_buffer.h"
|
#include "api/video/i420_buffer.h"
|
||||||
#include "api/video/nv12_buffer.h"
|
#include "api/video/nv12_buffer.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
#include "test/fake_texture_frame.h"
|
#include "test/fake_texture_frame.h"
|
||||||
#include "test/frame_utils.h"
|
#include "test/frame_utils.h"
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "modules/audio_device/audio_device_buffer.h"
|
#include "modules/audio_device/audio_device_buffer.h"
|
||||||
#include "modules/audio_device/fine_audio_buffer.h"
|
#include "modules/audio_device/fine_audio_buffer.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "api/audio/audio_mixer.h"
|
#include "api/audio/audio_mixer.h"
|
||||||
#include "modules/audio_mixer/default_output_rate_calculator.h"
|
#include "modules/audio_mixer/default_output_rate_calculator.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/strings/string_builder.h"
|
#include "rtc_base/strings/string_builder.h"
|
||||||
#include "rtc_base/task_queue_for_test.h"
|
#include "rtc_base/task_queue_for_test.h"
|
||||||
|
@ -73,8 +73,7 @@ class FakePacketTransport : public PacketTransportInternal {
|
|||||||
if (async_) {
|
if (async_) {
|
||||||
invoker_.AsyncInvokeDelayed<void>(
|
invoker_.AsyncInvokeDelayed<void>(
|
||||||
RTC_FROM_HERE, Thread::Current(),
|
RTC_FROM_HERE, Thread::Current(),
|
||||||
Bind(&FakePacketTransport::SendPacketInternal, this, packet),
|
[this, packet] { SendPacketInternal(packet); }, async_delay_ms_);
|
||||||
async_delay_ms_);
|
|
||||||
} else {
|
} else {
|
||||||
SendPacketInternal(packet);
|
SendPacketInternal(packet);
|
||||||
}
|
}
|
||||||
|
@ -4744,12 +4744,6 @@ void SdpOfferAnswerHandler::DestroyDataChannelTransport() {
|
|||||||
data_channel_controller()->set_rtp_data_channel(nullptr);
|
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()) {
|
if (pc_->sctp_mid()) {
|
||||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
||||||
data_channel_controller()->OnTransportChannelClosed();
|
data_channel_controller()->OnTransportChannelClosed();
|
||||||
|
@ -87,7 +87,6 @@ rtc_library("rtc_base_approved") {
|
|||||||
public_deps = [] # no-presubmit-check TODO(webrtc:8603)
|
public_deps = [] # no-presubmit-check TODO(webrtc:8603)
|
||||||
|
|
||||||
sources = [
|
sources = [
|
||||||
"bind.h",
|
|
||||||
"bit_buffer.cc",
|
"bit_buffer.cc",
|
||||||
"bit_buffer.h",
|
"bit_buffer.h",
|
||||||
"buffer.h",
|
"buffer.h",
|
||||||
@ -1323,7 +1322,6 @@ if (rtc_include_tests) {
|
|||||||
sources = [
|
sources = [
|
||||||
"atomic_ops_unittest.cc",
|
"atomic_ops_unittest.cc",
|
||||||
"base64_unittest.cc",
|
"base64_unittest.cc",
|
||||||
"bind_unittest.cc",
|
|
||||||
"bit_buffer_unittest.cc",
|
"bit_buffer_unittest.cc",
|
||||||
"bounded_inline_vector_unittest.cc",
|
"bounded_inline_vector_unittest.cc",
|
||||||
"buffer_queue_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.
|
// Run this on |thread| to reduce the number of context switches.
|
||||||
if (Thread::Current() != thread) {
|
if (Thread::Current() != thread) {
|
||||||
thread->Invoke<void>(RTC_FROM_HERE,
|
thread->Invoke<void>(RTC_FROM_HERE,
|
||||||
Bind(&AsyncInvoker::Flush, this, thread, id));
|
[this, thread, id] { Flush(thread, id); });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "rtc_base/async_invoker_inl.h"
|
#include "rtc_base/async_invoker_inl.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/constructor_magic.h"
|
#include "rtc_base/constructor_magic.h"
|
||||||
#include "rtc_base/event.h"
|
#include "rtc_base/event.h"
|
||||||
#include "rtc_base/ref_counted_object.h"
|
#include "rtc_base/ref_counted_object.h"
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#define RTC_BASE_ASYNC_INVOKER_INL_H_
|
#define RTC_BASE_ASYNC_INVOKER_INL_H_
|
||||||
|
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/event.h"
|
#include "rtc_base/event.h"
|
||||||
#include "rtc_base/message_handler.h"
|
#include "rtc_base/message_handler.h"
|
||||||
#include "rtc_base/ref_counted_object.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 <type_traits>
|
||||||
|
|
||||||
#include "api/function_view.h"
|
#include "api/function_view.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/callback_list.h"
|
#include "rtc_base/callback_list.h"
|
||||||
#include "test/gtest.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 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) {
|
TEST(CallbackList, RemoveOneReceiver) {
|
||||||
int removal_tag[2];
|
int removal_tag[2];
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include "rtc_base/callback.h"
|
#include "rtc_base/callback.h"
|
||||||
|
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/keep_ref_until_done.h"
|
#include "rtc_base/keep_ref_until_done.h"
|
||||||
#include "rtc_base/ref_count.h"
|
#include "rtc_base/ref_count.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
@ -30,11 +29,6 @@ void i(int& x) {
|
|||||||
x *= x;
|
x *= x;
|
||||||
} // NOLINT: Testing refs
|
} // NOLINT: Testing refs
|
||||||
|
|
||||||
struct BindTester {
|
|
||||||
int a() { return 24; }
|
|
||||||
int b(int x) const { return x * x; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class RefCountedBindTester : public RefCountInterface {
|
class RefCountedBindTester : public RefCountInterface {
|
||||||
public:
|
public:
|
||||||
RefCountedBindTester() : count_(0) {}
|
RefCountedBindTester() : count_(0) {}
|
||||||
@ -89,19 +83,6 @@ TEST(CallbackTest, OneParam) {
|
|||||||
EXPECT_EQ(81, x);
|
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) {
|
TEST(KeepRefUntilDoneTest, simple) {
|
||||||
RefCountedBindTester t;
|
RefCountedBindTester t;
|
||||||
EXPECT_EQ(0, t.RefCount());
|
EXPECT_EQ(0, t.RefCount());
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/event.h"
|
#include "rtc_base/event.h"
|
||||||
#include "rtc_base/gunit.h"
|
#include "rtc_base/gunit.h"
|
||||||
#include "rtc_base/thread.h"
|
#include "rtc_base/thread.h"
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/memory/memory.h"
|
#include "absl/memory/memory.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/event.h"
|
#include "rtc_base/event.h"
|
||||||
#include "rtc_base/task_queue_for_test.h"
|
#include "rtc_base/task_queue_for_test.h"
|
||||||
#include "rtc_base/time_utils.h"
|
#include "rtc_base/time_utils.h"
|
||||||
@ -67,7 +66,7 @@ TEST(TaskQueueTest, DISABLED_PostDelayedHighRes) {
|
|||||||
webrtc::TaskQueueForTest queue(kQueueName, TaskQueue::Priority::HIGH);
|
webrtc::TaskQueueForTest queue(kQueueName, TaskQueue::Priority::HIGH);
|
||||||
|
|
||||||
uint32_t start = Time();
|
uint32_t start = Time();
|
||||||
queue.PostDelayedTask(Bind(&CheckCurrent, &event, &queue), 3);
|
queue.PostDelayedTask([&event, &queue] { CheckCurrent(&event, &queue); }, 3);
|
||||||
EXPECT_TRUE(event.Wait(1000));
|
EXPECT_TRUE(event.Wait(1000));
|
||||||
uint32_t end = TimeMillis();
|
uint32_t end = TimeMillis();
|
||||||
// These tests are a little relaxed due to how "powerful" our test bots can
|
// These tests are a little relaxed due to how "powerful" our test bots can
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace webrtc_new_closure_impl {
|
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>
|
template <typename Closure>
|
||||||
class ClosureTask : public QueuedTask {
|
class ClosureTask : public QueuedTask {
|
||||||
public:
|
public:
|
||||||
|
@ -433,7 +433,7 @@ TEST(ThreadTest, ThreeThreadsInvoke) {
|
|||||||
struct LocalFuncs {
|
struct LocalFuncs {
|
||||||
static void Set(LockedBool* out) { out->Set(true); }
|
static void Set(LockedBool* out) { out->Set(true); }
|
||||||
static void InvokeSet(Thread* thread, LockedBool* out) {
|
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|.
|
// Set |out| true and call InvokeSet on |thread|.
|
||||||
@ -453,8 +453,9 @@ TEST(ThreadTest, ThreeThreadsInvoke) {
|
|||||||
LockedBool async_invoked(false);
|
LockedBool async_invoked(false);
|
||||||
|
|
||||||
invoker->AsyncInvoke<void>(
|
invoker->AsyncInvoke<void>(
|
||||||
RTC_FROM_HERE, thread1,
|
RTC_FROM_HERE, thread1, [&async_invoked, thread2, out] {
|
||||||
Bind(&SetAndInvokeSet, &async_invoked, thread2, out));
|
SetAndInvokeSet(&async_invoked, thread2, out);
|
||||||
|
});
|
||||||
|
|
||||||
EXPECT_TRUE_WAIT(async_invoked.Get(), 2000);
|
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.
|
// 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
|
// Thread B returns when C receives the call and C should be blocked until A
|
||||||
// starts to process messages.
|
// starts to process messages.
|
||||||
thread_b->Invoke<void>(RTC_FROM_HERE,
|
Thread* thread_c_ptr = thread_c.get();
|
||||||
Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker,
|
thread_b->Invoke<void>(
|
||||||
thread_c.get(), thread_a, &thread_a_called));
|
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_FALSE(thread_a_called.Get());
|
||||||
|
|
||||||
EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000);
|
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.
|
// succeed, since our critical sections are reentrant.
|
||||||
std::unique_ptr<Thread> worker(Thread::CreateWithSocketServer());
|
std::unique_ptr<Thread> worker(Thread::CreateWithSocketServer());
|
||||||
worker->Start();
|
worker->Start();
|
||||||
return worker->Invoke<bool>(
|
return worker->Invoke<bool>(RTC_FROM_HERE,
|
||||||
RTC_FROM_HERE, rtc::Bind(&ThreadQueueTest::IsLocked_Worker, this));
|
[this] { return IsLocked_Worker(); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -840,11 +844,6 @@ TEST_F(AsyncInvokeTest, FlushWithIds) {
|
|||||||
EXPECT_TRUE(flag2.get());
|
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) {
|
void WaitAndSetEvent(Event* wait_event, Event* set_event) {
|
||||||
wait_event->Wait(Event::kForever);
|
wait_event->Wait(Event::kForever);
|
||||||
set_event->Set();
|
set_event->Set();
|
||||||
@ -909,15 +908,6 @@ class DestructionFunctor {
|
|||||||
bool was_invoked_ = false;
|
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) {
|
TEST(ThreadPostTaskTest, InvokesWithLambda) {
|
||||||
std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
|
std::unique_ptr<rtc::Thread> background_thread(rtc::Thread::Create());
|
||||||
background_thread->Start();
|
background_thread->Start();
|
||||||
@ -1020,9 +1010,13 @@ TEST(ThreadPostTaskTest, InvokesOnBackgroundThread) {
|
|||||||
|
|
||||||
Event event;
|
Event event;
|
||||||
bool was_invoked_on_background_thread = false;
|
bool was_invoked_on_background_thread = false;
|
||||||
background_thread->PostTask(RTC_FROM_HERE,
|
Thread* background_thread_ptr = background_thread.get();
|
||||||
Bind(&ThreadIsCurrent, background_thread.get(),
|
background_thread->PostTask(
|
||||||
&was_invoked_on_background_thread, &event));
|
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);
|
event.Wait(Event::kForever);
|
||||||
|
|
||||||
EXPECT_TRUE(was_invoked_on_background_thread);
|
EXPECT_TRUE(was_invoked_on_background_thread);
|
||||||
@ -1036,9 +1030,10 @@ TEST(ThreadPostTaskTest, InvokesAsynchronously) {
|
|||||||
// thread. The second event ensures that the message is processed.
|
// thread. The second event ensures that the message is processed.
|
||||||
Event event_set_by_test_thread;
|
Event event_set_by_test_thread;
|
||||||
Event event_set_by_background_thread;
|
Event event_set_by_background_thread;
|
||||||
background_thread->PostTask(RTC_FROM_HERE,
|
background_thread->PostTask(RTC_FROM_HERE, [&event_set_by_test_thread,
|
||||||
Bind(&WaitAndSetEvent, &event_set_by_test_thread,
|
&event_set_by_background_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_test_thread.Set();
|
||||||
event_set_by_background_thread.Wait(Event::kForever);
|
event_set_by_background_thread.Wait(Event::kForever);
|
||||||
}
|
}
|
||||||
@ -1052,12 +1047,12 @@ TEST(ThreadPostTaskTest, InvokesInPostedOrder) {
|
|||||||
Event third;
|
Event third;
|
||||||
Event fourth;
|
Event fourth;
|
||||||
|
|
||||||
background_thread->PostTask(RTC_FROM_HERE,
|
background_thread->PostTask(
|
||||||
Bind(&WaitAndSetEvent, &first, &second));
|
RTC_FROM_HERE, [&first, &second] { WaitAndSetEvent(&first, &second); });
|
||||||
background_thread->PostTask(RTC_FROM_HERE,
|
background_thread->PostTask(
|
||||||
Bind(&WaitAndSetEvent, &second, &third));
|
RTC_FROM_HERE, [&second, &third] { WaitAndSetEvent(&second, &third); });
|
||||||
background_thread->PostTask(RTC_FROM_HERE,
|
background_thread->PostTask(
|
||||||
Bind(&WaitAndSetEvent, &third, &fourth));
|
RTC_FROM_HERE, [&third, &fourth] { WaitAndSetEvent(&third, &fourth); });
|
||||||
|
|
||||||
// All tasks have been posted before the first one is unblocked.
|
// All tasks have been posted before the first one is unblocked.
|
||||||
first.Set();
|
first.Set();
|
||||||
@ -1075,8 +1070,10 @@ TEST(ThreadPostDelayedTaskTest, InvokesAsynchronously) {
|
|||||||
Event event_set_by_background_thread;
|
Event event_set_by_background_thread;
|
||||||
background_thread->PostDelayedTask(
|
background_thread->PostDelayedTask(
|
||||||
RTC_FROM_HERE,
|
RTC_FROM_HERE,
|
||||||
Bind(&WaitAndSetEvent, &event_set_by_test_thread,
|
[&event_set_by_test_thread, &event_set_by_background_thread] {
|
||||||
&event_set_by_background_thread),
|
WaitAndSetEvent(&event_set_by_test_thread,
|
||||||
|
&event_set_by_background_thread);
|
||||||
|
},
|
||||||
/*milliseconds=*/10);
|
/*milliseconds=*/10);
|
||||||
event_set_by_test_thread.Set();
|
event_set_by_test_thread.Set();
|
||||||
event_set_by_background_thread.Wait(Event::kForever);
|
event_set_by_background_thread.Wait(Event::kForever);
|
||||||
@ -1092,14 +1089,14 @@ TEST(ThreadPostDelayedTaskTest, InvokesInDelayOrder) {
|
|||||||
Event third;
|
Event third;
|
||||||
Event fourth;
|
Event fourth;
|
||||||
|
|
||||||
background_thread->PostDelayedTask(RTC_FROM_HERE,
|
background_thread->PostDelayedTask(
|
||||||
Bind(&WaitAndSetEvent, &third, &fourth),
|
RTC_FROM_HERE, [&third, &fourth] { WaitAndSetEvent(&third, &fourth); },
|
||||||
/*milliseconds=*/11);
|
/*milliseconds=*/11);
|
||||||
background_thread->PostDelayedTask(RTC_FROM_HERE,
|
background_thread->PostDelayedTask(
|
||||||
Bind(&WaitAndSetEvent, &first, &second),
|
RTC_FROM_HERE, [&first, &second] { WaitAndSetEvent(&first, &second); },
|
||||||
/*milliseconds=*/9);
|
/*milliseconds=*/9);
|
||||||
background_thread->PostDelayedTask(RTC_FROM_HERE,
|
background_thread->PostDelayedTask(
|
||||||
Bind(&WaitAndSetEvent, &second, &third),
|
RTC_FROM_HERE, [&second, &third] { WaitAndSetEvent(&second, &third); },
|
||||||
/*milliseconds=*/10);
|
/*milliseconds=*/10);
|
||||||
|
|
||||||
// All tasks have been posted before the first one is unblocked.
|
// All tasks have been posted before the first one is unblocked.
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "common_video/include/video_frame_buffer.h"
|
#include "common_video/include/video_frame_buffer.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/keep_ref_until_done.h"
|
#include "rtc_base/keep_ref_until_done.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "modules/audio_device/fine_audio_buffer.h"
|
#include "modules/audio_device/fine_audio_buffer.h"
|
||||||
#include "rtc_base/atomic_ops.h"
|
#include "rtc_base/atomic_ops.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
#include "rtc_base/thread.h"
|
#include "rtc_base/thread.h"
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/numerics/samples_stats_counter.h"
|
#include "api/numerics/samples_stats_counter.h"
|
||||||
#include "api/units/data_size.h"
|
#include "api/units/data_size.h"
|
||||||
#include "rtc_base/bind.h"
|
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
Reference in New Issue
Block a user