Introduce BYPASS_PROXY_CONSTMETHOD0.

This allows const getters that query const state to be called without
marshalling calls between threads. This must not be used to
return pointers/references etc.

I'm starting by using this macro with the data channel which has a
few of these getters, as well as changing things a bit to make more
parts of the implementation, const.

Change-Id: I6ec7a3774cd8f7be2ef122fb7c7fc5919afee600
Bug: webrtc:11547
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/176846
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31489}
This commit is contained in:
Tomas Gunnarsson 2020-06-10 12:17:50 +02:00 committed by Commit Bot
parent 5f7bfbe6c6
commit 0ca13d97d2
4 changed files with 58 additions and 37 deletions

View File

@ -55,6 +55,7 @@
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include "api/scoped_refptr.h"
@ -396,6 +397,16 @@ class ConstMethodCall : public rtc::Message, public rtc::MessageHandler {
return call.Marshal(RTC_FROM_HERE, worker_thread_); \
}
// For use when returning purely const state (set during construction).
// Use with caution. This method should only be used when the return value will
// always be the same.
#define BYPASS_PROXY_CONSTMETHOD0(r, method) \
r method() const override { \
static_assert(!std::is_pointer<r>::value, "Type is a pointer"); \
static_assert(!std::is_reference<r>::value, "Type is a reference"); \
return c_->method(); \
}
} // namespace webrtc
#endif // API_PROXY_H_

View File

@ -139,9 +139,9 @@ rtc::scoped_refptr<DataChannel> DataChannel::Create(
const std::string& label,
const InternalDataChannelInit& config) {
rtc::scoped_refptr<DataChannel> channel(
new rtc::RefCountedObject<DataChannel>(provider, dct, label));
if (!channel->Init(config)) {
return NULL;
new rtc::RefCountedObject<DataChannel>(config, provider, dct, label));
if (!channel->Init()) {
return nullptr;
}
return channel;
}
@ -152,11 +152,13 @@ bool DataChannel::IsSctpLike(cricket::DataChannelType type) {
type == cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP;
}
DataChannel::DataChannel(DataChannelProviderInterface* provider,
DataChannel::DataChannel(const InternalDataChannelInit& config,
DataChannelProviderInterface* provider,
cricket::DataChannelType dct,
const std::string& label)
: internal_id_(GenerateUniqueId()),
label_(label),
config_(config),
observer_(nullptr),
state_(kConnecting),
messages_sent_(0),
@ -174,29 +176,28 @@ DataChannel::DataChannel(DataChannelProviderInterface* provider,
send_ssrc_(0),
receive_ssrc_(0) {}
bool DataChannel::Init(const InternalDataChannelInit& config) {
bool DataChannel::Init() {
if (data_channel_type_ == cricket::DCT_RTP) {
if (config.reliable || config.id != -1 || config.maxRetransmits ||
config.maxRetransmitTime) {
if (config_.reliable || config_.id != -1 || config_.maxRetransmits ||
config_.maxRetransmitTime) {
RTC_LOG(LS_ERROR) << "Failed to initialize the RTP data channel due to "
"invalid DataChannelInit.";
return false;
}
handshake_state_ = kHandshakeReady;
} else if (IsSctpLike(data_channel_type_)) {
if (config.id < -1 ||
(config.maxRetransmits && *config.maxRetransmits < 0) ||
(config.maxRetransmitTime && *config.maxRetransmitTime < 0)) {
if (config_.id < -1 ||
(config_.maxRetransmits && *config_.maxRetransmits < 0) ||
(config_.maxRetransmitTime && *config_.maxRetransmitTime < 0)) {
RTC_LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
"invalid DataChannelInit.";
return false;
}
if (config.maxRetransmits && config.maxRetransmitTime) {
if (config_.maxRetransmits && config_.maxRetransmitTime) {
RTC_LOG(LS_ERROR)
<< "maxRetransmits and maxRetransmitTime should not be both set.";
return false;
}
config_ = config;
switch (config_.open_handshake_role) {
case webrtc::InternalDataChannelInit::kNone: // pre-negotiated
@ -323,7 +324,7 @@ void DataChannel::SetSctpSid(int sid) {
return;
}
config_.id = sid;
const_cast<InternalDataChannelInit&>(config_).id = sid;
provider_->AddSctpDataStream(sid);
}

View File

@ -54,6 +54,8 @@ class DataChannelProviderInterface {
virtual ~DataChannelProviderInterface() {}
};
// TODO(tommi): Change to not inherit from DataChannelInit but to have it as
// a const member. Block access to the 'id' member since it cannot be const.
struct InternalDataChannelInit : public DataChannelInit {
enum OpenHandshakeRole { kOpener, kAcker, kNone };
// The default role is kOpener because the default |negotiated| is false.
@ -229,7 +231,8 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
static void ResetInternalIdAllocatorForTesting(int new_value);
protected:
DataChannel(DataChannelProviderInterface* client,
DataChannel(const InternalDataChannelInit& config,
DataChannelProviderInterface* client,
cricket::DataChannelType dct,
const std::string& label);
virtual ~DataChannel();
@ -266,7 +269,7 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
kHandshakeReady
};
bool Init(const InternalDataChannelInit& config);
bool Init();
void UpdateState();
void SetState(DataState state);
void DisconnectFromProvider();
@ -282,8 +285,8 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
const int internal_id_;
std::string label_;
InternalDataChannelInit config_;
const std::string label_;
const InternalDataChannelInit config_;
DataChannelObserver* observer_;
DataState state_;
RTCError error_;
@ -294,7 +297,7 @@ class DataChannel : public DataChannelInterface, public sigslot::has_slots<> {
// Number of bytes of data that have been queued using Send(). Increased
// before each transport send and decreased after each successful send.
uint64_t buffered_amount_;
cricket::DataChannelType data_channel_type_;
const cricket::DataChannelType data_channel_type_;
DataChannelProviderInterface* provider_;
HandshakeState handshake_state_;
bool connected_to_provider_;
@ -318,17 +321,18 @@ BEGIN_SIGNALING_PROXY_MAP(DataChannel)
PROXY_SIGNALING_THREAD_DESTRUCTOR()
PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*)
PROXY_METHOD0(void, UnregisterObserver)
PROXY_CONSTMETHOD0(std::string, label)
PROXY_CONSTMETHOD0(bool, reliable)
PROXY_CONSTMETHOD0(bool, ordered)
PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
PROXY_CONSTMETHOD0(absl::optional<int>, maxRetransmitsOpt)
PROXY_CONSTMETHOD0(absl::optional<int>, maxPacketLifeTime)
PROXY_CONSTMETHOD0(std::string, protocol)
PROXY_CONSTMETHOD0(bool, negotiated)
BYPASS_PROXY_CONSTMETHOD0(std::string, label)
BYPASS_PROXY_CONSTMETHOD0(bool, reliable)
BYPASS_PROXY_CONSTMETHOD0(bool, ordered)
BYPASS_PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime)
BYPASS_PROXY_CONSTMETHOD0(uint16_t, maxRetransmits)
BYPASS_PROXY_CONSTMETHOD0(absl::optional<int>, maxRetransmitsOpt)
BYPASS_PROXY_CONSTMETHOD0(absl::optional<int>, maxPacketLifeTime)
BYPASS_PROXY_CONSTMETHOD0(std::string, protocol)
BYPASS_PROXY_CONSTMETHOD0(bool, negotiated)
// Can't bypass the proxy since the id may change.
PROXY_CONSTMETHOD0(int, id)
PROXY_CONSTMETHOD0(Priority, priority)
BYPASS_PROXY_CONSTMETHOD0(Priority, priority)
PROXY_CONSTMETHOD0(DataState, state)
PROXY_CONSTMETHOD0(RTCError, error)
PROXY_CONSTMETHOD0(uint32_t, messages_sent)

View File

@ -22,15 +22,20 @@ class MockDataChannel : public rtc::RefCountedObject<DataChannel> {
public:
MockDataChannel(int id, DataState state)
: MockDataChannel(id, "MockDataChannel", state, "udp", 0, 0, 0, 0) {}
MockDataChannel(int id,
const std::string& label,
DataState state,
const std::string& protocol,
uint32_t messages_sent,
uint64_t bytes_sent,
uint32_t messages_received,
uint64_t bytes_received)
: rtc::RefCountedObject<DataChannel>(nullptr, cricket::DCT_NONE, label) {
MockDataChannel(
int id,
const std::string& label,
DataState state,
const std::string& protocol,
uint32_t messages_sent,
uint64_t bytes_sent,
uint32_t messages_received,
uint64_t bytes_received,
const InternalDataChannelInit& config = InternalDataChannelInit())
: rtc::RefCountedObject<DataChannel>(config,
nullptr,
cricket::DCT_NONE,
label) {
EXPECT_CALL(*this, id()).WillRepeatedly(::testing::Return(id));
EXPECT_CALL(*this, state()).WillRepeatedly(::testing::Return(state));
EXPECT_CALL(*this, protocol()).WillRepeatedly(::testing::Return(protocol));