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_BINDINGS_LIB_BUFFER_H_
      6 #define MOJO_PUBLIC_BINDINGS_LIB_BUFFER_H_
      7 
      8 #include <stddef.h>
      9 
     10 #include <deque>
     11 
     12 #include "mojo/public/system/macros.h"
     13 
     14 namespace mojo {
     15 
     16 // Buffer provides a way to allocate memory. Allocations are 8-byte aligned and
     17 // zero-initialized. Allocations remain valid for the lifetime of the Buffer.
     18 class Buffer {
     19  public:
     20   typedef void (*Destructor)(void* address);
     21 
     22   Buffer();
     23   virtual ~Buffer();
     24 
     25   virtual void* Allocate(size_t num_bytes, Destructor func = NULL) = 0;
     26 
     27   static Buffer* current();
     28 
     29  private:
     30   Buffer* previous_;
     31 };
     32 
     33 namespace internal {
     34 
     35 // The following class is designed to be allocated on the stack.  If necessary,
     36 // it will failover to allocating objects on the heap.
     37 class ScratchBuffer : public Buffer {
     38  public:
     39   ScratchBuffer();
     40   virtual ~ScratchBuffer();
     41 
     42   virtual void* Allocate(size_t num_bytes, Destructor func = NULL)
     43       MOJO_OVERRIDE;
     44 
     45  private:
     46   enum { kMinSegmentSize = 512 };
     47 
     48   struct Segment {
     49     Segment* next;
     50     char* cursor;
     51     char* end;
     52   };
     53 
     54   void* AllocateInSegment(Segment* segment, size_t num_bytes);
     55   void AddOverflowSegment(size_t delta);
     56 
     57   char fixed_data_[kMinSegmentSize];
     58   Segment fixed_;
     59   Segment* overflow_;
     60 
     61   struct PendingDestructor {
     62     Destructor func;
     63     void* address;
     64   };
     65   std::deque<PendingDestructor> pending_dtors_;
     66 
     67   MOJO_DISALLOW_COPY_AND_ASSIGN(ScratchBuffer);
     68 };
     69 
     70 // FixedBuffer provides a simple way to allocate objects within a fixed chunk
     71 // of memory. Objects are allocated by calling the |Allocate| method, which
     72 // extends the buffer accordingly. Objects allocated in this way are not freed
     73 // explicitly. Instead, they remain valid so long as the FixedBuffer remains
     74 // valid.  The Leak method may be used to steal the underlying memory from the
     75 // FixedBuffer.
     76 //
     77 // Typical usage:
     78 //
     79 //   {
     80 //     FixedBuffer buf(8 + 8);
     81 //
     82 //     int* a = static_cast<int*>(buf->Allocate(sizeof(int)));
     83 //     *a = 2;
     84 //
     85 //     double* b = static_cast<double*>(buf->Allocate(sizeof(double)));
     86 //     *b = 3.14f;
     87 //
     88 //     void* data = buf.Leak();
     89 //     Process(data);
     90 //
     91 //     free(data);
     92 //   }
     93 //
     94 class FixedBuffer : public Buffer {
     95  public:
     96   explicit FixedBuffer(size_t size);
     97   virtual ~FixedBuffer();
     98 
     99   // Grows the buffer by |num_bytes| and returns a pointer to the start of the
    100   // addition. The resulting address is 8-byte aligned, and the content of the
    101   // memory is zero-filled.
    102   virtual void* Allocate(size_t num_bytes, Destructor func = NULL)
    103       MOJO_OVERRIDE;
    104 
    105   size_t size() const { return size_; }
    106 
    107   // Returns the internal memory owned by the Buffer to the caller. The Buffer
    108   // relinquishes its pointer, effectively resetting the state of the Buffer
    109   // and leaving the caller responsible for freeing the returned memory address
    110   // when no longer needed.
    111   void* Leak();
    112 
    113  private:
    114   char* ptr_;
    115   size_t cursor_;
    116   size_t size_;
    117 
    118   MOJO_DISALLOW_COPY_AND_ASSIGN(FixedBuffer);
    119 };
    120 
    121 }  // namespace internal
    122 
    123 class AllocationScope {
    124  public:
    125   AllocationScope() {}
    126   ~AllocationScope() {}
    127 
    128   Buffer* buffer() { return &buffer_; }
    129 
    130  private:
    131   internal::ScratchBuffer buffer_;
    132 
    133   MOJO_DISALLOW_COPY_AND_ASSIGN(AllocationScope);
    134 };
    135 
    136 }  // namespace mojo
    137 
    138 #endif  // MOJO_PUBLIC_BINDINGS_LIB_BUFFER_H_
    139