Simplify reference counting implementation of PendingTaskSafetyFlag.

On a 32bit system, this reduces the allocation size of the flag
down from 12 bytes to 8, and removes the need for a vtable (the extra
4 bytes are the vtable pointer).

The downside is that this change makes the binary layout of the
flag, less compatible with RefCountedObject<> based reference counting
objects and thus we don't immediately get the benefits of identical
COMDAT folding and subsequently there's a slight binary size increase.
With wider use, the binary size benefits will come.

Bug: none
Change-Id: I04129771790a3258d6accaf0ab1258b7a798a55e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/215681
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33793}
This commit is contained in:
Tommi 2021-04-20 16:58:01 +02:00 committed by Commit Bot
parent e313c07020
commit 86ee89f73e
19 changed files with 105 additions and 49 deletions

View File

@ -561,6 +561,7 @@ rtc_source_set("rtc_stats_api") {
deps = [ deps = [
":scoped_refptr", ":scoped_refptr",
"../api:refcountedbase",
"../rtc_base:checks", "../rtc_base:checks",
"../rtc_base:rtc_base_approved", "../rtc_base:rtc_base_approved",
"../rtc_base/system:rtc_export", "../rtc_base/system:rtc_export",
@ -682,7 +683,10 @@ rtc_source_set("array_view") {
rtc_source_set("refcountedbase") { rtc_source_set("refcountedbase") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ "ref_counted_base.h" ] sources = [ "ref_counted_base.h" ]
deps = [ "../rtc_base:rtc_base_approved" ] deps = [
"../rtc_base:macromagic",
"../rtc_base:refcount",
]
} }
rtc_library("ice_transport_factory") { rtc_library("ice_transport_factory") {

View File

@ -10,8 +10,9 @@
#ifndef API_REF_COUNTED_BASE_H_ #ifndef API_REF_COUNTED_BASE_H_
#define API_REF_COUNTED_BASE_H_ #define API_REF_COUNTED_BASE_H_
#include <type_traits>
#include "rtc_base/constructor_magic.h" #include "rtc_base/constructor_magic.h"
#include "rtc_base/ref_count.h"
#include "rtc_base/ref_counter.h" #include "rtc_base/ref_counter.h"
namespace rtc { namespace rtc {
@ -38,6 +39,51 @@ class RefCountedBase {
RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedBase); RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
}; };
// Template based version of `RefCountedBase` for simple implementations that do
// not need (or want) destruction via virtual destructor or the overhead of a
// vtable.
//
// To use:
// struct MyInt : public rtc::RefCountedNonVirtual<MyInt> {
// int foo_ = 0;
// };
//
// rtc::scoped_refptr<MyInt> my_int(new MyInt());
//
// sizeof(MyInt) on a 32 bit system would then be 8, int + refcount and no
// vtable generated.
template <typename T>
class RefCountedNonVirtual {
public:
RefCountedNonVirtual() = default;
void AddRef() const { ref_count_.IncRef(); }
RefCountReleaseStatus Release() const {
// If you run into this assert, T has virtual methods. There are two
// options:
// 1) The class doesn't actually need virtual methods, the type is complete
// so the virtual attribute(s) can be removed.
// 2) The virtual methods are a part of the design of the class. In this
// case you can consider using `RefCountedBase` instead or alternatively
// use `rtc::RefCountedObject`.
static_assert(!std::is_polymorphic<T>::value,
"T has virtual methods. RefCountedBase is a better fit.");
const auto status = ref_count_.DecRef();
if (status == RefCountReleaseStatus::kDroppedLastRef) {
delete static_cast<const T*>(this);
}
return status;
}
protected:
~RefCountedNonVirtual() = default;
private:
mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedNonVirtual);
};
} // namespace rtc } // namespace rtc
#endif // API_REF_COUNTED_BASE_H_ #endif // API_REF_COUNTED_BASE_H_

View File

@ -19,9 +19,11 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "api/stats/rtc_stats.h" #include "api/stats/rtc_stats.h"
#include "rtc_base/ref_count.h" // TODO(tommi): Remove this include after fixing iwyu issue in chromium.
// See: third_party/blink/renderer/platform/peerconnection/rtc_stats.cc
#include "rtc_base/ref_counted_object.h" #include "rtc_base/ref_counted_object.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
@ -29,7 +31,8 @@ namespace webrtc {
// A collection of stats. // A collection of stats.
// This is accessible as a map from |RTCStats::id| to |RTCStats|. // This is accessible as a map from |RTCStats::id| to |RTCStats|.
class RTC_EXPORT RTCStatsReport : public rtc::RefCountInterface { class RTC_EXPORT RTCStatsReport final
: public rtc::RefCountedNonVirtual<RTCStatsReport> {
public: public:
typedef std::map<std::string, std::unique_ptr<const RTCStats>> StatsMap; typedef std::map<std::string, std::unique_ptr<const RTCStats>> StatsMap;
@ -107,11 +110,11 @@ class RTC_EXPORT RTCStatsReport : public rtc::RefCountInterface {
// listing all of its stats objects. // listing all of its stats objects.
std::string ToJson() const; std::string ToJson() const;
friend class rtc::RefCountedObject<RTCStatsReport>; protected:
friend class rtc::RefCountedNonVirtual<RTCStatsReport>;
~RTCStatsReport() = default;
private: private:
~RTCStatsReport() override;
int64_t timestamp_us_; int64_t timestamp_us_;
StatsMap stats_; StatsMap stats_;
}; };

View File

@ -32,7 +32,8 @@ namespace webrtc {
// window using criteria provided by application specific // window using criteria provided by application specific
// FullScreenApplicationHandler. // FullScreenApplicationHandler.
class FullScreenWindowDetector : public rtc::RefCountedBase { class FullScreenWindowDetector
: public rtc::RefCountedNonVirtual<FullScreenWindowDetector> {
public: public:
using ApplicationHandlerFactory = using ApplicationHandlerFactory =
std::function<std::unique_ptr<FullScreenApplicationHandler>( std::function<std::unique_ptr<FullScreenApplicationHandler>(

View File

@ -28,7 +28,8 @@ typedef union _XEvent XEvent;
namespace webrtc { namespace webrtc {
// A ref-counted object to store XDisplay connection. // A ref-counted object to store XDisplay connection.
class RTC_EXPORT SharedXDisplay : public rtc::RefCountedBase { class RTC_EXPORT SharedXDisplay
: public rtc::RefCountedNonVirtual<SharedXDisplay> {
public: public:
class XEventHandler { class XEventHandler {
public: public:
@ -38,9 +39,6 @@ class RTC_EXPORT SharedXDisplay : public rtc::RefCountedBase {
virtual bool HandleXEvent(const XEvent& event) = 0; virtual bool HandleXEvent(const XEvent& event) = 0;
}; };
// Takes ownership of |display|.
explicit SharedXDisplay(Display* display);
// Creates a new X11 Display for the |display_name|. NULL is returned if X11 // Creates a new X11 Display for the |display_name|. NULL is returned if X11
// connection failed. Equivalent to CreateDefault() when |display_name| is // connection failed. Equivalent to CreateDefault() when |display_name| is
// empty. // empty.
@ -65,8 +63,11 @@ class RTC_EXPORT SharedXDisplay : public rtc::RefCountedBase {
void IgnoreXServerGrabs(); void IgnoreXServerGrabs();
~SharedXDisplay();
protected: protected:
~SharedXDisplay() override; // Takes ownership of |display|.
explicit SharedXDisplay(Display* display);
private: private:
typedef std::map<int, std::vector<XEventHandler*> > EventHandlersMap; typedef std::map<int, std::vector<XEventHandler*> > EventHandlersMap;

View File

@ -25,15 +25,15 @@ namespace webrtc {
// The class provides functions to synchronize capturing and display // The class provides functions to synchronize capturing and display
// reconfiguring across threads, and the up-to-date MacDesktopConfiguration. // reconfiguring across threads, and the up-to-date MacDesktopConfiguration.
class DesktopConfigurationMonitor : public rtc::RefCountedBase { class DesktopConfigurationMonitor final
: public rtc::RefCountedNonVirtual<DesktopConfigurationMonitor> {
public: public:
DesktopConfigurationMonitor(); DesktopConfigurationMonitor();
~DesktopConfigurationMonitor();
// Returns the current desktop configuration. // Returns the current desktop configuration.
MacDesktopConfiguration desktop_configuration(); MacDesktopConfiguration desktop_configuration();
protected:
~DesktopConfigurationMonitor() override;
private: private:
static void DisplaysReconfiguredCallback(CGDirectDisplayID display, static void DisplaysReconfiguredCallback(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags, CGDisplayChangeSummaryFlags flags,

View File

@ -329,6 +329,7 @@ rtc_library("connection_context") {
"../api:callfactory_api", "../api:callfactory_api",
"../api:libjingle_peerconnection_api", "../api:libjingle_peerconnection_api",
"../api:media_stream_interface", "../api:media_stream_interface",
"../api:refcountedbase",
"../api:scoped_refptr", "../api:scoped_refptr",
"../api:sequence_checker", "../api:sequence_checker",
"../api/neteq:neteq_api", "../api/neteq:neteq_api",

View File

@ -17,7 +17,6 @@
#include "api/transport/field_trial_based_config.h" #include "api/transport/field_trial_based_config.h"
#include "media/sctp/sctp_transport_factory.h" #include "media/sctp/sctp_transport_factory.h"
#include "rtc_base/helpers.h" #include "rtc_base/helpers.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/task_utils/to_queued_task.h"
#include "rtc_base/time_utils.h" #include "rtc_base/time_utils.h"
@ -76,7 +75,7 @@ std::unique_ptr<SctpTransportFactoryInterface> MaybeCreateSctpFactory(
// Static // Static
rtc::scoped_refptr<ConnectionContext> ConnectionContext::Create( rtc::scoped_refptr<ConnectionContext> ConnectionContext::Create(
PeerConnectionFactoryDependencies* dependencies) { PeerConnectionFactoryDependencies* dependencies) {
return new rtc::RefCountedObject<ConnectionContext>(dependencies); return new ConnectionContext(dependencies);
} }
ConnectionContext::ConnectionContext( ConnectionContext::ConnectionContext(

View File

@ -17,6 +17,7 @@
#include "api/call/call_factory_interface.h" #include "api/call/call_factory_interface.h"
#include "api/media_stream_interface.h" #include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h" #include "api/peer_connection_interface.h"
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "api/sequence_checker.h" #include "api/sequence_checker.h"
#include "api/transport/sctp_transport_factory_interface.h" #include "api/transport/sctp_transport_factory_interface.h"
@ -27,7 +28,6 @@
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/network.h" #include "rtc_base/network.h"
#include "rtc_base/network_monitor_factory.h" #include "rtc_base/network_monitor_factory.h"
#include "rtc_base/ref_count.h"
#include "rtc_base/rtc_certificate_generator.h" #include "rtc_base/rtc_certificate_generator.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
#include "rtc_base/thread_annotations.h" #include "rtc_base/thread_annotations.h"
@ -47,7 +47,8 @@ class RtcEventLog;
// interferes with the operation of other PeerConnections. // interferes with the operation of other PeerConnections.
// //
// This class must be created and destroyed on the signaling thread. // This class must be created and destroyed on the signaling thread.
class ConnectionContext : public rtc::RefCountInterface { class ConnectionContext final
: public rtc::RefCountedNonVirtual<ConnectionContext> {
public: public:
// Creates a ConnectionContext. May return null if initialization fails. // Creates a ConnectionContext. May return null if initialization fails.
// The Dependencies class allows simple management of all new dependencies // The Dependencies class allows simple management of all new dependencies
@ -92,7 +93,8 @@ class ConnectionContext : public rtc::RefCountInterface {
protected: protected:
explicit ConnectionContext(PeerConnectionFactoryDependencies* dependencies); explicit ConnectionContext(PeerConnectionFactoryDependencies* dependencies);
virtual ~ConnectionContext(); friend class rtc::RefCountedNonVirtual<ConnectionContext>;
~ConnectionContext();
private: private:
// The following three variables are used to communicate between the // The following three variables are used to communicate between the

View File

@ -916,6 +916,7 @@ rtc_library("rtc_base") {
":threading", ":threading",
"../api:array_view", "../api:array_view",
"../api:function_view", "../api:function_view",
"../api:refcountedbase",
"../api:scoped_refptr", "../api:scoped_refptr",
"../api:sequence_checker", "../api:sequence_checker",
"../api/numerics", "../api/numerics",

View File

@ -13,7 +13,6 @@
#include <memory> #include <memory>
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/ssl_certificate.h" #include "rtc_base/ssl_certificate.h"
#include "rtc_base/ssl_identity.h" #include "rtc_base/ssl_identity.h"
#include "rtc_base/time_utils.h" #include "rtc_base/time_utils.h"
@ -22,14 +21,14 @@ namespace rtc {
scoped_refptr<RTCCertificate> RTCCertificate::Create( scoped_refptr<RTCCertificate> RTCCertificate::Create(
std::unique_ptr<SSLIdentity> identity) { std::unique_ptr<SSLIdentity> identity) {
return new RefCountedObject<RTCCertificate>(identity.release()); return new RTCCertificate(identity.release());
} }
RTCCertificate::RTCCertificate(SSLIdentity* identity) : identity_(identity) { RTCCertificate::RTCCertificate(SSLIdentity* identity) : identity_(identity) {
RTC_DCHECK(identity_); RTC_DCHECK(identity_);
} }
RTCCertificate::~RTCCertificate() {} RTCCertificate::~RTCCertificate() = default;
uint64_t RTCCertificate::Expires() const { uint64_t RTCCertificate::Expires() const {
int64_t expires = GetSSLCertificate().CertificateExpirationTime(); int64_t expires = GetSSLCertificate().CertificateExpirationTime();
@ -67,7 +66,7 @@ scoped_refptr<RTCCertificate> RTCCertificate::FromPEM(
SSLIdentity::CreateFromPEMStrings(pem.private_key(), pem.certificate())); SSLIdentity::CreateFromPEMStrings(pem.private_key(), pem.certificate()));
if (!identity) if (!identity)
return nullptr; return nullptr;
return new RefCountedObject<RTCCertificate>(identity.release()); return new RTCCertificate(identity.release());
} }
bool RTCCertificate::operator==(const RTCCertificate& certificate) const { bool RTCCertificate::operator==(const RTCCertificate& certificate) const {

View File

@ -16,8 +16,8 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "rtc_base/ref_count.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
namespace rtc { namespace rtc {
@ -49,7 +49,8 @@ class RTCCertificatePEM {
// A thin abstraction layer between "lower level crypto stuff" like // A thin abstraction layer between "lower level crypto stuff" like
// SSLCertificate and WebRTC usage. Takes ownership of some lower level objects, // SSLCertificate and WebRTC usage. Takes ownership of some lower level objects,
// reference counting protects these from premature destruction. // reference counting protects these from premature destruction.
class RTC_EXPORT RTCCertificate : public RefCountInterface { class RTC_EXPORT RTCCertificate final
: public RefCountedNonVirtual<RTCCertificate> {
public: public:
// Takes ownership of |identity|. // Takes ownership of |identity|.
static scoped_refptr<RTCCertificate> Create( static scoped_refptr<RTCCertificate> Create(
@ -82,7 +83,9 @@ class RTC_EXPORT RTCCertificate : public RefCountInterface {
protected: protected:
explicit RTCCertificate(SSLIdentity* identity); explicit RTCCertificate(SSLIdentity* identity);
~RTCCertificate() override;
friend class RefCountedNonVirtual<RTCCertificate>;
~RTCCertificate();
private: private:
// The SSLIdentity is the owner of the SSLCertificate. To protect our // The SSLIdentity is the owner of the SSLCertificate. To protect our

View File

@ -33,7 +33,7 @@ rtc_library("pending_task_safety_flag") {
] ]
deps = [ deps = [
"..:checks", "..:checks",
"..:refcount", "../../api:refcountedbase",
"../../api:scoped_refptr", "../../api:scoped_refptr",
"../../api:sequence_checker", "../../api:sequence_checker",
"../system:no_unique_address", "../system:no_unique_address",

View File

@ -10,19 +10,17 @@
#include "rtc_base/task_utils/pending_task_safety_flag.h" #include "rtc_base/task_utils/pending_task_safety_flag.h"
#include "rtc_base/ref_counted_object.h"
namespace webrtc { namespace webrtc {
// static // static
rtc::scoped_refptr<PendingTaskSafetyFlag> PendingTaskSafetyFlag::Create() { rtc::scoped_refptr<PendingTaskSafetyFlag> PendingTaskSafetyFlag::Create() {
return new rtc::RefCountedObject<PendingTaskSafetyFlag>(true); return new PendingTaskSafetyFlag(true);
} }
rtc::scoped_refptr<PendingTaskSafetyFlag> rtc::scoped_refptr<PendingTaskSafetyFlag>
PendingTaskSafetyFlag::CreateDetached() { PendingTaskSafetyFlag::CreateDetached() {
rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag( rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag(
new rtc::RefCountedObject<PendingTaskSafetyFlag>(true)); new PendingTaskSafetyFlag(true));
safety_flag->main_sequence_.Detach(); safety_flag->main_sequence_.Detach();
return safety_flag; return safety_flag;
} }
@ -30,7 +28,7 @@ PendingTaskSafetyFlag::CreateDetached() {
rtc::scoped_refptr<PendingTaskSafetyFlag> rtc::scoped_refptr<PendingTaskSafetyFlag>
PendingTaskSafetyFlag::CreateDetachedInactive() { PendingTaskSafetyFlag::CreateDetachedInactive() {
rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag( rtc::scoped_refptr<PendingTaskSafetyFlag> safety_flag(
new rtc::RefCountedObject<PendingTaskSafetyFlag>(false)); new PendingTaskSafetyFlag(false));
safety_flag->main_sequence_.Detach(); safety_flag->main_sequence_.Detach();
return safety_flag; return safety_flag;
} }

View File

@ -11,10 +11,10 @@
#ifndef RTC_BASE_TASK_UTILS_PENDING_TASK_SAFETY_FLAG_H_ #ifndef RTC_BASE_TASK_UTILS_PENDING_TASK_SAFETY_FLAG_H_
#define RTC_BASE_TASK_UTILS_PENDING_TASK_SAFETY_FLAG_H_ #define RTC_BASE_TASK_UTILS_PENDING_TASK_SAFETY_FLAG_H_
#include "api/ref_counted_base.h"
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "api/sequence_checker.h" #include "api/sequence_checker.h"
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/ref_count.h"
#include "rtc_base/system/no_unique_address.h" #include "rtc_base/system/no_unique_address.h"
namespace webrtc { namespace webrtc {
@ -55,7 +55,8 @@ namespace webrtc {
// my_task_queue_->PostTask(ToQueuedTask(pending_task_safety_flag_, // my_task_queue_->PostTask(ToQueuedTask(pending_task_safety_flag_,
// [this]() { MyMethod(); })); // [this]() { MyMethod(); }));
// //
class PendingTaskSafetyFlag : public rtc::RefCountInterface { class PendingTaskSafetyFlag final
: public rtc::RefCountedNonVirtual<PendingTaskSafetyFlag> {
public: public:
static rtc::scoped_refptr<PendingTaskSafetyFlag> Create(); static rtc::scoped_refptr<PendingTaskSafetyFlag> Create();
@ -113,7 +114,7 @@ class PendingTaskSafetyFlag : public rtc::RefCountInterface {
// This should be used by the class that wants tasks dropped after destruction. // This should be used by the class that wants tasks dropped after destruction.
// The requirement is that the instance has to be constructed and destructed on // The requirement is that the instance has to be constructed and destructed on
// the same thread as the potentially dropped tasks would be running on. // the same thread as the potentially dropped tasks would be running on.
class ScopedTaskSafety { class ScopedTaskSafety final {
public: public:
ScopedTaskSafety() = default; ScopedTaskSafety() = default;
~ScopedTaskSafety() { flag_->SetNotAlive(); } ~ScopedTaskSafety() { flag_->SetNotAlive(); }
@ -128,7 +129,7 @@ class ScopedTaskSafety {
// Like ScopedTaskSafety, but allows construction on a different thread than // Like ScopedTaskSafety, but allows construction on a different thread than
// where the flag will be used. // where the flag will be used.
class ScopedTaskSafetyDetached { class ScopedTaskSafetyDetached final {
public: public:
ScopedTaskSafetyDetached() = default; ScopedTaskSafetyDetached() = default;
~ScopedTaskSafetyDetached() { flag_->SetNotAlive(); } ~ScopedTaskSafetyDetached() { flag_->SetNotAlive(); }

View File

@ -106,8 +106,6 @@ OpenSLEngineManager::OpenSLEngineManager() {
thread_checker_.Detach(); thread_checker_.Detach();
} }
OpenSLEngineManager::~OpenSLEngineManager() = default;
SLObjectItf OpenSLEngineManager::GetOpenSLEngine() { SLObjectItf OpenSLEngineManager::GetOpenSLEngine() {
RTC_LOG(INFO) << "GetOpenSLEngine"; RTC_LOG(INFO) << "GetOpenSLEngine";
RTC_DCHECK(thread_checker_.IsCurrent()); RTC_DCHECK(thread_checker_.IsCurrent());

View File

@ -68,10 +68,11 @@ typedef ScopedSLObject<SLObjectItf, const SLObjectItf_*> ScopedSLObjectItf;
// Subsequent calls returns the already created engine. // Subsequent calls returns the already created engine.
// Note: This class must be used single threaded and this is enforced by a // Note: This class must be used single threaded and this is enforced by a
// thread checker. // thread checker.
class OpenSLEngineManager : public rtc::RefCountedBase { class OpenSLEngineManager
: public rtc::RefCountedNonVirtual<OpenSLEngineManager> {
public: public:
OpenSLEngineManager(); OpenSLEngineManager();
~OpenSLEngineManager() override; ~OpenSLEngineManager() = default;
SLObjectItf GetOpenSLEngine(); SLObjectItf GetOpenSLEngine();
private: private:

View File

@ -20,10 +20,11 @@
namespace webrtc { namespace webrtc {
namespace jni { namespace jni {
class AddIceCandidateObserverJni final : public rtc::RefCountedBase { class AddIceCandidateObserverJni final
: public rtc::RefCountedNonVirtual<AddIceCandidateObserverJni> {
public: public:
AddIceCandidateObserverJni(JNIEnv* env, const JavaRef<jobject>& j_observer); AddIceCandidateObserverJni(JNIEnv* env, const JavaRef<jobject>& j_observer);
~AddIceCandidateObserverJni() override = default; ~AddIceCandidateObserverJni() = default;
void OnComplete(RTCError error); void OnComplete(RTCError error);

View File

@ -56,15 +56,12 @@ bool RTCStatsReport::ConstIterator::operator!=(
rtc::scoped_refptr<RTCStatsReport> RTCStatsReport::Create( rtc::scoped_refptr<RTCStatsReport> RTCStatsReport::Create(
int64_t timestamp_us) { int64_t timestamp_us) {
return rtc::scoped_refptr<RTCStatsReport>( return rtc::scoped_refptr<RTCStatsReport>(new RTCStatsReport(timestamp_us));
new rtc::RefCountedObject<RTCStatsReport>(timestamp_us));
} }
RTCStatsReport::RTCStatsReport(int64_t timestamp_us) RTCStatsReport::RTCStatsReport(int64_t timestamp_us)
: timestamp_us_(timestamp_us) {} : timestamp_us_(timestamp_us) {}
RTCStatsReport::~RTCStatsReport() {}
rtc::scoped_refptr<RTCStatsReport> RTCStatsReport::Copy() const { rtc::scoped_refptr<RTCStatsReport> RTCStatsReport::Copy() const {
rtc::scoped_refptr<RTCStatsReport> copy = Create(timestamp_us_); rtc::scoped_refptr<RTCStatsReport> copy = Create(timestamp_us_);
for (auto it = stats_.begin(); it != stats_.end(); ++it) { for (auto it = stats_.begin(); it != stats_.end(); ++it) {