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}
diff --git a/api/proxy.h b/api/proxy.h
index 385992e..b1ebe31 100644
--- a/api/proxy.h
+++ b/api/proxy.h
@@ -55,6 +55,7 @@
#include <memory>
#include <string>
#include <tuple>
+#include <type_traits>
#include <utility>
#include "api/scoped_refptr.h"
@@ -396,6 +397,16 @@
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_
diff --git a/pc/data_channel.cc b/pc/data_channel.cc
index 0b9af37..795bf8d 100644
--- a/pc/data_channel.cc
+++ b/pc/data_channel.cc
@@ -139,9 +139,9 @@
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 @@
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 @@
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 @@
return;
}
- config_.id = sid;
+ const_cast<InternalDataChannelInit&>(config_).id = sid;
provider_->AddSctpDataStream(sid);
}
diff --git a/pc/data_channel.h b/pc/data_channel.h
index 9a0a0aa..1ee2679 100644
--- a/pc/data_channel.h
+++ b/pc/data_channel.h
@@ -54,6 +54,8 @@
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 @@
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 @@
kHandshakeReady
};
- bool Init(const InternalDataChannelInit& config);
+ bool Init();
void UpdateState();
void SetState(DataState state);
void DisconnectFromProvider();
@@ -282,8 +285,8 @@
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 @@
// 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 @@
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)
diff --git a/pc/test/mock_data_channel.h b/pc/test/mock_data_channel.h
index 9ca018a..63f0e6c 100644
--- a/pc/test/mock_data_channel.h
+++ b/pc/test/mock_data_channel.h
@@ -22,15 +22,20 @@
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));