webrtc/rtc_base/copy_on_write_buffer.cc
Danil Chapovalov 8df643b387 Introduce FinalRefCountedObject template class
To add ref counting to any class while avoiding
virtual functions for reference counting.
This template can both slightly reduce binary size
and slightly improve performance.

Bug: webrtc:11308
Change-Id: I90ac735f6c220ee2a1a991a71039acdb0ca86453
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/198845
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33058}
2021-01-22 16:20:22 +00:00

125 lines
3.2 KiB
C++

/*
* Copyright 2016 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/copy_on_write_buffer.h"
#include <stddef.h>
namespace rtc {
CopyOnWriteBuffer::CopyOnWriteBuffer() : offset_(0), size_(0) {
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
: buffer_(buf.buffer_), offset_(buf.offset_), size_(buf.size_) {}
CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
: buffer_(std::move(buf.buffer_)), offset_(buf.offset_), size_(buf.size_) {
buf.offset_ = 0;
buf.size_ = 0;
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::CopyOnWriteBuffer(const std::string& s)
: CopyOnWriteBuffer(s.data(), s.length()) {}
CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
: buffer_(size > 0 ? new RefCountedBuffer(size) : nullptr),
offset_(0),
size_(size) {
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
: buffer_(size > 0 || capacity > 0 ? new RefCountedBuffer(size, capacity)
: nullptr),
offset_(0),
size_(size) {
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
// Must either be the same view of the same buffer or have the same contents.
RTC_DCHECK(IsConsistent());
RTC_DCHECK(buf.IsConsistent());
return size_ == buf.size_ &&
(cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
}
void CopyOnWriteBuffer::SetSize(size_t size) {
RTC_DCHECK(IsConsistent());
if (!buffer_) {
if (size > 0) {
buffer_ = new RefCountedBuffer(size);
offset_ = 0;
size_ = size;
}
RTC_DCHECK(IsConsistent());
return;
}
if (size <= size_) {
size_ = size;
return;
}
UnshareAndEnsureCapacity(std::max(capacity(), size));
buffer_->SetSize(size + offset_);
size_ = size;
RTC_DCHECK(IsConsistent());
}
void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
RTC_DCHECK(IsConsistent());
if (!buffer_) {
if (new_capacity > 0) {
buffer_ = new RefCountedBuffer(0, new_capacity);
offset_ = 0;
size_ = 0;
}
RTC_DCHECK(IsConsistent());
return;
} else if (new_capacity <= capacity()) {
return;
}
UnshareAndEnsureCapacity(new_capacity);
RTC_DCHECK(IsConsistent());
}
void CopyOnWriteBuffer::Clear() {
if (!buffer_)
return;
if (buffer_->HasOneRef()) {
buffer_->Clear();
} else {
buffer_ = new RefCountedBuffer(0, capacity());
}
offset_ = 0;
size_ = 0;
RTC_DCHECK(IsConsistent());
}
void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
if (buffer_->HasOneRef() && new_capacity <= capacity()) {
return;
}
buffer_ =
new RefCountedBuffer(buffer_->data() + offset_, size_, new_capacity);
offset_ = 0;
RTC_DCHECK(IsConsistent());
}
} // namespace rtc