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