Flow123d  DF_patch_fe_data_tables-9d4017b
arena_resource.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file arena_resource.hh
15  */
16 
17 #ifndef ARENA_RESOURCE_HH_
18 #define ARENA_RESOURCE_HH_
19 
20 #include <memory_resource>
21 #include <vector>
22 #include <iostream>
23 #include <new>
24 #include <stdexcept> // !! Use Flow exception mechanism
25 
26 #include "system/asserts.hh"
27 
28 
29 // Final proposal of Arena
30 template <class Resource>
31 class ArenaResource : public std::pmr::memory_resource {
32 protected:
33  /// Inner constructor, used only in construction of child arena
34  ArenaResource(void *buffer, size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource* upstream = ArenaResource<Resource>::upstream_resource())
35  : upstream_( upstream ),
36  buffer_(buffer),
37  buffer_size_(buffer_size),
38  used_size_(0),
39  resource_(buffer_, buffer_size, upstream_),
40  simd_alignment_(simd_alignment),
41  full_data_(false)
42  {
43  ASSERT_PERMANENT_EQ( (buffer_size%simd_alignment), 0 );
44  }
45 
46  /// Returns different upstream resource in debug / release mode
47  static inline std::pmr::memory_resource* upstream_resource() {
48 #ifdef FLOW123D_DEBUG
49  return std::pmr::null_memory_resource();
50 #else
51  return std::pmr::get_default_resource();
52 #endif
53  }
54 
55 public:
56  /// Constructor. Creates assembly arena
57  ArenaResource(size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource* upstream = ArenaResource<Resource>::upstream_resource())
58  : upstream_(upstream), // TODO needs use buffer and resource of upstream if default upstream is not used
59  buffer_( std::pmr::get_default_resource()->allocate(buffer_size, simd_alignment) ),
60  buffer_size_(buffer_size),
61  used_size_(0),
62  resource_(buffer_, buffer_size, upstream_),
63  simd_alignment_(simd_alignment),
64  full_data_(false)
65  {
66  ASSERT_PERMANENT_EQ( (buffer_size%simd_alignment), 0 );
67  }
68 
69 
70  ~ArenaResource() = default;
71 
72  /**
73  * Create and return child arena.
74  *
75  * Child arena is created in free space of actual arena.
76  * Actual arena is marked as full (flag full_data_) and cannot allocate new data.
77  */
79  void *p = this->raw_allocate(1, simd_alignment_);
80  size_t used_size = (char *)p - (char *)buffer_;
81  size_t free_space = buffer_size_ - used_size;
82  full_data_ = true;
83  return new ArenaResource(p, free_space, simd_alignment_);
84  }
85 
86 
87  /// Compute and print free space and used space of arena buffer. Development method
88  inline void print_space() {
89  void *p = this->raw_allocate(1, simd_alignment_);
90  size_t used_size = (char *)p - (char *)buffer_;
91  size_t free_space = buffer_size_ - used_size;
92  std::cout << "Allocated space of arena is " << used_size << " B, free space is " << free_space << " B." << std::endl;
93  }
94 
95 
96  /// Getter for resource
97  Resource &resource() {
98  return resource_;
99  }
100 
101  /// Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
102  template <class T>
103  T* allocate_8(size_t n_items) {
104  size_t bytes = sizeof(T) * n_items;
105  return (T*)this->raw_allocate(bytes, 8);
106  }
107 
108  /// Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignment constructor argument)
109  template <class T>
110  T* allocate_simd(size_t n_items) {
111  size_t bytes = sizeof(T) * n_items;
112  return (T*)this->raw_allocate(bytes, simd_alignment_);
113  }
114 
115  // Reset allocated data
116  void reset() {
117  resource_.release();
118  used_size_ = 0;
119  full_data_ = false;
120 #ifdef FLOW123D_DEBUG
121  char *c_buffer = (char *)buffer_;
122  for (size_t i=0; i<buffer_size_; ++i)
123  c_buffer[i] = 0;
124 #endif
125  }
126 
127 protected:
128  void* raw_allocate(size_t bytes, size_t alignment) {
129  ASSERT(!full_data_).error("Allocation of new data is not possible because child arena was created.");
130  ASSERT_EQ(buffer_size_%alignment, 0);
131 
132  void* p = resource_.allocate(bytes, alignment);
133  used_size_ += (bytes + alignment - 1) / alignment * alignment;
134  if (p == nullptr) { // test only in Debug when null_pointer_resource is in use
135  throw std::bad_alloc();
136  }
137  return p;
138  }
139 
140  /// Override do_allocate to handle allocation logic
141  void* do_allocate(size_t bytes, size_t alignment) override {
142  return raw_allocate(bytes, alignment);
143  }
144 
145  /// Override do_deallocate (no-op for monotonic buffer)
146  void do_deallocate(FMT_UNUSED void* p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override {
147  // No-op
148  }
149 
150  /// Override do_is_equal for memory resource comparison
151  bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
152  return this == &other;
153  }
154 
155 private:
156  std::pmr::memory_resource* upstream_; ///< Pointer to upstream
157  void* buffer_; ///< Pointer to buffer
158  size_t buffer_size_; ///< Size of buffer
159  size_t used_size_; ///< Temporary data member, will be removed
160  Resource resource_; ///< Resource of arena
161  size_t simd_alignment_; ///< Size of SIMD alignment
162  bool full_data_; ///< Flag signs full data (child arena is created)
163 };
164 
165 
168 
169 
170 #endif /* ARENA_RESOURCE_HH_ */
ArenaResource< std::pmr::monotonic_buffer_resource > AssemblyArena
Definitions of ASSERTS.
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_PERMANENT_EQ(a, b)
Definition of comparative assert macro (EQual)
Definition: asserts.hh:329
#define ASSERT_EQ(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:333
Resource resource_
Resource of arena.
std::pmr::memory_resource * upstream_
Pointer to upstream.
T * allocate_8(size_t n_items)
Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
ArenaResource(size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource *upstream=ArenaResource< Resource >::upstream_resource())
Constructor. Creates assembly arena.
void print_space()
Compute and print free space and used space of arena buffer. Development method.
~ArenaResource()=default
void * do_allocate(size_t bytes, size_t alignment) override
Override do_allocate to handle allocation logic.
static std::pmr::memory_resource * upstream_resource()
Returns different upstream resource in debug / release mode.
bool full_data_
Flag signs full data (child arena is created)
T * allocate_simd(size_t n_items)
Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignme...
size_t used_size_
Temporary data member, will be removed.
void do_deallocate(FMT_UNUSED void *p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override
Override do_deallocate (no-op for monotonic buffer)
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
Override do_is_equal for memory resource comparison.
size_t buffer_size_
Size of buffer.
ArenaResource * get_child_arena()
void * raw_allocate(size_t bytes, size_t alignment)
size_t simd_alignment_
Size of SIMD alignment.
void * buffer_
Pointer to buffer.
Resource & resource()
Getter for resource.
ArenaResource(void *buffer, size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource *upstream=ArenaResource< Resource >::upstream_resource())
Inner constructor, used only in construction of child arena.
#define FMT_UNUSED
Definition: posix.h:75