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 <iterator>
6#include <memory>
7#include <new> // align_val_t and hardware_destructive_interference_size
8#include <cstdlib> // Needed for free.
9#ifndef safenew
10#define safenew new
11#endif
12
13#include <functional>
14#include <limits>
15
16/*
17 * ArrayOf<X>
18 * Not to be confused with std::array (which takes a fixed size) or std::vector
19 * This maintains a pointer allocated by NEW X[]. It's cheap: only one pointer,
20 * with no size and capacity information for resizing as for vector, and if X is
21 * a built-in numeric or pointer type, by default there is no zero filling at
22 * allocation time.
23 */
24
25template<typename X>
26class ArrayOf : public std::unique_ptr<X[]>
27{
28public:
30
31 template<typename Integral>
32 explicit ArrayOf(Integral count, bool initialize = false)
33 {
34 static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
35 reinit(count, initialize);
36 }
37
38 //ArrayOf(const ArrayOf&) PROHIBITED;
39 ArrayOf(const ArrayOf&) = delete;
41 : std::unique_ptr < X[] >
42 (std::move((std::unique_ptr < X[] >&)(that)))
43 {
44 }
46 {
47 std::unique_ptr<X[]>::operator=(std::move(that));
48 return *this;
49 }
50 ArrayOf& operator= (std::unique_ptr<X[]> &&that)
51 {
52 std::unique_ptr<X[]>::operator=(std::move(that));
53 return *this;
54 }
55
56 template< typename Integral >
57 void reinit(Integral count,
58 bool initialize = false)
59 {
60 static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
61 if (initialize)
62 // Initialize elements (usually, to zero for a numerical type)
63 std::unique_ptr<X[]>::reset(safenew X[count]{});
64 else
65 // Avoid the slight initialization overhead
66 std::unique_ptr<X[]>::reset(safenew X[count]);
67 }
68};
69
79template<typename X>
80class ArraysOf : public ArrayOf<ArrayOf<X>>
81{
82public:
84
85 template<typename Integral>
86 explicit ArraysOf(Integral N)
87 : ArrayOf<ArrayOf<X>>( N )
88 {}
89
90 template<typename Integral1, typename Integral2 >
91 ArraysOf(Integral1 N, Integral2 M, bool initialize = false)
92 : ArrayOf<ArrayOf<X>>( N )
93 {
94 static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
95 static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
96 for (size_t ii = 0; ii < N; ++ii)
97 (*this)[ii] = ArrayOf<X>{ M, initialize };
98 }
99
100 //ArraysOf(const ArraysOf&) PROHIBITED;
101 ArraysOf(const ArraysOf&) =delete;
103 {
104 ArrayOf<ArrayOf<X>>::operator=(std::move(that));
105 return *this;
106 }
107
108 template< typename Integral >
109 void reinit(Integral count)
110 {
112 }
113
114 template< typename Integral >
115 void reinit(Integral count, bool initialize)
116 {
117 ArrayOf<ArrayOf<X>>::reinit( count, initialize );
118 }
119
120 template<typename Integral1, typename Integral2 >
121 void reinit(Integral1 countN, Integral2 countM, bool initialize = false)
122 {
123 static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
124 static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
125 reinit(countN, false);
126 for (size_t ii = 0; ii < countN; ++ii)
127 (*this)[ii].reinit(countM, initialize);
128 }
129};
130
134struct freer { void operator() (void *p) const { free(p); } };
135
139template< typename T >
140using MallocPtr = std::unique_ptr< T, freer >;
141
145template <typename Character = char>
146using MallocString = std::unique_ptr< Character[], freer >;
147
153template <typename T>
154struct Destroyer {
155 void operator () (T *p) const { if (p) p->Destroy(); }
156};
157
161template <typename T>
162using Destroy_ptr = std::unique_ptr<T, Destroyer<T>>;
163
171// Construct this from any copyable function object, such as a lambda
172template <typename F>
173struct Finally {
174 Finally(F f) : clean( f ) {}
177};
178
181template <typename F>
182[[nodiscard]] Finally<F> finally (F f)
183{
184 return Finally<F>(f);
185}
186
189
193template<typename F> Finally(F) -> Finally<F>;
194
195#include <algorithm>
196
200template< typename T >
203 void operator () ( T *p ) const { if (p) *p = oldValue; }
204};
205
206
210template< typename T >
211class ValueRestorer : public std::unique_ptr< T, RestoreValue<T> >
212{
213 using std::unique_ptr< T, RestoreValue<T> >::reset; // make private
214 // But release() remains public and can be useful to commit a changed value
215public:
216 explicit ValueRestorer( T &var )
217 : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
218 {}
219 explicit ValueRestorer( T &var, const T& newValue )
220 : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
221 { var = newValue; }
223 : std::unique_ptr < T, RestoreValue<T> > ( std::move(that) ) {};
225 {
226 if (this != &that)
227 std::unique_ptr < T, RestoreValue<T> >::operator=(std::move(that));
228 return *this;
229 }
230};
231
235template< typename T >
237 explicit CopyableValueRestorer(T& var)
238 : pointer{ &var, RestoreValue<T>{ var } }
239 {}
240 CopyableValueRestorer(T& var, const T& newValue)
241 : pointer{ &var, RestoreValue<T>{ var } }
242 {
243 var = newValue;
244 }
245
246 std::shared_ptr<T> pointer;
247};
248
250template< typename T >
252{ return ValueRestorer< T >{ var }; }
253
254template< typename T >
255ValueRestorer< T > valueRestorer( T& var, const T& newValue )
256{ return ValueRestorer< T >{ var, newValue }; }
257
262template< typename Value, typename Category = std::forward_iterator_tag >
264 using iterator_category = Category;
265 using value_type = Value;
266 using difference_type = ptrdiff_t;
267 // void pointer type so that operator -> is disabled
268 using pointer = void;
269 // make "reference type" really the same as the value type
270 using reference = const Value;
271};
272
276template <typename Iterator>
277struct IteratorRange : public std::pair<Iterator, Iterator> {
278 using iterator = Iterator;
279 using reverse_iterator = std::reverse_iterator<Iterator>;
280
281 IteratorRange (const Iterator &a, const Iterator &b)
282 : std::pair<Iterator, Iterator> ( a, b ) {}
283
284 IteratorRange (Iterator &&a, Iterator &&b)
285 : std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}
286
288 { return { this->rbegin(), this->rend() }; }
289
290 Iterator begin() const { return this->first; }
291 Iterator end() const { return this->second; }
292
293 reverse_iterator rbegin() const { return reverse_iterator{ this->second }; }
294 reverse_iterator rend() const { return reverse_iterator{ this->first }; }
295
296 bool empty() const { return this->begin() == this->end(); }
297 explicit operator bool () const { return !this->empty(); }
298 size_t size() const { return std::distance(this->begin(), this->end()); }
299
300 template <typename T> iterator find(const T &t) const
301 { return std::find(this->begin(), this->end(), t); }
302
303 template <typename T> long index(const T &t) const
304 {
305 auto iter = this->find(t);
306 if (iter == this->end())
307 return -1;
308 return std::distance(this->begin(), iter);
309 }
310
311 template <typename T> bool contains(const T &t) const
312 { return this->end() != this->find(t); }
313
314 template <typename F> iterator find_if(const F &f) const
315 { return std::find_if(this->begin(), this->end(), f); }
316
317 template <typename F> long index_if(const F &f) const
318 {
319 auto iter = this->find_if(f);
320 if (iter == this->end())
321 return -1;
322 return std::distance(this->begin(), iter);
323 }
324
325 // to do: use std::all_of, any_of, none_of when available on all platforms
326 template <typename F> bool all_of(const F &f) const
327 {
328 auto notF =
329 [&](typename std::iterator_traits<Iterator>::reference v)
330 { return !f(v); };
331 return !this->any_of( notF );
332 }
333
334 template <typename F> bool any_of(const F &f) const
335 { return this->end() != this->find_if(f); }
336
337 template <typename F> bool none_of(const F &f) const
338 { return !this->any_of(f); }
339
340 template<typename T> struct identity
341 { const T&& operator () (T &&v) const { return std::forward(v); } };
342
343 // Like std::accumulate, but the iterators implied, and with another
344 // unary operation on the iterator value, pre-composed
345 template<
346 typename R,
347 typename Binary = std::plus< R >,
349 >
351 R init,
352 Binary binary_op = {},
353 Unary unary_op = {}
354 ) const
355 {
356 R result = init;
357 for (auto&& v : *this)
358 result = binary_op(result, unary_op(v));
359 return result;
360 }
361
362 // An overload making it more convenient to use with pointers to member
363 // functions
364 template<
365 typename R,
366 typename Binary = std::plus< R >,
367 typename R2, typename C
368 >
370 R init,
371 Binary binary_op,
372 R2 (C :: * pmf) () const
373 ) const
374 {
375 return this->accumulate( init, binary_op, std::mem_fn( pmf ) );
376 }
377
378 // Some accumulations frequent enough to be worth abbreviation:
379 template<
380 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
381 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
382 >
383 R min( Unary unary_op = {} ) const
384 {
385 return this->accumulate(
386 std::numeric_limits< R >::max(),
387 (const R&(*)(const R&, const R&)) std::min,
388 unary_op
389 );
390 }
391
392 template<
393 typename R2, typename C,
394 typename R = R2
395 >
396 R min( R2 (C :: * pmf) () const ) const
397 {
398 return this->min( std::mem_fn( pmf ) );
399 }
400
401 template<
402 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
403 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
404 >
405 R max( Unary unary_op = {} ) const
406 {
407 return this->accumulate(
408 std::numeric_limits< R >::lowest(),
409 (const R&(*)(const R&, const R&)) std::max,
410 unary_op
411 );
412 }
413
414 template<
415 typename R2, typename C,
416 typename R = R2
417 >
418 R max( R2 (C :: * pmf) () const ) const
419 {
420 return this->max( std::mem_fn( pmf ) );
421 }
422
423 template<
424 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
425 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
426 >
427 R sum( Unary unary_op = {} ) const
428 {
429 return this->accumulate(
430 R{ 0 },
431 std::plus< R >{},
432 unary_op
433 );
434 }
435
436 template<
437 typename R2, typename C,
438 typename R = R2
439 >
440 R sum( R2 (C :: * pmf) () const ) const
441 {
442 return this->sum( std::mem_fn( pmf ) );
443 }
444};
445
446template< typename Iterator>
448make_iterator_range( const Iterator &i1, const Iterator &i2 )
449{
450 return { i1, i2 };
451}
452
453template< typename Container >
455make_iterator_range( Container &container )
456{
457 return { container.begin(), container.end() };
458}
459
460template< typename Container >
462make_iterator_range( const Container &container )
463{
464 return { container.begin(), container.end() };
465}
466
467// A utility function building a container of results
468template< typename Container, typename Iterator, typename Function >
469Container transform_range( Iterator first, Iterator last, Function &&fn )
470{
471 Container result;
472 std::transform( first, last, std::back_inserter( result ), fn );
473 return result;
474}
475// A utility function, often constructing a vector from another vector
476template< typename OutContainer, typename InContainer, typename Function >
477OutContainer transform_container( InContainer &inContainer, Function &&fn )
478{
479 return transform_range<OutContainer>(
480 inContainer.begin(), inContainer.end(), fn );
481}
482
484
488struct UTILITY_API alignas(
489#if defined(_WIN32) && defined(_MSC_VER)
490 // MSVC supports this symbol in std, but MinGW uses libstdc++, which it does not.
491 std::hardware_destructive_interference_size
492#else
493 // That constant isn't defined for the other builds yet
494 64 /* ? */
495#endif
496)
497
498NonInterferingBase {
499 static void *operator new(std::size_t count, std::align_val_t al);
500 static void operator delete(void *ptr, std::align_val_t al);
501
502#if defined (_MSC_VER) && defined(_DEBUG)
503 // Versions that work in the presence of the DEBUG_NEW macro.
504 // Ignore the arguments supplied by the macro and forward to the
505 // other overloads.
506 static void *operator new(
507 std::size_t count, std::align_val_t al, int, const char *, int)
508 { return operator new(count, al); }
509 static void operator delete(
510 void *ptr, std::align_val_t al, int, const char *, int)
511 { return operator delete(ptr, al); }
512#endif
513};
514
516
519template<typename T> // CRTP
520struct SharedNonInterfering : NonInterferingBase
521{
522 template<typename... Args>
523 static std::shared_ptr<T> make_shared(Args &&...args)
524 {
525 return std::
526#ifdef __APPLE__
527 // shared_ptr must be constructed from unique_ptr on Mac
528 make_unique
529#else
531#endif
532 <T>(std::forward<Args>(args)...);
533 }
534};
535
539template< typename T > struct NonInterfering
540 : NonInterferingBase // Inherit operators; use empty base class optimization
541 , T
542{
543 using T::T;
544
546 void Set(const T &other)
547 {
548 T::operator =(other);
549 }
550
552 void Set(T &&other)
553 {
554 T::operator =(std::move(other));
555 }
556};
557
558// These macros are used widely, so declared here.
559#define QUANTIZED_TIME(time, rate) (floor(((double)(time) * (rate)) + 0.5) / (rate))
560// dB - linear amplitude conversions
561#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0))
562#define LINEAR_TO_DB(x) (20.0 * log10(x))
563
564#define MAX_AUDIO (1. - 1./(1<<15))
565
568template<typename T>
569struct AtomicUniquePointer : public std::atomic<T*> {
570 static_assert(AtomicUniquePointer::is_always_lock_free);
571 using std::atomic<T*>::atomic;
574
576 void reset(T *p = nullptr) {
577 delete this->exchange(p, std::memory_order_release);
578 }
580 template<typename... Args> void emplace(Args &&... args) {
581 reset(safenew T(std::forward<Args>(args)...));
582 }
584private:
586 using std::atomic<T*>::fetch_add;
587 using std::atomic<T*>::fetch_sub;
588};
589
590#endif // __AUDACITY_MEMORY_X_H__
int min(int a, int b)
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:251
struct UTILITY_API alignas(64) NonInterferingBase
Non-template helper for class template NonInterfering.
Definition: MemoryX.h:488
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:146
#define safenew
Definition: MemoryX.h:10
Container transform_range(Iterator first, Iterator last, Function &&fn)
Definition: MemoryX.h:469
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:448
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:162
Finally(F) -> Finally< F >
OutContainer transform_container(InContainer &inContainer, Function &&fn)
Definition: MemoryX.h:477
std::unique_ptr< T, freer > MallocPtr
Definition: MemoryX.h:140
static const auto fn
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Definition: MemoryX.h:27
ArrayOf(ArrayOf &&that)
Definition: MemoryX.h:40
ArrayOf(const ArrayOf &)=delete
ArrayOf()
Definition: MemoryX.h:29
ArrayOf & operator=(ArrayOf &&that)
Definition: MemoryX.h:45
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
ArrayOf(Integral count, bool initialize=false)
Definition: MemoryX.h:32
void reinit(Integral count)
Definition: MemoryX.h:109
ArraysOf(Integral1 N, Integral2 M, bool initialize=false)
Definition: MemoryX.h:91
ArraysOf(const ArraysOf &)=delete
ArraysOf & operator=(ArraysOf &&that)
Definition: MemoryX.h:102
ArraysOf()
Definition: MemoryX.h:83
void reinit(Integral1 countN, Integral2 countM, bool initialize=false)
Definition: MemoryX.h:121
ArraysOf(Integral N)
Definition: MemoryX.h:86
void reinit(Integral count, bool initialize)
Definition: MemoryX.h:115
Set a variable temporarily in a scope.
Definition: MemoryX.h:212
ValueRestorer(T &var, const T &newValue)
Definition: MemoryX.h:219
ValueRestorer(T &var)
Definition: MemoryX.h:216
ValueRestorer & operator=(ValueRestorer &&that)
Definition: MemoryX.h:224
ValueRestorer(ValueRestorer &&that)
Definition: MemoryX.h:222
void free(void *ptr)
Definition: VectorOps.h:27
STL namespace.
void reset(T *p=nullptr)
Definition: MemoryX.h:576
void emplace(Args &&... args)
reset to a pointer to a new object with given ctor arguments
Definition: MemoryX.h:580
std::shared_ptr< T > pointer
Definition: MemoryX.h:246
CopyableValueRestorer(T &var, const T &newValue)
Definition: MemoryX.h:240
CopyableValueRestorer(T &var)
Definition: MemoryX.h:237
A deleter class to supply the second template parameter of unique_ptr for classes like wxWindow that ...
Definition: MemoryX.h:154
void operator()(T *p) const
Definition: MemoryX.h:155
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Definition: MemoryX.h:173
Finally(F f)
Definition: MemoryX.h:174
F clean
Definition: MemoryX.h:176
~Finally()
Definition: MemoryX.h:175
const T && operator()(T &&v) const
Definition: MemoryX.h:341
A convenience for use with range-for.
Definition: MemoryX.h:277
R accumulate(R init, Binary binary_op, R2(C ::*pmf)() const) const
Definition: MemoryX.h:369
bool contains(const T &t) const
Definition: MemoryX.h:311
bool empty() const
Definition: MemoryX.h:296
R sum(R2(C ::*pmf)() const) const
Definition: MemoryX.h:440
R sum(Unary unary_op={}) const
Definition: MemoryX.h:427
R accumulate(R init, Binary binary_op={}, Unary unary_op={}) const
Definition: MemoryX.h:350
bool all_of(const F &f) const
Definition: MemoryX.h:326
std::reverse_iterator< Iterator > reverse_iterator
Definition: MemoryX.h:279
iterator find_if(const F &f) const
Definition: MemoryX.h:314
iterator find(const T &t) const
Definition: MemoryX.h:300
IteratorRange(Iterator &&a, Iterator &&b)
Definition: MemoryX.h:284
long index(const T &t) const
Definition: MemoryX.h:303
R max(Unary unary_op={}) const
Definition: MemoryX.h:405
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:287
R min(R2(C ::*pmf)() const) const
Definition: MemoryX.h:396
Iterator end() const
Definition: MemoryX.h:291
bool any_of(const F &f) const
Definition: MemoryX.h:334
Iterator iterator
Definition: MemoryX.h:278
long index_if(const F &f) const
Definition: MemoryX.h:317
reverse_iterator rend() const
Definition: MemoryX.h:294
bool none_of(const F &f) const
Definition: MemoryX.h:337
Iterator begin() const
Definition: MemoryX.h:290
size_t size() const
Definition: MemoryX.h:298
R min(Unary unary_op={}) const
Definition: MemoryX.h:383
IteratorRange(const Iterator &a, const Iterator &b)
Definition: MemoryX.h:281
reverse_iterator rbegin() const
Definition: MemoryX.h:293
R max(R2(C ::*pmf)() const) const
Definition: MemoryX.h:418
void Set(T &&other)
Allow assignment from default-aligned base type.
Definition: MemoryX.h:552
void Set(const T &other)
Allow assignment from default-aligned base type.
Definition: MemoryX.h:546
Structure used by ValueRestorer.
Definition: MemoryX.h:201
void operator()(T *p) const
Definition: MemoryX.h:203
Workaround for std::make_shared not working on macOs with over-alignment.
Definition: MemoryX.h:521
static std::shared_ptr< T > make_shared(Args &&...args)
Definition: MemoryX.h:523
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:263
ptrdiff_t difference_type
Definition: MemoryX.h:266
const Value reference
Definition: MemoryX.h:270
void pointer
Definition: MemoryX.h:268
Category iterator_category
Definition: MemoryX.h:264
Value value_type
Definition: MemoryX.h:265
Definition: MemoryX.h:134
void operator()(void *p) const
Definition: MemoryX.h:134