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
233template< typename T >
235{ return ValueRestorer< T >{ var }; }
236
237template< typename T >
238ValueRestorer< T > valueRestorer( T& var, const T& newValue )
239{ return ValueRestorer< T >{ var, newValue }; }
240
245template< typename Value, typename Category = std::forward_iterator_tag >
247 using iterator_category = Category;
248 using value_type = Value;
249 using difference_type = ptrdiff_t;
250 // void pointer type so that operator -> is disabled
251 using pointer = void;
252 // make "reference type" really the same as the value type
253 using reference = const Value;
254};
255
259template <typename Iterator>
260struct IteratorRange : public std::pair<Iterator, Iterator> {
261 using iterator = Iterator;
262 using reverse_iterator = std::reverse_iterator<Iterator>;
263
264 IteratorRange (const Iterator &a, const Iterator &b)
265 : std::pair<Iterator, Iterator> ( a, b ) {}
266
267 IteratorRange (Iterator &&a, Iterator &&b)
268 : std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}
269
271 { return { this->rbegin(), this->rend() }; }
272
273 Iterator begin() const { return this->first; }
274 Iterator end() const { return this->second; }
275
276 reverse_iterator rbegin() const { return reverse_iterator{ this->second }; }
277 reverse_iterator rend() const { return reverse_iterator{ this->first }; }
278
279 bool empty() const { return this->begin() == this->end(); }
280 explicit operator bool () const { return !this->empty(); }
281 size_t size() const { return std::distance(this->begin(), this->end()); }
282
283 template <typename T> iterator find(const T &t) const
284 { return std::find(this->begin(), this->end(), t); }
285
286 template <typename T> long index(const T &t) const
287 {
288 auto iter = this->find(t);
289 if (iter == this->end())
290 return -1;
291 return std::distance(this->begin(), iter);
292 }
293
294 template <typename T> bool contains(const T &t) const
295 { return this->end() != this->find(t); }
296
297 template <typename F> iterator find_if(const F &f) const
298 { return std::find_if(this->begin(), this->end(), f); }
299
300 template <typename F> long index_if(const F &f) const
301 {
302 auto iter = this->find_if(f);
303 if (iter == this->end())
304 return -1;
305 return std::distance(this->begin(), iter);
306 }
307
308 // to do: use std::all_of, any_of, none_of when available on all platforms
309 template <typename F> bool all_of(const F &f) const
310 {
311 auto notF =
312 [&](typename std::iterator_traits<Iterator>::reference v)
313 { return !f(v); };
314 return !this->any_of( notF );
315 }
316
317 template <typename F> bool any_of(const F &f) const
318 { return this->end() != this->find_if(f); }
319
320 template <typename F> bool none_of(const F &f) const
321 { return !this->any_of(f); }
322
323 template<typename T> struct identity
324 { const T&& operator () (T &&v) const { return std::forward(v); } };
325
326 // Like std::accumulate, but the iterators implied, and with another
327 // unary operation on the iterator value, pre-composed
328 template<
329 typename R,
330 typename Binary = std::plus< R >,
332 >
334 R init,
335 Binary binary_op = {},
336 Unary unary_op = {}
337 ) const
338 {
339 R result = init;
340 for (auto&& v : *this)
341 result = binary_op(result, unary_op(v));
342 return result;
343 }
344
345 // An overload making it more convenient to use with pointers to member
346 // functions
347 template<
348 typename R,
349 typename Binary = std::plus< R >,
350 typename R2, typename C
351 >
353 R init,
354 Binary binary_op,
355 R2 (C :: * pmf) () const
356 ) const
357 {
358 return this->accumulate( init, binary_op, std::mem_fn( pmf ) );
359 }
360
361 // Some accumulations frequent enough to be worth abbreviation:
362 template<
363 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
364 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
365 >
366 R min( Unary unary_op = {} ) const
367 {
368 return this->accumulate(
369 std::numeric_limits< R >::max(),
370 (const R&(*)(const R&, const R&)) std::min,
371 unary_op
372 );
373 }
374
375 template<
376 typename R2, typename C,
377 typename R = R2
378 >
379 R min( R2 (C :: * pmf) () const ) const
380 {
381 return this->min( std::mem_fn( pmf ) );
382 }
383
384 template<
385 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
386 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
387 >
388 R max( Unary unary_op = {} ) const
389 {
390 return this->accumulate(
391 std::numeric_limits< R >::lowest(),
392 (const R&(*)(const R&, const R&)) std::max,
393 unary_op
394 );
395 }
396
397 template<
398 typename R2, typename C,
399 typename R = R2
400 >
401 R max( R2 (C :: * pmf) () const ) const
402 {
403 return this->max( std::mem_fn( pmf ) );
404 }
405
406 template<
407 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
408 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
409 >
410 R sum( Unary unary_op = {} ) const
411 {
412 return this->accumulate(
413 R{ 0 },
414 std::plus< R >{},
415 unary_op
416 );
417 }
418
419 template<
420 typename R2, typename C,
421 typename R = R2
422 >
423 R sum( R2 (C :: * pmf) () const ) const
424 {
425 return this->sum( std::mem_fn( pmf ) );
426 }
427};
428
429template< typename Iterator>
431make_iterator_range( const Iterator &i1, const Iterator &i2 )
432{
433 return { i1, i2 };
434}
435
436template< typename Container >
438make_iterator_range( Container &container )
439{
440 return { container.begin(), container.end() };
441}
442
443template< typename Container >
445make_iterator_range( const Container &container )
446{
447 return { container.begin(), container.end() };
448}
449
450// A utility function building a container of results
451template< typename Container, typename Iterator, typename Function >
452Container transform_range( Iterator first, Iterator last, Function &&fn )
453{
454 Container result;
455 std::transform( first, last, std::back_inserter( result ), fn );
456 return result;
457}
458// A utility function, often constructing a vector from another vector
459template< typename OutContainer, typename InContainer, typename Function >
460OutContainer transform_container( InContainer &inContainer, Function &&fn )
461{
462 return transform_range<OutContainer>(
463 inContainer.begin(), inContainer.end(), fn );
464}
465
467
471struct UTILITY_API alignas(
472#ifdef __WIN32__
473 std::hardware_destructive_interference_size
474#else
475 // That constant isn't defined for the other builds yet
476 64 /* ? */
477#endif
478)
479
480NonInterferingBase {
481 static void *operator new(std::size_t count, std::align_val_t al);
482 static void operator delete(void *ptr, std::align_val_t al);
483
484#if defined (_MSC_VER) && defined(_DEBUG)
485 // Versions that work in the presence of the DEBUG_NEW macro.
486 // Ignore the arguments supplied by the macro and forward to the
487 // other overloads.
488 static void *operator new(
489 std::size_t count, std::align_val_t al, int, const char *, int)
490 { return operator new(count, al); }
491 static void operator delete(
492 void *ptr, std::align_val_t al, int, const char *, int)
493 { return operator delete(ptr, al); }
494#endif
495};
496
498
501template<typename T> // CRTP
502struct SharedNonInterfering : NonInterferingBase
503{
504 template<typename... Args>
505 static std::shared_ptr<T> make_shared(Args &&...args)
506 {
507 return std::
508#ifdef __APPLE__
509 // shared_ptr must be constructed from unique_ptr on Mac
510 make_unique
511#else
513#endif
514 <T>(std::forward<Args>(args)...);
515 }
516};
517
521template< typename T > struct NonInterfering
522 : NonInterferingBase // Inherit operators; use empty base class optimization
523 , T
524{
525 using T::T;
526
528 void Set(const T &other)
529 {
530 T::operator =(other);
531 }
532
534 void Set(T &&other)
535 {
536 T::operator =(std::move(other));
537 }
538};
539
540// These macros are used widely, so declared here.
541#define QUANTIZED_TIME(time, rate) (floor(((double)(time) * (rate)) + 0.5) / (rate))
542// dB - linear amplitude conversions
543#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0))
544#define LINEAR_TO_DB(x) (20.0 * log10(x))
545
546#define MAX_AUDIO (1. - 1./(1<<15))
547
548#include <type_traits>
549#include <variant>
550#include <stdexcept>
551
553template <typename Visitor, typename Variant>
555 using Var = std::remove_reference_t<Variant>;
556 using Alt = std::variant_alternative_t<0, Var>;
557 using QAlt = std::conditional_t<
558 std::is_const_v<Var>, const Alt, Alt >;
559 using Arg = std::conditional_t<std::is_lvalue_reference_v<Variant>,
560 std::add_lvalue_reference_t<QAlt>, std::add_rvalue_reference_t<QAlt>
561 >;
562 // All this just so that the noreturn function below has an appropriate type
563 using type = decltype( std::invoke(
564 std::forward<Visitor>( std::declval<Visitor>() ),
565 std::declval<Arg>() ) );
566};
567
569template <typename Visitor, typename Variant>
570[[noreturn]] auto VisitHelper(Visitor &&, Variant &&)
572{
573 // Fall through here when the variant holds no value
574 // Should really throw std::bad_variant_access but that may not be available
575 throw std::invalid_argument{"Bad variant"};
576}
577
579template <size_t Index, size_t... Indices, typename Visitor, typename Variant>
580auto VisitHelper(Visitor &&vis, Variant &&var)
581{
582 // Invoke vis at most once after no-throw testing for presence of
583 // alternatives in the variant
584 if (const auto pValue = std::get_if<Index>(&var)) {
585 if constexpr (std::is_lvalue_reference_v<Variant>)
586 return std::invoke( std::forward<Visitor>(vis), (*pValue) );
587 else
588 return std::invoke( std::forward<Visitor>(vis), std::move(*pValue) );
589 }
590 // Recur down the index value pack
591 return VisitHelper<Indices...>(
592 std::forward<Visitor>(vis), std::forward<Variant>(var));
593}
594
596template <size_t... Indices, typename Visitor, typename Variant>
597auto VisitHelper(std::index_sequence<Indices...>, Visitor &&vis, Variant &&var)
598{
599 // Non-template parameters were deduced and are passed on as non-deduced
600 return VisitHelper<Indices...>(
601 std::forward<Visitor>(vis), std::forward<Variant>(var) );
602}
603
605
610template <typename Visitor, typename Variant>
611auto Visit(Visitor &&vis, Variant &&var)
612{
613 constexpr auto size = std::variant_size_v<std::remove_reference_t<Variant>>;
614 return VisitHelper( std::make_index_sequence<size>{},
615 std::forward<Visitor>(vis), std::forward<Variant>(var) );
616}
617
620template<typename T>
621struct AtomicUniquePointer : public std::atomic<T*> {
622 static_assert(AtomicUniquePointer::is_always_lock_free);
623 using std::atomic<T*>::atomic;
626
628 void reset(T *p = nullptr) {
629 delete this->exchange(p, std::memory_order_release);
630 }
632 template<typename... Args> void emplace(Args &&... args) {
633 reset(safenew T(std::forward<Args>(args)...));
634 }
636private:
638 using std::atomic<T*>::fetch_add;
639 using std::atomic<T*>::fetch_sub;
640};
641
642#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:234
struct UTILITY_API alignas(64) NonInterferingBase
Non-template helper for class template NonInterfering.
Definition: MemoryX.h:471
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
Definition: MemoryX.h:611
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:452
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:431
auto VisitHelper(Visitor &&, Variant &&) -> typename VisitHelperReturn< Visitor, Variant >::type
Help to define Visit() below.
Definition: MemoryX.h:570
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:460
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
STL namespace.
void reset(T *p=nullptr)
Definition: MemoryX.h:628
void emplace(Args &&... args)
reset to a pointer to a new object with given ctor arguments
Definition: MemoryX.h:632
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:324
A convenience for use with range-for.
Definition: MemoryX.h:260
R accumulate(R init, Binary binary_op, R2(C ::*pmf)() const) const
Definition: MemoryX.h:352
bool contains(const T &t) const
Definition: MemoryX.h:294
bool empty() const
Definition: MemoryX.h:279
R sum(R2(C ::*pmf)() const) const
Definition: MemoryX.h:423
R sum(Unary unary_op={}) const
Definition: MemoryX.h:410
R accumulate(R init, Binary binary_op={}, Unary unary_op={}) const
Definition: MemoryX.h:333
bool all_of(const F &f) const
Definition: MemoryX.h:309
std::reverse_iterator< Iterator > reverse_iterator
Definition: MemoryX.h:262
iterator find_if(const F &f) const
Definition: MemoryX.h:297
iterator find(const T &t) const
Definition: MemoryX.h:283
IteratorRange(Iterator &&a, Iterator &&b)
Definition: MemoryX.h:267
long index(const T &t) const
Definition: MemoryX.h:286
R max(Unary unary_op={}) const
Definition: MemoryX.h:388
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:270
R min(R2(C ::*pmf)() const) const
Definition: MemoryX.h:379
Iterator end() const
Definition: MemoryX.h:274
bool any_of(const F &f) const
Definition: MemoryX.h:317
Iterator iterator
Definition: MemoryX.h:261
long index_if(const F &f) const
Definition: MemoryX.h:300
reverse_iterator rend() const
Definition: MemoryX.h:277
bool none_of(const F &f) const
Definition: MemoryX.h:320
Iterator begin() const
Definition: MemoryX.h:273
size_t size() const
Definition: MemoryX.h:281
R min(Unary unary_op={}) const
Definition: MemoryX.h:366
IteratorRange(const Iterator &a, const Iterator &b)
Definition: MemoryX.h:264
reverse_iterator rbegin() const
Definition: MemoryX.h:276
R max(R2(C ::*pmf)() const) const
Definition: MemoryX.h:401
void Set(T &&other)
Allow assignment from default-aligned base type.
Definition: MemoryX.h:534
void Set(const T &other)
Allow assignment from default-aligned base type.
Definition: MemoryX.h:528
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:503
static std::shared_ptr< T > make_shared(Args &&...args)
Definition: MemoryX.h:505
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:246
ptrdiff_t difference_type
Definition: MemoryX.h:249
const Value reference
Definition: MemoryX.h:253
void pointer
Definition: MemoryX.h:251
Category iterator_category
Definition: MemoryX.h:247
Value value_type
Definition: MemoryX.h:248
Help to define Visit() below.
Definition: MemoryX.h:554
std::conditional_t< std::is_const_v< Var >, const Alt, Alt > QAlt
Definition: MemoryX.h:558
decltype(std::invoke(std::forward< Visitor >(std::declval< Visitor >()), std::declval< Arg >())) type
Definition: MemoryX.h:565
std::remove_reference_t< Variant > Var
Definition: MemoryX.h:555
std::conditional_t< std::is_lvalue_reference_v< Variant >, std::add_lvalue_reference_t< QAlt >, std::add_rvalue_reference_t< QAlt > > Arg
Definition: MemoryX.h:561
std::variant_alternative_t< 0, Var > Alt
Definition: MemoryX.h:556
Definition: MemoryX.h:134
void operator()(void *p) const
Definition: MemoryX.h:134