• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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_BASE_BIG_BUFFER_H_
6 #define MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_H_
7 
8 #include <cstdint>
9 #include <vector>
10 
11 #include "base/component_export.h"
12 #include "base/containers/span.h"
13 #include "base/macros.h"
14 #include "base/optional.h"
15 #include "mojo/public/cpp/bindings/struct_traits.h"
16 #include "mojo/public/cpp/system/buffer.h"
17 
18 namespace mojo_base {
19 
20 class BigBuffer;
21 class BigBufferView;
22 
23 namespace internal {
24 
25 // Internal helper used by BigBuffer when backed by shared memory.
COMPONENT_EXPORT(MOJO_BASE)26 class COMPONENT_EXPORT(MOJO_BASE) BigBufferSharedMemoryRegion {
27  public:
28   BigBufferSharedMemoryRegion();
29   BigBufferSharedMemoryRegion(mojo::ScopedSharedBufferHandle buffer_handle,
30                               size_t size);
31   BigBufferSharedMemoryRegion(BigBufferSharedMemoryRegion&& other);
32   ~BigBufferSharedMemoryRegion();
33 
34   BigBufferSharedMemoryRegion& operator=(BigBufferSharedMemoryRegion&& other);
35 
36   void* memory() const { return buffer_mapping_.get(); }
37 
38   size_t size() const { return size_; }
39   mojo::ScopedSharedBufferHandle TakeBufferHandle();
40 
41  private:
42   friend class mojo_base::BigBuffer;
43   friend class mojo_base::BigBufferView;
44 
45   size_t size_;
46   mojo::ScopedSharedBufferHandle buffer_handle_;
47   mojo::ScopedSharedBufferMapping buffer_mapping_;
48 
49   DISALLOW_COPY_AND_ASSIGN(BigBufferSharedMemoryRegion);
50 };
51 
52 }  // namespace internal
53 
54 // BigBuffer represents a potentially large sequence of bytes. When passed over
55 // mojom (as a mojo_base::mojom::BigBuffer union), it may serialize as either an
56 // inlined array of bytes or as a shared buffer handle with the payload copied
57 // into the corresponding shared memory region. This makes it easier to send
58 // payloads of varying and unbounded size over IPC without fear of hitting
59 // message size limits.
60 //
61 // A BigBuffer may be (implicitly) constructed over any span of bytes, and it
62 // exposes simple |data()| and |size()| accessors akin to what common container
63 // types provide. Users do not need to be concerned with the actual backing
64 // storage used to implement this interface.
COMPONENT_EXPORT(MOJO_BASE)65 class COMPONENT_EXPORT(MOJO_BASE) BigBuffer {
66  public:
67   static constexpr size_t kMaxInlineBytes = 64 * 1024;
68 
69   enum class StorageType {
70     kBytes,
71     kSharedMemory,
72   };
73 
74   // Defaults to empty vector storage.
75   BigBuffer();
76   BigBuffer(BigBuffer&& other);
77 
78   // Constructs a BigBuffer over an existing span of bytes. Intentionally
79   // implicit for convenience. Always copies the contents of |data| into some
80   // internal storage.
81   BigBuffer(base::span<const uint8_t> data);
82 
83   // Helper for implicit conversion from byte vectors.
84   BigBuffer(const std::vector<uint8_t>& data);
85 
86   // Constructs a BigBuffer from an existing shared memory region. Not intended
87   // for general-purpose use.
88   explicit BigBuffer(internal::BigBufferSharedMemoryRegion shared_memory);
89 
90   ~BigBuffer();
91 
92   BigBuffer& operator=(BigBuffer&& other);
93 
94   // Returns a pointer to the data stored by this BigBuffer, regardless of
95   // backing storage type.
96   uint8_t* data();
97   const uint8_t* data() const;
98 
99   // Returns the size of the data stored by this BigBuffer, regardless of
100   // backing storage type.
101   size_t size() const;
102 
103   StorageType storage_type() const { return storage_type_; }
104 
105   const std::vector<uint8_t>& bytes() const {
106     DCHECK_EQ(storage_type_, StorageType::kBytes);
107     return bytes_;
108   }
109 
110   internal::BigBufferSharedMemoryRegion& shared_memory() {
111     DCHECK_EQ(storage_type_, StorageType::kSharedMemory);
112     return shared_memory_.value();
113   }
114 
115  private:
116   friend class BigBufferView;
117 
118   StorageType storage_type_;
119   std::vector<uint8_t> bytes_;
120   base::Optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
121 
122   DISALLOW_COPY_AND_ASSIGN(BigBuffer);
123 };
124 
125 // Similar to BigBuffer, but doesn't *necessarily* own the buffer storage.
126 // Namely, if constructed over a small enough span of memory, it will simply
127 // retain a reference to that memory. This is generally only safe to use for
128 // serialization and deserialization.
COMPONENT_EXPORT(MOJO_BASE)129 class COMPONENT_EXPORT(MOJO_BASE) BigBufferView {
130  public:
131   BigBufferView();
132   BigBufferView(BigBufferView&& other);
133 
134   // Constructs a BigBufferView over |bytes|. If |bytes| is large enough, this
135   // will allocate shared memory and copy the contents there. Otherwise this
136   // will retain an unsafe reference to |bytes| and must therefore not outlive
137   // |bytes|.
138   explicit BigBufferView(base::span<const uint8_t> bytes);
139   ~BigBufferView();
140 
141   BigBufferView& operator=(BigBufferView&& other);
142 
143   base::span<const uint8_t> data() const;
144 
145   // Explicitly retains a reference to |bytes| as the backing storage for this
146   // view. Does not copy and therefore |bytes| must remain valid throughout the
147   // view's lifetime. Used for deserialization.
148   void SetBytes(base::span<const uint8_t> bytes);
149 
150   // Explictly adopts |shared_memory| as the backing storage for this view. Used
151   // for deserialization.
152   void SetSharedMemory(internal::BigBufferSharedMemoryRegion shared_memory);
153 
154   // Converts to a BigBuffer which owns the viewed data. May have to copy data.
155   static BigBuffer ToBigBuffer(BigBufferView view) WARN_UNUSED_RESULT;
156 
157   BigBuffer::StorageType storage_type() const { return storage_type_; }
158 
159   base::span<const uint8_t> bytes() const {
160     DCHECK_EQ(storage_type_, BigBuffer::StorageType::kBytes);
161     return bytes_;
162   }
163 
164   internal::BigBufferSharedMemoryRegion& shared_memory() {
165     DCHECK_EQ(storage_type_, BigBuffer::StorageType::kSharedMemory);
166     return shared_memory_.value();
167   }
168 
169  private:
170   BigBuffer::StorageType storage_type_;
171   base::span<const uint8_t> bytes_;
172   base::Optional<internal::BigBufferSharedMemoryRegion> shared_memory_;
173 
174   DISALLOW_COPY_AND_ASSIGN(BigBufferView);
175 };
176 
177 }  // namespace mojo_base
178 
179 #endif  // MOJO_PUBLIC_CPP_BASE_BIG_BUFFER_H_
180