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>
174 Final_action(F f) : clean( f ) {}
177};
178
181template <typename F>
182Final_action<F> finally (F f)
183{
184 return Final_action<F>(f);
185}
186
187#include <algorithm>
188
192template< typename T >
195 void operator () ( T *p ) const { if (p) *p = oldValue; }
196};
197
198
202template< typename T >
203class ValueRestorer : public std::unique_ptr< T, RestoreValue<T> >
204{
205 using std::unique_ptr< T, RestoreValue<T> >::reset; // make private
206 // But release() remains public and can be useful to commit a changed value
207public:
208 explicit ValueRestorer( T &var )
209 : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
210 {}
211 explicit ValueRestorer( T &var, const T& newValue )
212 : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
213 { var = newValue; }
215 : std::unique_ptr < T, RestoreValue<T> > ( std::move(that) ) {};
217 {
218 if (this != &that)
219 std::unique_ptr < T, RestoreValue<T> >::operator=(std::move(that));
220 return *this;
221 }
222};
223
225template< typename T >
227{ return ValueRestorer< T >{ var }; }
228
229template< typename T >
230ValueRestorer< T > valueRestorer( T& var, const T& newValue )
231{ return ValueRestorer< T >{ var, newValue }; }
232
237template< typename Value, typename Category = std::forward_iterator_tag >
239 using iterator_category = Category;
240 using value_type = Value;
241 using difference_type = ptrdiff_t;
242 // void pointer type so that operator -> is disabled
243 using pointer = void;
244 // make "reference type" really the same as the value type
245 using reference = const Value;
246};
247
251template <typename Iterator>
252struct IteratorRange : public std::pair<Iterator, Iterator> {
253 using iterator = Iterator;
254 using reverse_iterator = std::reverse_iterator<Iterator>;
255
256 IteratorRange (const Iterator &a, const Iterator &b)
257 : std::pair<Iterator, Iterator> ( a, b ) {}
258
259 IteratorRange (Iterator &&a, Iterator &&b)
260 : std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}
261
263 { return { this->rbegin(), this->rend() }; }
264
265 Iterator begin() const { return this->first; }
266 Iterator end() const { return this->second; }
267
268 reverse_iterator rbegin() const { return reverse_iterator{ this->second }; }
269 reverse_iterator rend() const { return reverse_iterator{ this->first }; }
270
271 bool empty() const { return this->begin() == this->end(); }
272 explicit operator bool () const { return !this->empty(); }
273 size_t size() const { return std::distance(this->begin(), this->end()); }
274
275 template <typename T> iterator find(const T &t) const
276 { return std::find(this->begin(), this->end(), t); }
277
278 template <typename T> long index(const T &t) const
279 {
280 auto iter = this->find(t);
281 if (iter == this->end())
282 return -1;
283 return std::distance(this->begin(), iter);
284 }
285
286 template <typename T> bool contains(const T &t) const
287 { return this->end() != this->find(t); }
288
289 template <typename F> iterator find_if(const F &f) const
290 { return std::find_if(this->begin(), this->end(), f); }
291
292 template <typename F> long index_if(const F &f) const
293 {
294 auto iter = this->find_if(f);
295 if (iter == this->end())
296 return -1;
297 return std::distance(this->begin(), iter);
298 }
299
300 // to do: use std::all_of, any_of, none_of when available on all platforms
301 template <typename F> bool all_of(const F &f) const
302 {
303 auto notF =
304 [&](typename std::iterator_traits<Iterator>::reference v)
305 { return !f(v); };
306 return !this->any_of( notF );
307 }
308
309 template <typename F> bool any_of(const F &f) const
310 { return this->end() != this->find_if(f); }
311
312 template <typename F> bool none_of(const F &f) const
313 { return !this->any_of(f); }
314
315 template<typename T> struct identity
316 { const T&& operator () (T &&v) const { return std::forward(v); } };
317
318 // Like std::accumulate, but the iterators implied, and with another
319 // unary operation on the iterator value, pre-composed
320 template<
321 typename R,
322 typename Binary = std::plus< R >,
324 >
326 R init,
327 Binary binary_op = {},
328 Unary unary_op = {}
329 ) const
330 {
331 R result = init;
332 for (auto&& v : *this)
333 result = binary_op(result, unary_op(v));
334 return result;
335 }
336
337 // An overload making it more convenient to use with pointers to member
338 // functions
339 template<
340 typename R,
341 typename Binary = std::plus< R >,
342 typename R2, typename C
343 >
345 R init,
346 Binary binary_op,
347 R2 (C :: * pmf) () const
348 ) const
349 {
350 return this->accumulate( init, binary_op, std::mem_fn( pmf ) );
351 }
352
353 // Some accumulations frequent enough to be worth abbreviation:
354 template<
355 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
356 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
357 >
358 R min( Unary unary_op = {} ) const
359 {
360 return this->accumulate(
361 std::numeric_limits< R >::max(),
362 (const R&(*)(const R&, const R&)) std::min,
363 unary_op
364 );
365 }
366
367 template<
368 typename R2, typename C,
369 typename R = R2
370 >
371 R min( R2 (C :: * pmf) () const ) const
372 {
373 return this->min( std::mem_fn( pmf ) );
374 }
375
376 template<
377 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
378 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
379 >
380 R max( Unary unary_op = {} ) const
381 {
382 return this->accumulate(
383 std::numeric_limits< R >::lowest(),
384 (const R&(*)(const R&, const R&)) std::max,
385 unary_op
386 );
387 }
388
389 template<
390 typename R2, typename C,
391 typename R = R2
392 >
393 R max( R2 (C :: * pmf) () const ) const
394 {
395 return this->max( std::mem_fn( pmf ) );
396 }
397
398 template<
399 typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
400 typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
401 >
402 R sum( Unary unary_op = {} ) const
403 {
404 return this->accumulate(
405 R{ 0 },
406 std::plus< R >{},
407 unary_op
408 );
409 }
410
411 template<
412 typename R2, typename C,
413 typename R = R2
414 >
415 R sum( R2 (C :: * pmf) () const ) const
416 {
417 return this->sum( std::mem_fn( pmf ) );
418 }
419};
420
421template< typename Iterator>
423make_iterator_range( const Iterator &i1, const Iterator &i2 )
424{
425 return { i1, i2 };
426}
427
428template< typename Container >
430make_iterator_range( Container &container )
431{
432 return { container.begin(), container.end() };
433}
434
435template< typename Container >
437make_iterator_range( const Container &container )
438{
439 return { container.begin(), container.end() };
440}
441
442// A utility function building a container of results
443template< typename Container, typename Iterator, typename Function >
444Container transform_range( Iterator first, Iterator last, Function &&fn )
445{
446 Container result;
447 std::transform( first, last, std::back_inserter( result ), fn );
448 return result;
449}
450// A utility function, often constructing a vector from another vector
451template< typename OutContainer, typename InContainer, typename Function >
452OutContainer transform_container( InContainer &inContainer, Function &&fn )
453{
454 return transform_range<OutContainer>(
455 inContainer.begin(), inContainer.end(), fn );
456}
457
459
463struct UTILITY_API alignas(
464#ifdef __WIN32__
465 std::hardware_destructive_interference_size
466#else
467 // That constant isn't defined for the other builds yet
468 64 /* ? */
469#endif
470)
471
472NonInterferingBase {
473 static void *operator new(std::size_t count, std::align_val_t al);
474 static void operator delete(void *ptr, std::align_val_t al);
475
476#if defined (_MSC_VER) && defined(_DEBUG)
477 // Versions that work in the presence of the DEBUG_NEW macro.
478 // Ignore the arguments supplied by the macro and forward to the
479 // other overloads.
480 static void *operator new(
481 std::size_t count, std::align_val_t al, int, const char *, int)
482 { return operator new(count, al); }
483 static void operator delete(
484 void *ptr, std::align_val_t al, int, const char *, int)
485 { return operator delete(ptr, al); }
486#endif
487};
488
492template< typename T > struct NonInterfering
493 : NonInterferingBase // Inherit operators; use empty base class optimization
494 , T
495{
496 using T::T;
497};
498
499// These macros are used widely, so declared here.
500#define QUANTIZED_TIME(time, rate) (floor(((double)(time) * (rate)) + 0.5) / (rate))
501// dB - linear amplitude conversions
502#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0))
503#define LINEAR_TO_DB(x) (20.0 * log10(x))
504
505#define MAX_AUDIO (1. - 1./(1<<15))
506
507#include <type_traits>
508#include <variant>
509#include <stdexcept>
510
512template <typename Visitor, typename Variant>
514 using Var = std::remove_reference_t<Variant>;
515 using Alt = std::variant_alternative_t<0, Var>;
516 using QAlt = std::conditional_t<
517 std::is_const_v<Var>, const Alt, Alt >;
518 using Arg = std::conditional_t<std::is_lvalue_reference_v<Variant>,
519 std::add_lvalue_reference_t<QAlt>, std::add_rvalue_reference_t<QAlt>
520 >;
521 // All this just so that the noreturn function below has an appropriate type
522 using type = decltype( std::invoke(
523 std::forward<Visitor>( std::declval<Visitor>() ),
524 std::declval<Arg>() ) );
525};
526
528template <typename Visitor, typename Variant>
529[[noreturn]] auto VisitHelper(Visitor &&, Variant &&)
531{
532 // Fall through here when the variant holds no value
533 // Should really throw std::bad_variant_access but that may not be available
534 throw std::invalid_argument{"Bad variant"};
535}
536
538template <size_t Index, size_t... Indices, typename Visitor, typename Variant>
539auto VisitHelper(Visitor &&vis, Variant &&var)
540{
541 // Invoke vis at most once after no-throw testing for presence of
542 // alternatives in the variant
543 if (const auto pValue = std::get_if<Index>(&var)) {
544 if constexpr (std::is_lvalue_reference_v<Variant>)
545 return std::invoke( std::forward<Visitor>(vis), (*pValue) );
546 else
547 return std::invoke( std::forward<Visitor>(vis), std::move(*pValue) );
548 }
549 // Recur down the index value pack
550 return VisitHelper<Indices...>(
551 std::forward<Visitor>(vis), std::forward<Variant>(var));
552}
553
555template <size_t... Indices, typename Visitor, typename Variant>
556auto VisitHelper(std::index_sequence<Indices...>, Visitor &&vis, Variant &&var)
557{
558 // Non-template parameters were deduced and are passed on as non-deduced
559 return VisitHelper<Indices...>(
560 std::forward<Visitor>(vis), std::forward<Variant>(var) );
561}
562
564
569template <typename Visitor, typename Variant>
570auto Visit(Visitor &&vis, Variant &&var)
571{
572 constexpr auto size = std::variant_size_v<std::remove_reference_t<Variant>>;
573 return VisitHelper( std::make_index_sequence<size>{},
574 std::forward<Visitor>(vis), std::forward<Variant>(var) );
575}
576
577#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:226
struct UTILITY_API alignas(64) NonInterferingBase
Non-template helper for class template NonInterfering.
Definition: MemoryX.h:463
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
Definition: MemoryX.h:570
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:444
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:423
auto VisitHelper(Visitor &&, Variant &&) -> typename VisitHelperReturn< Visitor, Variant >::type
Help to define Visit() below.
Definition: MemoryX.h:529
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
Definition: MemoryX.h:162
OutContainer transform_container(InContainer &inContainer, Function &&fn)
Definition: MemoryX.h:452
std::unique_ptr< T, freer > MallocPtr
Definition: MemoryX.h:140
static const auto fn
Memory.h template class for making an array of float, bool, etc.
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
memory.h template class for making an array of arrays.
Definition: MemoryX.h:81
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:204
ValueRestorer(T &var, const T &newValue)
Definition: MemoryX.h:211
ValueRestorer(T &var)
Definition: MemoryX.h:208
ValueRestorer & operator=(ValueRestorer &&that)
Definition: MemoryX.h:216
ValueRestorer(ValueRestorer &&that)
Definition: MemoryX.h:214
STL namespace.
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
Final_action(F f)
Definition: MemoryX.h:174
~Final_action()
Definition: MemoryX.h:175
const T && operator()(T &&v) const
Definition: MemoryX.h:316
A convenience for use with range-for.
Definition: MemoryX.h:252
R accumulate(R init, Binary binary_op, R2(C ::*pmf)() const) const
Definition: MemoryX.h:344
bool contains(const T &t) const
Definition: MemoryX.h:286
bool empty() const
Definition: MemoryX.h:271
R sum(R2(C ::*pmf)() const) const
Definition: MemoryX.h:415
R sum(Unary unary_op={}) const
Definition: MemoryX.h:402
R accumulate(R init, Binary binary_op={}, Unary unary_op={}) const
Definition: MemoryX.h:325
bool all_of(const F &f) const
Definition: MemoryX.h:301
std::reverse_iterator< Iterator > reverse_iterator
Definition: MemoryX.h:254
iterator find_if(const F &f) const
Definition: MemoryX.h:289
iterator find(const T &t) const
Definition: MemoryX.h:275
IteratorRange(Iterator &&a, Iterator &&b)
Definition: MemoryX.h:259
long index(const T &t) const
Definition: MemoryX.h:278
R max(Unary unary_op={}) const
Definition: MemoryX.h:380
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:262
R min(R2(C ::*pmf)() const) const
Definition: MemoryX.h:371
Iterator end() const
Definition: MemoryX.h:266
bool any_of(const F &f) const
Definition: MemoryX.h:309
Iterator iterator
Definition: MemoryX.h:253
long index_if(const F &f) const
Definition: MemoryX.h:292
reverse_iterator rend() const
Definition: MemoryX.h:269
bool none_of(const F &f) const
Definition: MemoryX.h:312
Iterator begin() const
Definition: MemoryX.h:265
size_t size() const
Definition: MemoryX.h:273
R min(Unary unary_op={}) const
Definition: MemoryX.h:358
IteratorRange(const Iterator &a, const Iterator &b)
Definition: MemoryX.h:256
reverse_iterator rbegin() const
Definition: MemoryX.h:268
R max(R2(C ::*pmf)() const) const
Definition: MemoryX.h:393
Structure used by ValueRestorer.
Definition: MemoryX.h:193
void operator()(T *p) const
Definition: MemoryX.h:195
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:238
ptrdiff_t difference_type
Definition: MemoryX.h:241
const Value reference
Definition: MemoryX.h:245
void pointer
Definition: MemoryX.h:243
Category iterator_category
Definition: MemoryX.h:239
Value value_type
Definition: MemoryX.h:240
Help to define Visit() below.
Definition: MemoryX.h:513
std::conditional_t< std::is_const_v< Var >, const Alt, Alt > QAlt
Definition: MemoryX.h:517
decltype(std::invoke(std::forward< Visitor >(std::declval< Visitor >()), std::declval< Arg >())) type
Definition: MemoryX.h:524
std::remove_reference_t< Variant > Var
Definition: MemoryX.h:514
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:520
std::variant_alternative_t< 0, Var > Alt
Definition: MemoryX.h:515
Definition: MemoryX.h:134
void operator()(void *p) const
Definition: MemoryX.h:134