Flow123d  DF_patch_fe_data_tables-6bd0dc8
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 // TODO shared_ptr out of class, pass pointer to data, describe how to use
31 template <class Resource>
32 class ArenaResource : public std::pmr::memory_resource {
33 protected:
34  /// Returns different upstream resource in debug / release mode
35  static inline std::pmr::memory_resource* upstream_resource() {
36 #ifdef FLOW123D_DEBUG
37  return std::pmr::null_memory_resource();
38 #else
39  return std::pmr::get_default_resource();
40 #endif
41  }
42 
43 public:
44  /// Constructor. Creates assembly arena
45  ArenaResource(size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource* upstream = ArenaResource<Resource>::upstream_resource())
46  : upstream_(upstream), // TODO needs use buffer and resource of upstream if default upstream is not used
47  buffer_( std::pmr::get_default_resource()->allocate(buffer_size, simd_alignment) ),
48  buffer_size_(buffer_size),
49  used_size_(0),
50  resource_(buffer_, buffer_size, upstream_),
51  simd_alignment_(simd_alignment),
52  full_data_(false)
53  {
54  ASSERT_PERMANENT_EQ( (buffer_size%simd_alignment), 0 );
55  }
56 
57 
58  /// Same as previous but doesn't construct buffer implicitly.
59  ArenaResource(void *buffer, size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource* upstream = ArenaResource<Resource>::upstream_resource())
60  : upstream_( upstream ),
61  buffer_(buffer),
62  buffer_size_(buffer_size),
63  used_size_(0),
64  resource_(buffer_, buffer_size, upstream_),
65  simd_alignment_(simd_alignment),
66  full_data_(false)
67  {
68  ASSERT_PERMANENT_EQ( (buffer_size%simd_alignment), 0 );
69  }
70 
71 
72  ~ArenaResource() = default; // virtual, call destructor buffer_ = default_resource, (resource_)
73 
74  /**
75  * Create and return child arena.
76  *
77  * Child arena is created in free space of actual arena.
78  * Actual arena is marked as full (flag full_data_) and cannot allocate new data.
79  */
81  void *p = this->raw_allocate(1, simd_alignment_);
82  size_t used_size = (char *)p - (char *)buffer_;
83  size_t free_space = buffer_size_ - used_size;
84  full_data_ = true;
85  return new ArenaResource(p, free_space, simd_alignment_);
86  }
87 
88 
89  /// Compute and print free space and used space of arena buffer. Development method
90  inline void print_space() {
91  void *p = this->raw_allocate(1, simd_alignment_);
92  size_t used_size = (char *)p - (char *)buffer_;
93  size_t free_space = buffer_size_ - used_size;
94  std::cout << "Allocated space of arena is " << used_size << " B, free space is " << free_space << " B." << std::endl;
95  }
96 
97 
98  /// Getter for resource
99  Resource &resource() {
100  return resource_;
101  }
102 
103  /// Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
104  template <class T>
105  T* allocate_8(size_t n_items) {
106  size_t bytes = sizeof(T) * n_items;
107  return (T*)this->raw_allocate(bytes, 8);
108  }
109 
110  /// Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignment constructor argument)
111  template <class T>
112  T* allocate_simd(size_t n_items) {
113  size_t bytes = sizeof(T) * n_items;
114  return (T*)this->raw_allocate(bytes, simd_alignment_);
115  }
116 
117  // Reset allocated data
118  void reset() {
119  resource_.release();
120  used_size_ = 0;
121  full_data_ = false;
122 #ifdef FLOW123D_DEBUG
123  char *c_buffer = (char *)buffer_;
124  for (size_t i=0; i<buffer_size_; ++i)
125  c_buffer[i] = 0;
126 #endif
127  }
128 
129 protected:
130  void* raw_allocate(size_t bytes, size_t alignment) {
131  ASSERT(!full_data_).error("Allocation of new data is not possible because child arena was created.");
132  ASSERT_EQ(buffer_size_%alignment, 0);
133 
134  void* p = resource_.allocate(bytes, alignment);
135  used_size_ += (bytes + alignment - 1) / alignment * alignment;
136  if (p == nullptr) { // test only in Debug when null_pointer_resource is in use
137  throw std::bad_alloc();
138  }
139  return p;
140  }
141 
142  /// Override do_allocate to handle allocation logic
143  void* do_allocate(size_t bytes, size_t alignment) override {
144  return raw_allocate(bytes, alignment);
145  }
146 
147  /// Override do_deallocate (no-op for monotonic buffer)
148  void do_deallocate(FMT_UNUSED void* p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override {
149  // No-op
150  }
151 
152  /// Override do_is_equal for memory resource comparison
153  bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
154  return this == &other;
155  }
156 
157 private:
158  std::pmr::memory_resource* upstream_; ///< Pointer to upstream
159  void* buffer_; ///< Pointer to buffer
160  size_t buffer_size_; ///< Size of buffer
161  size_t used_size_; ///< Temporary data member, will be removed
162  Resource resource_; ///< Resource of arena
163  size_t simd_alignment_; ///< Size of SIMD alignment
164  bool full_data_; ///< Flag signs full data (child arena is created)
165 };
166 
167 
170 
171 
172 #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())
Same as previous but doesn't construct buffer implicitly.
#define FMT_UNUSED
Definition: posix.h:75