Flow123d  DF_patch_fe_data_tables-836d647
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)
35  : upstream_(std::pmr::get_default_resource()),
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  ArenaResource(size_t buffer_size, size_t simd_alignment, std::pmr::memory_resource* upstream = ArenaResource<Resource>::upstream_resource())
57  : upstream_(upstream), // TODO needs use buffer and resource of upstream if default upstream is not used
58  buffer_( upstream_->allocate(buffer_size, simd_alignment) ),
59  buffer_size_(buffer_size),
60  used_size_(0),
61  resource_(buffer_, buffer_size, upstream_),
62  simd_alignment_(simd_alignment),
63  full_data_(false)
64  {
65  ASSERT_PERMANENT_EQ( (buffer_size%simd_alignment), 0 );
66  }
67 
68 
69  ~ArenaResource() = default;
70 
71  /**
72  * Create and return child arena.
73  *
74  * Child arena is created in free space of actual arena.
75  * Actual arena is marked as full (flag full_data_) and cannot allocate new data.
76  */
78  void *p = this->raw_allocate(1, simd_alignment_);
79  size_t used_size = (char *)p - (char *)buffer_;
80  size_t free_space = buffer_size_ - used_size;
81  full_data_ = true;
82  return ArenaResource(p, free_space, simd_alignment_);
83  }
84 
85 
86  /// Getter for resource
87  Resource &resource() {
88  return resource_;
89  }
90 
91  /// Allocate and return data pointer of n_item array of type T (alignment to length 8 bytes)
92  template <class T>
93  T* allocate_8(size_t n_items) {
94  size_t bytes = sizeof(T) * n_items;
95  return (T*)this->raw_allocate(bytes, 8);
96  }
97 
98  /// Allocate and return data pointer of n_item array of type T (alignment to length given by simd_alignment constructor argument)
99  template <class T>
100  T* allocate_simd(size_t n_items) {
101  size_t bytes = sizeof(T) * n_items;
102  return (T*)this->raw_allocate(bytes, simd_alignment_);
103  }
104 
105  // Reset allocated data
106  void reset() {
107  resource_.release();
108  used_size_ = 0;
109 #ifdef FLOW123D_DEBUG
110  char *c_buffer = (char *)buffer_;
111  for (size_t i=0; i<buffer_size_; ++i)
112  c_buffer[i] = 0;
113 #endif
114  }
115 
116 protected:
117  void* raw_allocate(size_t bytes, size_t alignment) {
118  ASSERT(!full_data_).error("Allocation of new data is not possible because child arena was created.");
119 
120  void* p = resource_.allocate(bytes, alignment);
121  used_size_ += (bytes + alignment - 1) / alignment * alignment;
122  if (p == nullptr) { // test only in Debug when null_pointer_resource is in use
123  throw std::bad_alloc();
124  }
125  return p;
126  }
127 
128  /// Override do_allocate to handle allocation logic
129  void* do_allocate(size_t bytes, size_t alignment) override {
130  return raw_allocate(bytes, alignment);
131  }
132 
133  /// Override do_deallocate (no-op for monotonic buffer)
134  void do_deallocate(FMT_UNUSED void* p, FMT_UNUSED size_t bytes, FMT_UNUSED size_t alignment) override {
135  // No-op
136  }
137 
138  /// Override do_is_equal for memory resource comparison
139  bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
140  return this == &other;
141  }
142 
143 private:
144  std::pmr::memory_resource* upstream_; ///< Pointer to upstream
145  void* buffer_; ///< Pointer to buffer
146  size_t buffer_size_; ///< Size of buffer
147  size_t used_size_; ///< Temporary data member, will be removed
148  Resource resource_; ///< Resource of arena
149  size_t simd_alignment_; ///< Size of SIMD alignment
150  bool full_data_; ///< Flag signs full data (child arena is created)
151 };
152 
153 
156 
157 
158 #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
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())
~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)
ArenaResource(void *buffer, size_t buffer_size, size_t simd_alignment)
Inner constructor, used only in construction of child arena.
bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override
Override do_is_equal for memory resource comparison.
ArenaResource get_child_arena()
size_t buffer_size_
Size of buffer.
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.
#define FMT_UNUSED
Definition: posix.h:75