blob: 5bc28c910ad4295b89afc8c72e5f660672f3fae7 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include "base/macros.h"
#include "mojo/public/cpp/bindings/bindings_export.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/message.h"
namespace mojo {
namespace internal {
// Buffer provides an interface to allocate memory blocks which are 8-byte
// aligned. It doesn't own the underlying memory. Users must ensure that the
// memory stays valid while using the allocated blocks from Buffer.
// A Buffer may be moved around. A moved-from Buffer is reset and may no longer
// be used to Allocate memory unless re-Initialized.
// Constructs an invalid Buffer. May not call Allocate().
// Constructs a Buffer which can Allocate() blocks from a buffer of fixed size
// |size| at |data|. Allocations start at |cursor|, so if |cursor| == |size|
// then no allocations are allowed.
// |data| is not owned.
Buffer(void* data, size_t size, size_t cursor);
// Like above, but gives the Buffer an underlying message object which can
// have its payload extended to acquire more storage capacity on Allocate().
// |data| and |size| must correspond to |message|'s serialized buffer contents
// at the time of construction.
// |message| is NOT owned and must outlive this Buffer.
Buffer(MessageHandle message, void* data, size_t size);
Buffer(Buffer&& other);
Buffer& operator=(Buffer&& other);
void* data() const { return data_; }
size_t size() const { return size_; }
size_t cursor() const { return cursor_; }
bool is_valid() const {
return data_ != nullptr || (size_ == 0 && !message_.is_valid());
// Allocates |num_bytes| from the buffer and returns an index to the start of
// the allocated block. The resulting index is 8-byte aligned and can be
// resolved to an address using Get<T>() below.
size_t Allocate(size_t num_bytes);
// Returns a typed address within the Buffer corresponding to |index|. Note
// that this address is NOT stable across calls to |Allocate()| and thus must
// not be cached accordingly.
template <typename T>
T* Get(size_t index) {
DCHECK_LT(index, cursor_);
return reinterpret_cast<T*>(static_cast<uint8_t*>(data_) + index);
// A template helper combining Allocate() and Get<T>() above to allocate and
// return a block of size |sizeof(T)|.
template <typename T>
T* AllocateAndGet() {
return Get<T>(Allocate(sizeof(T)));
// A helper which combines Allocate() and Get<void>() for a specified number
// of bytes.
void* AllocateAndGet(size_t num_bytes) {
return Get<void>(Allocate(num_bytes));
// Serializes |handles| into the buffer object. Only valid to call when this
// Buffer is backed by a message object.
void AttachHandles(std::vector<ScopedHandle>* handles);
// Seals this Buffer so it can no longer be used for allocation, and ensures
// the backing message object has a complete accounting of the size of the
// meaningful payload bytes.
void Seal();
// Resets the buffer to an invalid state. Can no longer be used to Allocate().
void Reset();
MessageHandle message_;
void* data_ = nullptr;
size_t size_ = 0;
size_t cursor_ = 0;
} // namespace internal
} // namespace mojo