Home | History | Annotate | Download | only in lib
      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