Audacity 3.2.0
MemoryX.h
Go to the documentation of this file.
1#ifndef __AUDACITY_MEMORY_X_H__
2#define __AUDACITY_MEMORY_X_H__
3
4// C++ standard header <memory> with a few extensions
5#include <memory>
6#include <new> // align_val_t and hardware_destructive_interference_size
7#include <cstdlib> // Needed for free.
8#ifndef safenew
9#define safenew new
10#endif
11
12#include <functional>
13#include <limits>
14
15#include <cstdint>
16
17/*
18 * ArrayOf<X>
19 * Not to be confused with std::array (which takes a fixed size) or std::vector
20 * This maintains a pointer allocated by NEW X[]. It's cheap: only one pointer,
21 * with no size and capacity information for resizing as for vector, and if X is
22 * a built-in numeric or pointer type, by default there is no zero filling at
23 * allocation time.
24 */
25
26template<typename X>
27class ArrayOf : public std::unique_ptr<X[]>
28{
29public:
31
32 template<typename Integral>
33 explicit ArrayOf(Integral count, bool initialize = false)
34 {
35 static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
36 reinit(count, initialize);
37 }
38
39 //ArrayOf(const ArrayOf&) = delete;
40 ArrayOf(const ArrayOf&) = delete;
42 : std::unique_ptr < X[] >
43 (std::move((std::unique_ptr < X[] >&)(that)))
44 {
45 }
47 {
48 std::unique_ptr<X[]>::operator=(std::move(that));
49 return *this;
50 }
51 ArrayOf& operator= (std::unique_ptr<X[]> &&that)
52 {
53 std::unique_ptr<X[]>::operator=(std::move(that));
54 return *this;
55 }
56
57 template< typename Integral >
58 void reinit(Integral count,
59 bool initialize = false)
60 {
61 static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
62 if (initialize)
63 // Initialize elements (usually, to zero for a numerical type)
64 std::unique_ptr<X[]>::reset(safenew X[count]{});
65 else
66 // Avoid the slight initialization overhead
67 std::unique_ptr<X[]>::reset(safenew X[count]);
68 }
69};
70
80template<typename X>
81class ArraysOf : public ArrayOf<ArrayOf<X>>
82{
83public:
85
86 template<typename Integral>
87 explicit ArraysOf(Integral N)
88 : ArrayOf<ArrayOf<X>>( N )
89 {}
90
91 template<typename Integral1, typename Integral2 >
92 ArraysOf(Integral1 N, Integral2 M, bool initialize = false)
93 : ArrayOf<ArrayOf<X>>( N )
94 {
95 static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
96 static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
97 for (size_t ii = 0; ii < N; ++ii)
98 (*this)[ii] = ArrayOf<X>{ M, initialize };
99 }
100
101 //ArraysOf(const ArraysOf&) = delete;
102 ArraysOf(const ArraysOf&) =delete;
104 {
105 ArrayOf<ArrayOf<X>>::operator=(std::move(that));
106 return *this;
107 }
108
109 template< typename Integral >
110 void reinit(Integral count)
111 {
113 }
114
115 template< typename Integral >
116 void reinit(Integral count, bool initialize)
117 {
118 ArrayOf<ArrayOf<X>>::reinit( count, initialize );
119 }
120
121 template<typename Integral1, typename Integral2 >
122 void reinit(Integral1 countN, Integral2 countM, bool initialize = false)
123 {
124 static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
125 static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
126 reinit(countN, false);
127 for (size_t ii = 0; ii < countN; ++ii)
128 (*this)[ii].reinit(countM, initialize);
129 }
130};
131
135struct freer { void operator() (void *p) const { free(p); } };
136
140template< typename T >
141using MallocPtr = std::unique_ptr< T, freer >;
142
146template <typename Character = char>
147using MallocString = std::unique_ptr< Character[], freer >;
148
154template <typename T>
155struct Destroyer {
156 void operator () (T *p) const { if (p) p->Destroy(); }
157};
158
162template <typename T>
163using Destroy_ptr = std::unique_ptr<T, Destroyer<T>>;
164
172// Construct this from any copyable function object, such as a lambda
173template <typename F>
174struct Finally {
175 Finally(F f) : clean( f ) {}
178};
179
182template <typename F>
183[[nodiscard]] Finally<F> finally (F f)
184{
185 return Finally<F>(f);
186}
187
190
194template<typename F> Finally(F) -> Finally<F>;
195
196#include <algorithm>
197
201template< typename T >
204 void operator () ( T *p ) const { if (p) *p = oldValue; }
205};
206
207
211template< typename T >
212class ValueRestorer : public std::unique_ptr< T, RestoreValue<T> >
213{
214 using std::unique_ptr< T, RestoreValue<T> >::reset; // make private
215 // But release() remains public and can be useful to commit a changed value
216public:
217 explicit ValueRestorer( T &var )
218 : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
219 {}
220 explicit ValueRestorer( T &var, const T& newValue )
221 : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
222 { var = newValue; }
224 : std::unique_ptr < T, RestoreValue<T> > ( std::move(that) ) {};
226 {
227 if (this != &that)
228 std::unique_ptr < T, RestoreValue<T> >::operator=(std::move(that));
229 return *this;
230 }
231};
232
236template< typename T >
238 explicit CopyableValueRestorer(T& var)
239 : pointer{ &var, RestoreValue<T>{ var } }
240 {}
241 CopyableValueRestorer(T& var, const T& newValue)
242 : pointer{ &var, RestoreValue<T>{ var } }
243 {
244 var = newValue;
245 }
246
247 std::shared_ptr<T> pointer;
248};
249
251template< typename T >
253{ return ValueRestorer< T >{ var }; }
254
255template< typename T >
256ValueRestorer< T > valueRestorer( T& var, const T& newValue )
257{ return ValueRestorer< T >{ var, newValue }; }
258
260
264struct UTILITY_API alignas(
265#if defined(_WIN32) && defined(_MSC_VER)
266 // MSVC supports this symbol in std, but MinGW uses libstdc++, which it does not.
267 std::hardware_destructive_interference_size
268#else
269 // That constant isn't defined for the other builds yet
270 64 /* ? */
271#endif
272)
273
274NonInterferingBase {
275 static void *operator new(std::size_t count, std::align_val_t al);
276 static void operator delete(void *ptr, std::align_val_t al);
277
278#if defined (_MSC_VER) && defined(_DEBUG)
279 // Versions that work in the presence of the DEBUG_NEW macro.
280 // Ignore the arguments supplied by the macro and forward to the
281 // other overloads.
282 static void *operator new(
283 std::size_t count, std::align_val_t al, int, const char *, int)
284 { return operator new(count, al); }
285 static void operator delete(
286 void *ptr, std::align_val_t al, int, const char *, int)
287 { return operator delete(ptr, al); }
288#endif
289};
290
292
295template<typename T> // CRTP
296struct SharedNonInterfering : NonInterferingBase
297{
298 template<typename... Args>
299 static std::shared_ptr<T> make_shared(Args &&...args)
300 {
301 return std::
302#ifdef __APPLE__
303 // shared_ptr must be constructed from unique_ptr on Mac
304 make_unique
305#else
307#endif
308 <T>(std::forward<Args>(args)...);
309 }
310};
311
315template< typename T > struct NonInterfering
316 : NonInterferingBase // Inherit operators; use empty base class optimization
317 , T
318{
319 using T::T;
320
322 void Set(const T &other)
323 {
324 T::operator =(other);
325 }
326
328 void Set(T &&other)
329 {
330 T::operator =(std::move(other));
331 }
332};
333
334// These macros are used widely, so declared here.
335#define QUANTIZED_TIME(time, rate) (floor(((double)(time) * (rate)) + 0.5) / (rate))
336// dB - linear amplitude conversions
337#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0))
338#define LINEAR_TO_DB(x) (20.0 * log10(x))
339
340#define MAX_AUDIO (1. - 1./(1<<15))
341
344template<typename T>
345struct AtomicUniquePointer : public std::atomic<T*> {
346 static_assert(AtomicUniquePointer::is_always_lock_free);
347 using std::atomic<T*>::atomic;
350
352 void reset(T *p = nullptr) {
353 delete this->exchange(p, std::memory_order_release);
354 }
356 template<typename... Args> void emplace(Args &&... args) {
357 reset(safenew T(std::forward<Args>(args)...));
358 }
360private:
362 using std::atomic<T*>::fetch_add;
363 using std::atomic<T*>::fetch_sub;
364};
365
367inline bool IsLittleEndian() noexcept
368{
369 const std::uint32_t x = 1u;
370 return static_cast<const unsigned char*>(static_cast<const void*>(&x))[0];
371 // We will assume the same for other widths!
372}
373
375template <typename IntType>
376constexpr IntType SwapIntBytes(IntType value) noexcept
377{
378 static_assert(std::is_integral<IntType>::value, "Integral type required");
379
380 constexpr auto size = sizeof(IntType);
381
382 static_assert(
383 size == 1 || size == 2 || size == 4 || size == 8, "Unsupported size");
384
385 if constexpr (size == 1)
386 return value;
387 else if constexpr (size == 2)
388 return (value >> 8) | (value << 8);
389 else if constexpr (size == 4) // On x86, this (and 64 bit version) is a single instruction! (At least, clang is smart enough to do that)
390 return ((value >> 24) & 0xFF) | ((value >> 8) & 0xFF00) |
391 ((value << 8) & 0xFF0000) | ((value << 24) & 0xFF000000);
392 else if constexpr (size == 8)
393 return ((value >> 56) & 0xFF) | ((value >> 40) & 0xFF00) |
394 ((value >> 24) & 0xFF0000) | ((value >> 8) & 0xFF000000) |
395 ((value << 8) & 0xFF00000000) | ((value << 24) & 0xFF0000000000) |
396 ((value << 40) & 0xFF000000000000) |
397 ((value << 56) & 0xFF00000000000000);
398
399 // Unreachable
400 return value;
401}
402
403#endif // __AUDACITY_MEMORY_X_H__
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:252
struct UTILITY_API alignas(64) NonInterferingBase
Non-template helper for class template NonInterfering.
Definition: MemoryX.h:264
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:147
#define safenew
Definition: MemoryX.h:9
constexpr IntType SwapIntBytes(IntType value) noexcept
Swap bytes in an integer.
Definition: MemoryX.h:376
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:163
Finally(F) -> Finally< F >
std::unique_ptr< T, freer > MallocPtr
Definition: MemoryX.h:141
bool IsLittleEndian() noexcept
Check that machine is little-endian.
Definition: MemoryX.h:367
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Definition: MemoryX.h:28
ArrayOf(ArrayOf &&that)
Definition: MemoryX.h:41
ArrayOf(const ArrayOf &)=delete
ArrayOf()
Definition: MemoryX.h:30
ArrayOf & operator=(ArrayOf &&that)
Definition: MemoryX.h:46
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:58
ArrayOf(Integral count, bool initialize=false)
Definition: MemoryX.h:33
void reinit(Integral count)
Definition: MemoryX.h:110
ArraysOf(Integral1 N, Integral2 M, bool initialize=false)
Definition: MemoryX.h:92
ArraysOf(const ArraysOf &)=delete
ArraysOf & operator=(ArraysOf &&that)
Definition: MemoryX.h:103
ArraysOf()
Definition: MemoryX.h:84
void reinit(Integral1 countN, Integral2 countM, bool initialize=false)
Definition: MemoryX.h:122
ArraysOf(Integral N)
Definition: MemoryX.h:87
void reinit(Integral count, bool initialize)
Definition: MemoryX.h:116
Set a variable temporarily in a scope.
Definition: MemoryX.h:213
ValueRestorer(T &var, const T &newValue)
Definition: MemoryX.h:220
ValueRestorer(T &var)
Definition: MemoryX.h:217
ValueRestorer & operator=(ValueRestorer &&that)
Definition: MemoryX.h:225
ValueRestorer(ValueRestorer &&that)
Definition: MemoryX.h:223
void free(void *ptr)
Definition: VectorOps.h:34
STL namespace.
void reset(T *p=nullptr)
Definition: MemoryX.h:352
void emplace(Args &&... args)
reset to a pointer to a new object with given ctor arguments
Definition: MemoryX.h:356
std::shared_ptr< T > pointer
Definition: MemoryX.h:247
CopyableValueRestorer(T &var, const T &newValue)
Definition: MemoryX.h:241
CopyableValueRestorer(T &var)
Definition: MemoryX.h:238
A deleter class to supply the second template parameter of unique_ptr for classes like wxWindow that ...
Definition: MemoryX.h:155
void operator()(T *p) const
Definition: MemoryX.h:156
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Definition: MemoryX.h:174
Finally(F f)
Definition: MemoryX.h:175
F clean
Definition: MemoryX.h:177
~Finally()
Definition: MemoryX.h:176
void Set(T &&other)
Allow assignment from default-aligned base type.
Definition: MemoryX.h:328
void Set(const T &other)
Allow assignment from default-aligned base type.
Definition: MemoryX.h:322
Structure used by ValueRestorer.
Definition: MemoryX.h:202
void operator()(T *p) const
Definition: MemoryX.h:204
Workaround for std::make_shared not working on macOs with over-alignment.
Definition: MemoryX.h:297
static std::shared_ptr< T > make_shared(Args &&...args)
Definition: MemoryX.h:299
Definition: MemoryX.h:135
void operator()(void *p) const
Definition: MemoryX.h:135