• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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