Index: components/tracing/core/scattered_stream_writer.cc |
diff --git a/components/tracing/core/scattered_stream_writer.cc b/components/tracing/core/scattered_stream_writer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..73e2a36ae20ebf7e829555caecb2951e17f8b6c1 |
--- /dev/null |
+++ b/components/tracing/core/scattered_stream_writer.cc |
@@ -0,0 +1,79 @@ |
+// 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::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 < TraceRingBuffer::Chunk::kSize. |
+ 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 |