mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00

This should substantially reduce the overhead due to deferred callbacks in profiles. Bug: webrtc:15723 Change-Id: I4c52beb91eb08c9b0ac2d1ce9a4e11839aa35e38 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/331020 Reviewed-by: Victor Boivie <boivie@webrtc.org> Commit-Queue: Daniel Collins <dpcollins@google.com> Cr-Commit-Position: refs/heads/main@{#41363}
116 lines
4.4 KiB
C++
116 lines
4.4 KiB
C++
/*
|
|
* Copyright (c) 2021 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.
|
|
*/
|
|
#ifndef NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_
|
|
#define NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_
|
|
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "absl/strings/string_view.h"
|
|
#include "absl/types/variant.h"
|
|
#include "api/array_view.h"
|
|
#include "api/ref_counted_base.h"
|
|
#include "api/scoped_refptr.h"
|
|
#include "api/task_queue/task_queue_base.h"
|
|
#include "net/dcsctp/public/dcsctp_message.h"
|
|
#include "net/dcsctp/public/dcsctp_socket.h"
|
|
|
|
namespace dcsctp {
|
|
// Defers callbacks until they can be safely triggered.
|
|
//
|
|
// There are a lot of callbacks from the dcSCTP library to the client,
|
|
// such as when messages are received or streams are closed. When the client
|
|
// receives these callbacks, the client is expected to be able to call into the
|
|
// library - from within the callback. For example, sending a reply message when
|
|
// a certain SCTP message has been received, or to reconnect when the connection
|
|
// was closed for any reason. This means that the dcSCTP library must always be
|
|
// in a consistent and stable state when these callbacks are delivered, and to
|
|
// ensure that's the case, callbacks are not immediately delivered from where
|
|
// they originate, but instead queued (deferred) by this class. At the end of
|
|
// any public API method that may result in callbacks, they are triggered and
|
|
// then delivered.
|
|
//
|
|
// There are a number of exceptions, which is clearly annotated in the API.
|
|
class CallbackDeferrer : public DcSctpSocketCallbacks {
|
|
public:
|
|
class ScopedDeferrer {
|
|
public:
|
|
explicit ScopedDeferrer(CallbackDeferrer& callback_deferrer)
|
|
: callback_deferrer_(callback_deferrer) {
|
|
callback_deferrer_.Prepare();
|
|
}
|
|
|
|
~ScopedDeferrer() { callback_deferrer_.TriggerDeferred(); }
|
|
|
|
private:
|
|
CallbackDeferrer& callback_deferrer_;
|
|
};
|
|
|
|
explicit CallbackDeferrer(DcSctpSocketCallbacks& underlying)
|
|
: underlying_(underlying) {}
|
|
|
|
// Implementation of DcSctpSocketCallbacks
|
|
SendPacketStatus SendPacketWithStatus(
|
|
rtc::ArrayView<const uint8_t> data) override;
|
|
std::unique_ptr<Timeout> CreateTimeout(
|
|
webrtc::TaskQueueBase::DelayPrecision precision) override;
|
|
TimeMs TimeMillis() override;
|
|
webrtc::Timestamp Now() override { return underlying_.Now(); }
|
|
uint32_t GetRandomInt(uint32_t low, uint32_t high) override;
|
|
void OnMessageReceived(DcSctpMessage message) override;
|
|
void OnError(ErrorKind error, absl::string_view message) override;
|
|
void OnAborted(ErrorKind error, absl::string_view message) override;
|
|
void OnConnected() override;
|
|
void OnClosed() override;
|
|
void OnConnectionRestarted() override;
|
|
void OnStreamsResetFailed(rtc::ArrayView<const StreamID> outgoing_streams,
|
|
absl::string_view reason) override;
|
|
void OnStreamsResetPerformed(
|
|
rtc::ArrayView<const StreamID> outgoing_streams) override;
|
|
void OnIncomingStreamsReset(
|
|
rtc::ArrayView<const StreamID> incoming_streams) override;
|
|
void OnBufferedAmountLow(StreamID stream_id) override;
|
|
void OnTotalBufferedAmountLow() override;
|
|
|
|
void OnLifecycleMessageExpired(LifecycleId lifecycle_id,
|
|
bool maybe_delivered) override;
|
|
void OnLifecycleMessageFullySent(LifecycleId lifecycle_id) override;
|
|
void OnLifecycleMessageDelivered(LifecycleId lifecycle_id) override;
|
|
void OnLifecycleEnd(LifecycleId lifecycle_id) override;
|
|
|
|
private:
|
|
struct Error {
|
|
ErrorKind error;
|
|
std::string message;
|
|
};
|
|
struct StreamReset {
|
|
std::vector<StreamID> streams;
|
|
std::string message;
|
|
};
|
|
// Use a pre-sized variant for storage to avoid double heap allocation. This
|
|
// variant can hold all cases of stored data.
|
|
using CallbackData = absl::
|
|
variant<absl::monostate, DcSctpMessage, Error, StreamReset, StreamID>;
|
|
using Callback = void (*)(CallbackData, DcSctpSocketCallbacks&);
|
|
|
|
void Prepare();
|
|
void TriggerDeferred();
|
|
|
|
DcSctpSocketCallbacks& underlying_;
|
|
bool prepared_ = false;
|
|
std::vector<std::pair<Callback, CallbackData>> deferred_;
|
|
};
|
|
} // namespace dcsctp
|
|
|
|
#endif // NET_DCSCTP_SOCKET_CALLBACK_DEFERRER_H_
|