1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <vector> 12 13 #include "base/component_export.h" 14 #include "base/macros.h" 15 #include "mojo/public/cpp/system/handle.h" 16 #include "mojo/public/cpp/system/message.h" 17 18 namespace mojo { 19 namespace internal { 20 21 // Buffer provides an interface to allocate memory blocks which are 8-byte 22 // aligned. It doesn't own the underlying memory. Users must ensure that the 23 // memory stays valid while using the allocated blocks from Buffer. 24 // 25 // A Buffer may be moved around. A moved-from Buffer is reset and may no longer 26 // be used to Allocate memory unless re-Initialized. 27 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) Buffer { 28 public: 29 // Constructs an invalid Buffer. May not call Allocate(). 30 Buffer(); 31 32 // Constructs a Buffer which can Allocate() blocks from a buffer of fixed size 33 // |size| at |data|. Allocations start at |cursor|, so if |cursor| == |size| 34 // then no allocations are allowed. 35 // 36 // |data| is not owned. 37 Buffer(void* data, size_t size, size_t cursor); 38 39 // Like above, but gives the Buffer an underlying message object which can 40 // have its payload extended to acquire more storage capacity on Allocate(). 41 // 42 // |data| and |size| must correspond to |message|'s data buffer at the time of 43 // construction. 44 // 45 // |payload_size| is the length of the payload as known by |message|, and it 46 // must be less than or equal to |size|. 47 // 48 // |message| is NOT owned and must outlive this Buffer. 49 Buffer(MessageHandle message, 50 size_t message_payload_size, 51 void* data, 52 size_t size); 53 54 Buffer(Buffer&& other); 55 ~Buffer(); 56 57 Buffer& operator=(Buffer&& other); 58 59 void* data() const { return data_; } 60 size_t size() const { return size_; } 61 size_t cursor() const { return cursor_; } 62 63 bool is_valid() const { 64 return data_ != nullptr || (size_ == 0 && !message_.is_valid()); 65 } 66 67 // Allocates |num_bytes| from the buffer and returns an index to the start of 68 // the allocated block. The resulting index is 8-byte aligned and can be 69 // resolved to an address using Get<T>() below. 70 size_t Allocate(size_t num_bytes); 71 72 // Returns a typed address within the Buffer corresponding to |index|. Note 73 // that this address is NOT stable across calls to |Allocate()| and thus must 74 // not be cached accordingly. 75 template <typename T> 76 T* Get(size_t index) { 77 DCHECK_LT(index, cursor_); 78 return reinterpret_cast<T*>(static_cast<uint8_t*>(data_) + index); 79 } 80 81 // A template helper combining Allocate() and Get<T>() above to allocate and 82 // return a block of size |sizeof(T)|. 83 template <typename T> 84 T* AllocateAndGet() { 85 return Get<T>(Allocate(sizeof(T))); 86 } 87 88 // A helper which combines Allocate() and Get<void>() for a specified number 89 // of bytes. 90 void* AllocateAndGet(size_t num_bytes) { 91 return Get<void>(Allocate(num_bytes)); 92 } 93 94 // Serializes |handles| into the buffer object. Only valid to call when this 95 // Buffer is backed by a message object. 96 void AttachHandles(std::vector<ScopedHandle>* handles); 97 98 // Seals this Buffer so it can no longer be used for allocation, and ensures 99 // the backing message object has a complete accounting of the size of the 100 // meaningful payload bytes. 101 void Seal(); 102 103 // Resets the buffer to an invalid state. Can no longer be used to Allocate(). 104 void Reset(); 105 106 private: 107 MessageHandle message_; 108 109 // The payload size from the message's internal perspective. This differs from 110 // |size_| as Mojo may intentionally over-allocate space to account for future 111 // growth. It differs from |cursor_| because we don't push payload size 112 // updates to the message object as frequently as we update |cursor_|, for 113 // performance. 114 size_t message_payload_size_ = 0; 115 116 // The storage location and capacity currently backing |message_|. Owned by 117 // the message object internally, not by this Buffer. 118 void* data_ = nullptr; 119 size_t size_ = 0; 120 121 // The current write offset into |data_| if this Buffer is being used for 122 // message creation. 123 size_t cursor_ = 0; 124 125 DISALLOW_COPY_AND_ASSIGN(Buffer); 126 }; 127 128 } // namespace internal 129 } // namespace mojo 130 131 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_BUFFER_H_ 132