Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
counting_callocator.hpp
Go to the documentation of this file.
1 /*
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2021 Gothel Software e.K.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #ifndef COUNTING_CALLOCATOR_HPP
26 #define COUNTING_CALLOCATOR_HPP
27 
28 #include <cinttypes>
29 #include <memory>
30 
31 #include <jau/basic_types.hpp>
32 #include <jau/callocator.hpp>
33 
34 namespace jau {
35 
36 /**
37  * Performance counter jau::callocator specialization.
38  * <p>
39  * This class shall be compliant with <i>C++ named requirements for Allocator</i>.
40  * </p>
41  * <p>
42  * Not overriding deprecated (C++17) and removed (C++20)
43  * methods: address(), max_size(), construct() and destroy().
44  * </p>
45  */
46 template <class T>
48 {
49  public:
50  template <class U> struct rebind {typedef counting_callocator<U> other;};
51 
52  // typedefs' for C++ named requirements: Allocator
53  typedef T value_type;
54 
55  // std::size_t id;
56  bool old_stats;
57  std::size_t memory_usage;
58  std::size_t alloc_count;
59  std::size_t dealloc_count;
60  std::size_t realloc_count;
61  ssize_t alloc_balance;
62 
63  private:
64  // inline static relaxed_atomic_size_t next_id = 1;
65 
66  /**
67  * vector<value_type>::get_allocator() returns a copy of the allocator instance,
68  * where we desire to access the copied statistics.
69  * <p>
70  * However, vector<value_type>(const vector<value_type>&) also copies the allocator instance,
71  * but here the copied statistics shall be flushed since the elements are
72  * copied into the new vector<value_type> instance using the new allocator.<br>
73  * Without flushing the stats, we would see a size + size allocator stats,
74  * the former size from the copied allocator and the latter from the
75  * copied elements into the new vector<value_type> instance.
76  * </p>
77  */
78  constexpr void flush_stats() noexcept {
79  if( old_stats ) {
80  old_stats = false;
81  memory_usage = 0;
82  alloc_count = 0;
83  dealloc_count = 0;
84  realloc_count = 0;
85  alloc_balance = 0;
86  }
87  }
88 
89  public:
90  std::string toString(const nsize_t mem_width=0, const nsize_t count_width=0) {
91  return "CAlloc["/*+std::to_string(id)+", "*/+to_decstring(memory_usage, ',', mem_width)+" bytes, alloc[balance "+
92  to_decstring(alloc_balance, ',', count_width)+" = "+
93  to_decstring(alloc_count, ',', count_width)+" - "+to_decstring(dealloc_count, ',', count_width)+
94  ", realloc = "+to_decstring(realloc_count, ',', count_width)+"]]";
95  }
96 
99  // id(next_id++),
100  old_stats(false),
102  { } // C++11
103 
104 #if __cplusplus > 201703L
105  constexpr counting_callocator(const counting_callocator& other) noexcept
107  // id(next_id++),
108  old_stats(true),
109  memory_usage(other.memory_usage),
110  alloc_count(other.alloc_count), dealloc_count(other.dealloc_count),
111  realloc_count(other.realloc_count), alloc_balance(other.alloc_balance)
112  {} // C++20
113 #else
116  // id(next_id++),
117  old_stats(true),
118  memory_usage(other.memory_usage),
119  alloc_count(other.alloc_count), dealloc_count(other.dealloc_count),
120  realloc_count(other.realloc_count), alloc_balance(other.alloc_balance)
121  { }
122 #endif
123 
124 #if __cplusplus > 201703L
125  template <typename U>
126  constexpr counting_callocator(const counting_callocator<U>& other) noexcept
128  // id(next_id++),
129  old_stats(true),
130  memory_usage(other.memory_usage),
131  alloc_count(other.alloc_count), dealloc_count(other.dealloc_count),
132  realloc_count(other.realloc_count), alloc_balance(other.alloc_balance)
133  {} // C++20
134 #else
135  template <typename U>
138  // id(next_id++),
139  old_stats(true),
140  memory_usage(other.memory_usage),
141  alloc_count(other.alloc_count), dealloc_count(other.dealloc_count),
142  realloc_count(other.realloc_count), alloc_balance(other.alloc_balance)
143  { }
144 #endif
145 
146 #if __cplusplus > 201703L
147  constexpr ~counting_callocator() {} // C++20
148 #else
150 #endif
151 
152 #if __cplusplus <= 201703L
153  value_type* allocate(std::size_t n, const void * hint) { // C++17 deprecated; C++20 removed
154  flush_stats();
155  memory_usage += n * sizeof(value_type);
156  ++alloc_count;
157  ++alloc_balance;
159  }
160 #endif
161 
162 #if __cplusplus > 201703L
163  [[nodiscard]] constexpr value_type* allocate(std::size_t n) { // C++20
164  flush_stats();
165  memory_usage += n * sizeof(value_type);
166  ++alloc_count;
167  ++alloc_balance;
169  }
170 #else
171  value_type* allocate(std::size_t n) { // C++17
172  flush_stats();
173  memory_usage += n * sizeof(value_type);
174  ++alloc_count;
175  ++alloc_balance;
177  }
178 #endif
179 
180  [[nodiscard]] constexpr value_type* reallocate(value_type* p, std::size_t old_size, std::size_t new_size) {
181  value_type * const res = reinterpret_cast<value_type*>(
182  jau::callocator<value_type>::reallocate( p, old_size, new_size ) );
183  if( nullptr != res ) {
184  memory_usage -= old_size * sizeof(value_type);
185  memory_usage += new_size * sizeof(value_type);
186  ++realloc_count;
187  } // else realloc does not free storage on failure (nullptr)
188  return res;
189  }
190 
191 #if __cplusplus > 201703L
192  constexpr void deallocate(value_type* p, std::size_t n ) {
193  flush_stats();
194  memory_usage -= n * sizeof(value_type);
195  ++dealloc_count;
196  --alloc_balance;
198  }
199 #else
200  void deallocate(value_type* p, std::size_t n ) {
201  flush_stats();
202  memory_usage -= n * sizeof(value_type);
203  ++dealloc_count;
204  --alloc_balance;
206  }
207 #endif
208 };
209 
210 
211 #if __cplusplus > 201703L
212 template <class T1, class T2>
213  constexpr bool operator==(const counting_callocator<T1>& lhs, const counting_callocator<T2>& rhs) noexcept {
214 #if 0
215  if( &lhs == &rhs ) {
216  return true;
217  }
218  return lhs.memory_usage == rhs.memory_usage;
219 #else
220  (void)lhs;
221  (void)rhs;
222  return true;
223 #endif
224  }
225 #else
226  template <class T1, class T2>
227  bool operator==(const counting_callocator<T1>& lhs, const counting_callocator<T2>& rhs) noexcept {
228 #if 0
229  if( &lhs == &rhs ) {
230  return true;
231  }
232  return lhs.memory_usage == rhs.memory_usage;
233 #else
234  (void)lhs;
235  (void)rhs;
236  return true;
237 #endif
238  }
239  template <class T1, class T2>
240  bool operator!=(const counting_callocator<T1>& lhs, const counting_callocator<T2>& rhs) noexcept {
241  return !(lhs==rhs);
242  }
243 #endif
244 
245 } /* namespace jau */
246 
247 #endif // COUNTING_CALLOCATOR_HPP
248 
callocator.hpp
jau::to_decstring
std::string to_decstring(const value_type &v, const char separator=',', const nsize_t width=0) noexcept
Produce a decimal string representation of an integral integer value.
Definition: string_util.hpp:143
jau::counting_callocator::~counting_callocator
~counting_callocator()
Definition: counting_callocator.hpp:149
jau::counting_callocator::counting_callocator
counting_callocator() noexcept
Definition: counting_callocator.hpp:97
jau::counting_callocator::alloc_balance
ssize_t alloc_balance
Definition: counting_callocator.hpp:61
jau
Definition: basic_algos.hpp:34
jau::callocator::value_type
T value_type
Definition: callocator.hpp:58
jau::counting_callocator::realloc_count
std::size_t realloc_count
Definition: counting_callocator.hpp:60
jau::counting_callocator::reallocate
constexpr value_type * reallocate(value_type *p, std::size_t old_size, std::size_t new_size)
Definition: counting_callocator.hpp:180
jau::callocator::reallocate
constexpr value_type * reallocate(value_type *p, std::size_t old_size, std::size_t new_size)
Definition: callocator.hpp:105
jau::counting_callocator::alloc_count
std::size_t alloc_count
Definition: counting_callocator.hpp:58
jau::counting_callocator::toString
std::string toString(const nsize_t mem_width=0, const nsize_t count_width=0)
Definition: counting_callocator.hpp:90
jau::callocator::deallocate
void deallocate(value_type *p, std::size_t n)
Definition: callocator.hpp:117
jau::counting_callocator::rebind
Definition: counting_callocator.hpp:50
jau::counting_callocator::deallocate
void deallocate(value_type *p, std::size_t n)
Definition: counting_callocator.hpp:200
jau::counting_callocator::memory_usage
std::size_t memory_usage
Definition: counting_callocator.hpp:57
jau::nsize_t
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:44
jau::counting_callocator::allocate
value_type * allocate(std::size_t n, const void *hint)
Definition: counting_callocator.hpp:153
jau::counting_callocator::dealloc_count
std::size_t dealloc_count
Definition: counting_callocator.hpp:59
jau::counting_callocator::value_type
T value_type
Definition: counting_callocator.hpp:53
jau::callocator
A simple allocator using POSIX C functions: ::malloc(), ::free() and ::realloc().
Definition: callocator.hpp:53
jau::counting_callocator::old_stats
bool old_stats
Definition: counting_callocator.hpp:56
jau::operator!=
bool operator!=(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
Definition: callocator.hpp:155
basic_types.hpp
jau::callocator::allocate
value_type * allocate(std::size_t n, const void *hint)
Definition: callocator.hpp:89
jau::counting_callocator::rebind::other
counting_callocator< U > other
Definition: counting_callocator.hpp:50
jau::counting_callocator::allocate
value_type * allocate(std::size_t n)
Definition: counting_callocator.hpp:171
jau::operator==
bool operator==(const callocator< T1 > &lhs, const callocator< T2 > &rhs) noexcept
Definition: callocator.hpp:142
jau::counting_callocator::counting_callocator
counting_callocator(const counting_callocator &other) noexcept
Definition: counting_callocator.hpp:114
jau::counting_callocator::counting_callocator
counting_callocator(const counting_callocator< U > &other) noexcept
Definition: counting_callocator.hpp:136
jau::counting_callocator
Performance counter jau::callocator specialization.
Definition: counting_callocator.hpp:48