1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/tracing/core/scattered_stream_writer.h"
#include <string.h>
#include <algorithm>
#include "base/logging.h"
namespace tracing {
namespace v2 {
ScatteredStreamWriter::Delegate::~Delegate() {}
ScatteredStreamWriter::ScatteredStreamWriter(Delegate* delegate)
: delegate_(delegate),
cur_range_({nullptr, nullptr}),
write_ptr_(nullptr) {}
ScatteredStreamWriter::~ScatteredStreamWriter() {}
void ScatteredStreamWriter::Reset(ContiguousMemoryRange range) {
cur_range_ = range;
write_ptr_ = range.begin;
DCHECK_LT(write_ptr_, cur_range_.end);
}
void ScatteredStreamWriter::Extend() {
Reset(delegate_->GetNewBuffer());
}
void ScatteredStreamWriter::WriteByte(uint8_t value) {
if (write_ptr_ >= cur_range_.end)
Extend();
*write_ptr_++ = value;
}
void ScatteredStreamWriter::WriteBytes(const uint8_t* src, size_t size) {
uint8_t* const end = write_ptr_ + size;
if (end <= cur_range_.end) {
// Fast-path, the buffer fits into the current contiguous range.
// TODO(primiano): perf optimization, this is a tracing hot path. The
// compiler can make strong optimization on memcpy if the size arg is a
// constexpr. Make a templated variant of this for fixed-size writes.
memcpy(write_ptr_, src, size);
write_ptr_ = end;
return;
}
// Slow path, scatter the writes.
size_t bytes_left = size;
while (bytes_left > 0) {
if (write_ptr_ >= cur_range_.end)
Extend();
const size_t burst_size = std::min(bytes_available(), bytes_left);
WriteBytes(src, burst_size);
bytes_left -= burst_size;
src += burst_size;
}
}
// TODO(primiano): perf optimization: I suspect that at the end this will always
// be called with |size| == 4, in which case we might just hardcode it.
ContiguousMemoryRange ScatteredStreamWriter::ReserveBytes(size_t size) {
// Assume the reservations are always < kChunkSize.
if (write_ptr_ + size > cur_range_.end) {
Extend();
DCHECK_LE(write_ptr_ + size, cur_range_.end);
}
uint8_t* begin = write_ptr_;
write_ptr_ += size;
#ifndef NDEBUG
memset(begin, '\xFF', size);
#endif
return {begin, begin + size};
}
} // namespace v2
} // namespace tracing
|