1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_ 18 #define INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_ 19 20 #include <stddef.h> 21 #include <stdint.h> 22 23 #include <limits> 24 #include <memory> 25 26 #include "perfetto/base/logging.h" 27 #include "perfetto/trace_processor/ref_counted.h" 28 #include "perfetto/trace_processor/trace_blob.h" 29 30 namespace perfetto { 31 namespace trace_processor { 32 33 // A read-only view of a TraceBlob. 34 // This class is an equivalent of std::string_view for trace binary data, with 35 // a twist: it supports turning a TraceBlob into a refcounted reference. In this 36 // case the TraceBlobView acts directly as a shared_ptr, without requiring extra 37 // layers of indirection. 38 // The underlying TraceBlob will be freed once all the TraceBlobViews that refer 39 // to the same buffer have passed through the pipeline and been parsed. 40 // The overall idea is that a TraceBlob is passed around until it's written. 41 // When writing is done it transforms into a shared refcounted object which is 42 // held onto by one or more read-only TraceBlobView instances. 43 // 44 // In summary: 45 // - TraceBlob: writable, move-only, single-instance. 46 // - TraceBlobView: readable, copyable, multiple-instances can hold onto 47 // (different sub-slices of) the same refcounted TraceBlob. 48 class alignas(8) TraceBlobView { 49 public: 50 // Takes ownership of the passed |blob|. 51 static constexpr size_t kWholeBlob = std::numeric_limits<size_t>::max(); 52 explicit TraceBlobView(TraceBlob blob, 53 size_t offset = 0, 54 size_t length = kWholeBlob) { 55 PERFETTO_DCHECK(offset <= std::numeric_limits<uint32_t>::max()); 56 data_ = blob.data() + offset; 57 if (length == kWholeBlob) { 58 length_ = static_cast<uint32_t>(blob.size() - offset); 59 } else { 60 PERFETTO_DCHECK(length <= std::numeric_limits<uint32_t>::max()); 61 PERFETTO_DCHECK(offset + length_ <= blob.size()); 62 length_ = static_cast<uint32_t>(length); 63 } 64 blob_.reset(new TraceBlob(std::move(blob))); 65 } 66 TraceBlobView(RefPtr<TraceBlob> blob,size_t offset,uint32_t length)67 TraceBlobView(RefPtr<TraceBlob> blob, size_t offset, uint32_t length) 68 : blob_(std::move(blob)), data_(blob_->data() + offset), length_(length) { 69 PERFETTO_DCHECK(offset + length_ <= blob_->size()); 70 } 71 72 // Trivial empty ctor. TraceBlobView()73 TraceBlobView() : data_(nullptr), length_(0) {} 74 75 ~TraceBlobView() = default; 76 77 // Allow std::move(). TraceBlobView(TraceBlobView && other)78 TraceBlobView(TraceBlobView&& other) noexcept { *this = std::move(other); } 79 80 TraceBlobView& operator=(TraceBlobView&& other) noexcept { 81 data_ = other.data_; 82 length_ = other.length_; 83 blob_ = std::move(other.blob_); 84 return *this; 85 } 86 87 // Disable copy operators. Use x.Copy() to get a copy. 88 TraceBlobView(const TraceBlobView&) = delete; 89 TraceBlobView& operator=(const TraceBlobView&) = delete; 90 91 // [data, data+length] must be <= the current TraceBlobView. slice(const uint8_t * data,size_t length)92 TraceBlobView slice(const uint8_t* data, size_t length) const { 93 PERFETTO_DCHECK(data >= data_); 94 PERFETTO_DCHECK(data + length <= data_ + length_); 95 return TraceBlobView(blob_, data, static_cast<uint32_t>(length)); 96 } 97 98 // Like slice() but takes an offset rather than a pointer as 1st argument. slice_off(size_t off,size_t length)99 TraceBlobView slice_off(size_t off, size_t length) const { 100 PERFETTO_DCHECK(off + length <= length_); 101 return TraceBlobView(blob_, data_ + off, static_cast<uint32_t>(length)); 102 } 103 copy()104 TraceBlobView copy() const { return slice(data_, length_); } 105 106 bool operator==(const TraceBlobView& rhs) const { 107 return (data_ == rhs.data_) && (length_ == rhs.length_) && 108 (blob_ == rhs.blob_); 109 } 110 bool operator!=(const TraceBlobView& rhs) const { return !(*this == rhs); } 111 data()112 const uint8_t* data() const { return data_; } offset()113 size_t offset() const { return static_cast<size_t>(data_ - blob_->data()); } length()114 size_t length() const { return length_; } size()115 size_t size() const { return length_; } blob()116 RefPtr<TraceBlob> blob() const { return blob_; } 117 118 private: TraceBlobView(RefPtr<TraceBlob> blob,const uint8_t * data,uint32_t length)119 TraceBlobView(RefPtr<TraceBlob> blob, const uint8_t* data, uint32_t length) 120 : blob_(std::move(blob)), data_(data), length_(length) {} 121 122 RefPtr<TraceBlob> blob_; 123 const uint8_t* data_ = nullptr; 124 uint32_t length_ = 0; 125 }; 126 127 } // namespace trace_processor 128 } // namespace perfetto 129 130 #endif // INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_BLOB_VIEW_H_ 131