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