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.
COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE)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