Android-cuttlefish cvd tool
types.h
Go to the documentation of this file.
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#pragma once
18
19#include <string.h>
20
21#include <algorithm>
22#include <memory>
23#include <string>
24#include <type_traits>
25#include <utility>
26#include <vector>
27
29
30#include "fdevent/fdevent.h"
31#include "sysdeps/uio.h"
32
33// Essentially std::vector<char>, except without zero initialization or reallocation.
34// Features a position attribute to allow sequential read/writes for copying between Blocks.
35struct Block {
36 using iterator = char*;
37
38 Block() = default;
39
40 explicit Block(size_t size) { allocate(size); }
41
42 explicit Block(const std::string& s) : Block(s.begin(), s.end()) {}
43
44 template <typename Iterator>
46 std::copy(begin, end, data_.get());
47 }
48
49 Block(const Block& copy) = delete;
50 Block(Block&& move) noexcept
51 : data_(std::exchange(move.data_, nullptr)),
52 capacity_(std::exchange(move.capacity_, 0)),
53 size_(std::exchange(move.size_, 0)),
54 position_(std::exchange(move.position_, 0)) {}
55
56 Block& operator=(const Block& copy) = delete;
57 Block& operator=(Block&& move) noexcept {
58 clear();
59 data_ = std::exchange(move.data_, nullptr);
60 capacity_ = std::exchange(move.capacity_, 0);
61 size_ = std::exchange(move.size_, 0);
62 position_ = std::exchange(move.size_, 0);
63 return *this;
64 }
65
66 ~Block() = default;
67
68 void resize(size_t new_size) {
69 if (!data_) {
70 allocate(new_size);
71 } else {
72 CHECK_GE(capacity_, new_size);
73 size_ = new_size;
74 }
75 }
76
77 template <typename InputIt>
78 void assign(InputIt begin, InputIt end) {
79 clear();
81 std::copy(begin, end, data_.get());
82 }
83
84 void clear() {
85 data_.reset();
86 capacity_ = 0;
87 size_ = 0;
88 position_ = 0;
89 }
90
91 bool is_full() const { return remaining() == 0; }
92
93 size_t remaining() const { return size_ - position_; }
94
95 size_t fillFrom(Block& from) {
96 size_t size = std::min(remaining(), from.remaining());
97 memcpy(&data_[position_], &from.data_[from.position_], size);
98 position_ += size;
99 from.position_ += size;
100 return size;
101 }
102
103 void rewind() { position_ = 0; }
104 size_t position() const { return position_; }
105
106 size_t capacity() const { return capacity_; }
107 size_t size() const { return size_; }
108 bool empty() const { return size() == 0; }
109
110 char* data() { return data_.get(); }
111 const char* data() const { return data_.get(); }
112
113 char* begin() { return data_.get(); }
114 const char* begin() const { return data_.get(); }
115
116 char* end() { return data() + size_; }
117 const char* end() const { return data() + size_; }
118
119 char& operator[](size_t idx) { return data()[idx]; }
120 const char& operator[](size_t idx) const { return data()[idx]; }
121
122 bool operator==(const Block& rhs) const {
123 static_assert(std::is_standard_layout<decltype(data())>());
124 return size() == rhs.size() && memcmp(data(), rhs.data(), size()) == 0;
125 }
126
127 private:
128 void allocate(size_t size) {
129 CHECK(data_ == nullptr);
130 CHECK_EQ(0ULL, capacity_);
131 CHECK_EQ(0ULL, size_);
132 if (size != 0) {
133 // This isn't std::make_unique because that's equivalent to `new char[size]()`, which
134 // value-initializes the array instead of leaving it uninitialized. As an optimization,
135 // call new without parentheses to avoid this costly initialization.
136 data_.reset(new char[size]);
137 capacity_ = size;
138 size_ = size;
139 }
140 }
141
142 std::unique_ptr<char[]> data_;
143 size_t capacity_ = 0;
144 size_t size_ = 0;
145 size_t position_ = 0;
146};
147
148struct amessage {
149 uint32_t command; /* command identifier constant */
150 uint32_t arg0; /* first argument */
151 uint32_t arg1; /* second argument */
152 uint32_t data_length; /* length of payload (0 is allowed) */
153 uint32_t data_check; /* checksum of data payload */
154 uint32_t magic; /* command ^ 0xffffffff */
155};
156
157struct apacket {
161};
162
163struct IOVector {
164 using value_type = char;
166 using size_type = size_t;
167
168 IOVector() = default;
169
170 explicit IOVector(block_type&& block) { append(std::move(block)); }
171
172 IOVector(const IOVector& copy) = delete;
173 IOVector(IOVector&& move) noexcept : IOVector() { *this = std::move(move); }
174
175 IOVector& operator=(const IOVector& copy) = delete;
176 IOVector& operator=(IOVector&& move) noexcept;
177
178 const value_type* front_data() const {
179 if (chain_.empty()) {
180 return nullptr;
181 }
182
183 return chain_[start_index_].data() + begin_offset_;
184 }
185
187 if (chain_.empty()) {
188 return 0;
189 }
190
191 return chain_[start_index_].size() - begin_offset_;
192 }
193
195 bool empty() const { return size() == 0; }
196
197 // Return the last block so the caller can still reuse its allocated capacity
198 // or it can be simply ignored.
200
201 void drop_front(size_type len);
202
203 // Split the first |len| bytes out of this chain into its own.
205
206 // Add a nonempty block to the chain.
207 void append(block_type&& block) {
208 if (block.size() == 0) {
209 return;
210 }
211 CHECK_NE(0ULL, block.size());
212 chain_length_ += block.size();
213 chain_.emplace_back(std::move(block));
214 }
215
216 void trim_front();
217
218 private:
219 void trim_chain_front();
220
221 // Drop the front block from the chain, and update chain_length_ appropriately.
222 void pop_front_block();
223
224 // Iterate over the blocks with a callback with an operator()(const char*, size_t).
225 template <typename Fn>
226 void iterate_blocks(Fn&& callback) const {
227 if (size() == 0) {
228 return;
229 }
230
231 for (size_t i = start_index_; i < chain_.size(); ++i) {
232 const auto& block = chain_[i];
233 const char* begin = block.data();
234 size_t length = block.size();
235
236 if (i == start_index_) {
237 CHECK_GE(block.size(), begin_offset_);
238 begin += begin_offset_;
239 length -= begin_offset_;
240 }
241 callback(begin, length);
242 }
243 }
244
245 public:
246 // Copy all of the blocks into a single block.
247 template <typename CollectionType = block_type>
248 CollectionType coalesce() const& {
249 CollectionType result;
250 if (size() == 0) {
251 return result;
252 }
253
254 result.resize(size());
255
256 size_t offset = 0;
257 iterate_blocks([&offset, &result](const char* data, size_t len) {
258 static_assert(std::is_standard_layout<decltype(result)>());
259 memcpy(&result[offset], data, len);
260 offset += len;
261 });
262
263 return result;
264 }
265
266 block_type coalesce() &&;
267
268 template <typename FunctionType>
269 auto coalesced(FunctionType&& f) const {
270 if (chain_.size() == start_index_ + 1) {
271 // If we only have one block, we can use it directly.
272 return f(chain_[start_index_].data() + begin_offset_, size());
273 } else {
274 // Otherwise, copy to a single block.
275 auto data = coalesce();
276 return f(data.data(), data.size());
277 }
278 }
279
280 // Get a list of iovecs that can be used to write out all of the blocks.
281 std::vector<adb_iovec> iovecs() const;
282
283 private:
284 // Total length of all of the blocks in the chain.
285 size_t chain_length_ = 0;
286
287 size_t begin_offset_ = 0;
288 size_t start_index_ = 0;
289 std::vector<block_type> chain_;
290};
291
292// An implementation of weak pointers tied to the fdevent run loop.
293//
294// This allows for code to submit a request for an object, and upon receiving
295// a response, know whether the object is still alive, or has been destroyed
296// because of other reasons. We keep a list of living weak_ptrs in each object,
297// and clear the weak_ptrs when the object is destroyed. This is safe, because
298// we require that both the destructor of the referent and the get method on
299// the weak_ptr are executed on the main thread.
300template <typename T>
302
303template <typename T>
304struct weak_ptr {
305 weak_ptr() = default;
306 explicit weak_ptr(T* ptr) { reset(ptr); }
307 weak_ptr(const weak_ptr& copy) { reset(copy.get()); }
308
310 reset(move.get());
311 move.reset();
312 }
313
315
317 if (&copy == this) {
318 return *this;
319 }
320
321 reset(copy.get());
322 return *this;
323 }
324
326 if (&move == this) {
327 return *this;
328 }
329
330 reset(move.get());
331 move.reset();
332 return *this;
333 }
334
335 T* get() const {
337 return ptr_;
338 }
339
340 void reset(T* ptr = nullptr) {
342
343 if (ptr == ptr_) {
344 return;
345 }
346
347 if (ptr_) {
348 ptr_->weak_ptrs_.erase(
349 std::remove(ptr_->weak_ptrs_.begin(), ptr_->weak_ptrs_.end(), this));
350 }
351
352 ptr_ = ptr;
353 if (ptr_) {
354 ptr_->weak_ptrs_.push_back(this);
355 }
356 }
357
358 private:
359 friend struct enable_weak_from_this<T>;
360 T* ptr_ = nullptr;
361};
362
363template <typename T>
366 if (!weak_ptrs_.empty()) {
368 for (auto& weak : weak_ptrs_) {
369 weak->ptr_ = nullptr;
370 }
371 weak_ptrs_.clear();
372 }
373 }
374
375 weak_ptr<T> weak() { return weak_ptr<T>(static_cast<T*>(this)); }
376
378 fdevent_run_on_looper([this]() { delete static_cast<T*>(this); });
379 }
380
381 private:
382 friend struct weak_ptr<T>;
383 std::vector<weak_ptr<T>*> weak_ptrs_;
384};
#define min(a, b)
Definition: ext4_utils.h:44
void fdevent_run_on_looper(std::function< void()> fn)
Definition: fdevent.cpp:260
void fdevent_check_looper()
Definition: fdevent.cpp:268
char data[Size]
Definition: incremental_server.cpp:1
#define CHECK_EQ(x, y)
Definition: logging.h:280
#define CHECK(x)
Definition: logging.h:251
#define CHECK_GE(x, y)
Definition: logging.h:284
#define CHECK_NE(x, y)
Definition: logging.h:281
std::set< Range >::iterator Iterator
Definition: disjoint_range_set.cc:64
Definition: types.h:35
size_t capacity() const
Definition: types.h:106
const char * begin() const
Definition: types.h:114
char * end()
Definition: types.h:116
~Block()=default
size_t remaining() const
Definition: types.h:93
bool is_full() const
Definition: types.h:91
const char & operator[](size_t idx) const
Definition: types.h:120
size_t fillFrom(Block &from)
Definition: types.h:95
char * iterator
Definition: types.h:36
char & operator[](size_t idx)
Definition: types.h:119
void rewind()
Definition: types.h:103
size_t size_
Definition: types.h:144
Block & operator=(const Block &copy)=delete
void assign(InputIt begin, InputIt end)
Definition: types.h:78
size_t position() const
Definition: types.h:104
Block(const Block &copy)=delete
Block()=default
void resize(size_t new_size)
Definition: types.h:68
size_t size() const
Definition: types.h:107
Block(size_t size)
Definition: types.h:40
size_t capacity_
Definition: types.h:143
Block & operator=(Block &&move) noexcept
Definition: types.h:57
void allocate(size_t size)
Definition: types.h:128
char * data()
Definition: types.h:110
void clear()
Definition: types.h:84
Block(Block &&move) noexcept
Definition: types.h:50
Block(Iterator begin, Iterator end)
Definition: types.h:45
size_t position_
Definition: types.h:145
char * begin()
Definition: types.h:113
const char * end() const
Definition: types.h:117
const char * data() const
Definition: types.h:111
bool empty() const
Definition: types.h:108
bool operator==(const Block &rhs) const
Definition: types.h:122
std::unique_ptr< char[]> data_
Definition: types.h:142
Block(const std::string &s)
Definition: types.h:42
Definition: types.h:163
void append(block_type &&block)
Definition: types.h:207
std::vector< adb_iovec > iovecs() const
Definition: types.cpp:193
IOVector(block_type &&block)
Definition: types.h:170
size_type front_size() const
Definition: types.h:186
void trim_chain_front()
Definition: types.cpp:131
size_t chain_length_
Definition: types.h:285
IOVector & operator=(const IOVector &copy)=delete
void pop_front_block()
Definition: types.cpp:138
void trim_front()
Definition: types.cpp:114
void drop_front(size_type len)
Definition: types.cpp:41
IOVector(const IOVector &copy)=delete
size_t start_index_
Definition: types.h:288
size_type size() const
Definition: types.h:194
size_t begin_offset_
Definition: types.h:287
IOVector(IOVector &&move) noexcept
Definition: types.h:173
IOVector()=default
auto coalesced(FunctionType &&f) const
Definition: types.h:269
IOVector take_front(size_type len)
Definition: types.cpp:65
std::vector< block_type > chain_
Definition: types.h:289
bool empty() const
Definition: types.h:195
Block block_type
Definition: types.h:165
char value_type
Definition: types.h:164
const value_type * front_data() const
Definition: types.h:178
size_t size_type
Definition: types.h:166
block_type clear()
Definition: types.cpp:29
CollectionType coalesce() const &
Definition: types.h:248
void iterate_blocks(Fn &&callback) const
Definition: types.h:226
Definition: types.h:148
uint32_t magic
Definition: types.h:154
uint32_t data_check
Definition: types.h:153
uint32_t arg1
Definition: types.h:151
uint32_t data_length
Definition: types.h:152
uint32_t arg0
Definition: types.h:150
uint32_t command
Definition: types.h:149
Definition: types.h:157
amessage msg
Definition: types.h:159
payload_type payload
Definition: types.h:160
Definition: types.h:364
std::vector< weak_ptr< T > * > weak_ptrs_
Definition: types.h:383
void schedule_deletion()
Definition: types.h:377
~enable_weak_from_this()
Definition: types.h:365
friend struct weak_ptr< T >
Definition: types.h:382
weak_ptr< T > weak()
Definition: types.h:375
Definition: types.h:304
weak_ptr & operator=(weak_ptr &&move)
Definition: types.h:325
weak_ptr & operator=(const weak_ptr &copy)
Definition: types.h:316
T * ptr_
Definition: types.h:360
~weak_ptr()
Definition: types.h:314
void reset(T *ptr=nullptr)
Definition: types.h:340
weak_ptr(weak_ptr &&move)
Definition: types.h:309
weak_ptr(T *ptr)
Definition: types.h:306
weak_ptr()=default
T * get() const
Definition: types.h:335
weak_ptr(const weak_ptr &copy)
Definition: types.h:307