Advertisement
Guest User

Untitled

a guest
Mar 29th, 2015
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.15 KB | None | 0 0
  1. struct C_Arena
  2. {
  3. struct Header header;
  4. size_t size;
  5. size_t used;
  6. char* data[];
  7. };
  8. ...
  9. struct C_Arena *arena = malloc(1000);
  10. arena->size = 1000 - sizeof(struct C_flexible_array_struct));
  11. arena->used = 0;
  12. struct Header *header = &arena->header;
  13. ...
  14.  
  15. auto arena = Chunk<Header>(new char[1000], 1000);
  16. Header *header = arena.Get<Header>();
  17. ...
  18.  
  19. // Round down to a power of two multiple.
  20. constexpr std::size_t Align(std::size_t n, std::size_t a) {
  21. return n & ~(a - 1);
  22. }
  23.  
  24. // Round up to a power of two multiple.
  25. constexpr std::size_t AlignUp(std::size_t n, std::size_t a) {
  26. return Align(n + a - 1, a);
  27. }
  28.  
  29. namespace memory {
  30. namespace detail {
  31.  
  32. // Calculate a data item alignment according to its size.
  33. constexpr std::size_t Align(std::size_t size, std::size_t offset) {
  34. return size < 0x08 ? ::AlignUp(offset, 0x04)
  35. : size < 0x10 ? ::AlignUp(offset, 0x08)
  36. : ::AlignUp(offset, 0x10);
  37. }
  38.  
  39. // Services for placement of a given type instance within a memory chunk
  40. // at the specified offset.
  41. template <typename T, std::size_t S> class EntryLayout {
  42. public:
  43. using Type = T;
  44. using Pointer = T *;
  45.  
  46. static constexpr std::size_t Size = sizeof(Type);
  47. static constexpr std::size_t Offset = Align(Size, S);
  48. static constexpr std::size_t EndOffset = Offset + Size;
  49.  
  50. static Pointer Instance(char *ptr) {
  51. return reinterpret_cast<Pointer>(RawData(ptr));
  52. }
  53.  
  54. template <typename... Args>
  55. static Pointer Construct(char *ptr, Args &&... args) {
  56. return new (RawData(ptr)) Type(std::forward<Args>(args)...);
  57. }
  58.  
  59. static void Destruct(char *ptr) { Instance(ptr)->~Type(); }
  60.  
  61. private:
  62. static char *RawData(char *ptr) { return ptr + Offset; }
  63. };
  64.  
  65. // Services for placement of a number of types within a memory
  66. // chunk at the specified offset.
  67. template <std::size_t S, typename... Tail> class ChunkLayout {
  68. public:
  69. static constexpr std::size_t StartOffset = S;
  70. static constexpr std::size_t EndOffset = S;
  71.  
  72. template <typename... Args> static void Construct(char *, Args...) {}
  73.  
  74. static void Destruct(char *) {}
  75. };
  76.  
  77. // Recursive template specialization of the above.
  78. template <std::size_t S, typename Head, typename... Tail>
  79. class ChunkLayout<S, Head, Tail...>
  80. : public ChunkLayout<EntryLayout<Head, S>::EndOffset, Tail...> {
  81. public:
  82. using EntryType = Head;
  83. using HeadLayout = EntryLayout<Head, S>;
  84. using TailLayout = ChunkLayout<HeadLayout::EndOffset, Tail...>;
  85.  
  86. static constexpr std::size_t StartOffset = S;
  87. static constexpr std::size_t EndOffset = TailLayout::EndOffset;
  88.  
  89. static typename HeadLayout::Pointer Instance(char *ptr) {
  90. return HeadLayout::Instance(ptr);
  91. }
  92.  
  93. template <typename... Args> void Construct(char *ptr, Args... args) {
  94. HeadLayout::Construct(ptr, args...);
  95. TailLayout::Construct(ptr, args...);
  96. }
  97.  
  98. void Destruct(char *ptr) {
  99. TailLayout::Destruct(ptr);
  100. HeadLayout::Destruct(ptr);
  101. }
  102. };
  103.  
  104. } // namespace detail
  105.  
  106. // Control of memory chunk free and used space.
  107. class ChunkSpace {
  108. public:
  109. ChunkSpace(std::size_t size) noexcept : free_{size}, used_(0) {}
  110.  
  111. std::size_t Used() const { return used_; }
  112. std::size_t Free() const { return free_; }
  113. std::size_t Size() const { return free_ + used_; }
  114.  
  115. bool Alloc(std::size_t size) {
  116. if (size > free_)
  117. return false;
  118. free_ -= size;
  119. used_ += size;
  120. return true;
  121. }
  122.  
  123. void Reset(std::size_t size = 0) {
  124. assert(size <= used_);
  125. free_ = free_ + used_ - size;
  126. used_ = size;
  127. }
  128.  
  129. private:
  130. std::size_t free_;
  131. std::size_t used_;
  132. };
  133.  
  134. template <typename... EntryType>
  135. class Chunk : public detail::ChunkLayout<0, ChunkSpace, EntryType...> {
  136. using Layout = detail::ChunkLayout<0, ChunkSpace, EntryType...>;
  137.  
  138. public:
  139. Chunk(char *data, std::size_t size) : data_{data} {
  140. assert(size > Layout::EndOffset);
  141.  
  142. // Construct ChunkSpace instance to bootstrap allocation.
  143. Layout::HeadLayout::Construct(data_, size);
  144. // Allocate space required for all the chunk data.
  145. Alloc(Layout::EndOffset);
  146. // Construct the rest of the chunk data.
  147. Layout::TailLayout::Construct(data_);
  148. }
  149.  
  150. ~Chunk() {
  151. Layout::Destruct(data_);
  152. }
  153.  
  154. template <typename T>
  155. T* Get() {
  156. return decltype(Upcast<T>(this))::Instance(data_);
  157. }
  158.  
  159. template <typename T>
  160. const T* Get() const {
  161. return decltype(Upcast<T>(this))::Instance(data_);
  162. }
  163.  
  164. std::size_t Used() const { return Get<ChunkSpace>()->Used(); }
  165. std::size_t Free() const { return Get<ChunkSpace>()->Free(); }
  166. std::size_t Size() const { return Get<ChunkSpace>()->Size(); }
  167.  
  168. void *Allocate(std::size_t size) {
  169. std::size_t offset = Used();
  170. std::size_t aligned_offset = detail::Align(size, offset);
  171. std::size_t offset_padding = aligned_offset - offset;
  172. if (!Alloc(size + offset_padding))
  173. return nullptr;
  174. return data_ + aligned_offset;
  175. }
  176.  
  177. private:
  178. bool Alloc(std::size_t size) {
  179. return Get<ChunkSpace>()->Alloc(size);
  180. }
  181.  
  182. // Some C++ magic to upcast to the base class that contains layout info
  183. // for a given entry type.
  184. template <typename Head, std::size_t S, typename... Tail>
  185. static typename detail::ChunkLayout<S, Head, Tail...>::HeadLayout
  186. Upcast(const detail::ChunkLayout<S, Head, Tail...> *);
  187.  
  188. char *data_;
  189. };
  190.  
  191. } // namespace memory
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement