Add Slice method to CopyOnWriteBuffer and use it in FEC code.

This avoids unnecessary memcpy calls.

Bug: webrtc:10750
Change-Id: I73fe8f1c9659f2c5e59d7fb97b80349a3504a34a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/145320
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29315}
This commit is contained in:
Ilya Nikolaevskiy
2019-09-25 14:37:10 +02:00
committed by Commit Bot
parent 85d5c197a8
commit 741bab0f6c
5 changed files with 147 additions and 43 deletions

View File

@ -14,40 +14,47 @@
namespace rtc {
CopyOnWriteBuffer::CopyOnWriteBuffer() {
CopyOnWriteBuffer::CopyOnWriteBuffer() : offset_(0), size_(0) {
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::CopyOnWriteBuffer(const CopyOnWriteBuffer& buf)
: buffer_(buf.buffer_) {}
: buffer_(buf.buffer_), offset_(buf.offset_), size_(buf.size_) {}
CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
: buffer_(std::move(buf.buffer_)) {}
: 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 RefCountedObject<Buffer>(size) : nullptr) {
: buffer_(size > 0 ? new RefCountedObject<Buffer>(size) : nullptr),
offset_(0),
size_(size) {
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size, size_t capacity)
: buffer_(size > 0 || capacity > 0
? new RefCountedObject<Buffer>(size, capacity)
: nullptr) {
: nullptr),
offset_(0),
size_(size) {
RTC_DCHECK(IsConsistent());
}
CopyOnWriteBuffer::~CopyOnWriteBuffer() = default;
bool CopyOnWriteBuffer::operator==(const CopyOnWriteBuffer& buf) const {
// Must either use the same buffer internally or have the same contents.
// Must either be the same view of the same buffer or have the same contents.
RTC_DCHECK(IsConsistent());
RTC_DCHECK(buf.IsConsistent());
return buffer_.get() == buf.buffer_.get() ||
(buffer_.get() && buf.buffer_.get() &&
*buffer_.get() == *buf.buffer_.get());
return size_ == buf.size_ &&
(cdata() == buf.cdata() || memcmp(cdata(), buf.cdata(), size_) == 0);
}
void CopyOnWriteBuffer::SetSize(size_t size) {
@ -55,35 +62,39 @@ void CopyOnWriteBuffer::SetSize(size_t size) {
if (!buffer_) {
if (size > 0) {
buffer_ = new RefCountedObject<Buffer>(size);
offset_ = 0;
size_ = size;
}
RTC_DCHECK(IsConsistent());
return;
}
// Clone data if referenced.
if (!buffer_->HasOneRef()) {
buffer_ = new RefCountedObject<Buffer>(buffer_->data(),
std::min(buffer_->size(), size),
std::max(buffer_->capacity(), size));
if (size <= size_) {
size_ = size;
return;
}
buffer_->SetSize(size);
UnshareAndEnsureCapacity(std::max(capacity(), size));
buffer_->SetSize(size + offset_);
size_ = size;
RTC_DCHECK(IsConsistent());
}
void CopyOnWriteBuffer::EnsureCapacity(size_t capacity) {
void CopyOnWriteBuffer::EnsureCapacity(size_t new_capacity) {
RTC_DCHECK(IsConsistent());
if (!buffer_) {
if (capacity > 0) {
buffer_ = new RefCountedObject<Buffer>(0, capacity);
if (new_capacity > 0) {
buffer_ = new RefCountedObject<Buffer>(0, new_capacity);
offset_ = 0;
size_ = 0;
}
RTC_DCHECK(IsConsistent());
return;
} else if (capacity <= buffer_->capacity()) {
} else if (new_capacity <= capacity()) {
return;
}
CloneDataIfReferenced(std::max(buffer_->capacity(), capacity));
buffer_->EnsureCapacity(capacity);
UnshareAndEnsureCapacity(new_capacity);
RTC_DCHECK(IsConsistent());
}
@ -94,18 +105,21 @@ void CopyOnWriteBuffer::Clear() {
if (buffer_->HasOneRef()) {
buffer_->Clear();
} else {
buffer_ = new RefCountedObject<Buffer>(0, buffer_->capacity());
buffer_ = new RefCountedObject<Buffer>(0, capacity());
}
offset_ = 0;
size_ = 0;
RTC_DCHECK(IsConsistent());
}
void CopyOnWriteBuffer::CloneDataIfReferenced(size_t new_capacity) {
if (buffer_->HasOneRef()) {
void CopyOnWriteBuffer::UnshareAndEnsureCapacity(size_t new_capacity) {
if (buffer_->HasOneRef() && new_capacity <= capacity()) {
return;
}
buffer_ = new RefCountedObject<Buffer>(buffer_->data(), buffer_->size(),
buffer_ = new RefCountedObject<Buffer>(buffer_->data() + offset_, size_,
new_capacity);
offset_ = 0;
RTC_DCHECK(IsConsistent());
}