Audacity  2.3.1
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 <cstdlib> // Needed for free.
7 #ifndef safenew
8 #define safenew new
9 #endif
10 
11 
12 #include <functional>
13 
14 #if !(_MSC_VER >= 1800 || __cplusplus >= 201402L)
15 /* replicate the very useful C++14 make_unique for those build environments
16 that don't implement it yet.
17 typical useage:
18 auto p = std::make_unique<Myclass>(ctorArg1, ctorArg2, ... ctorArgN);
19 p->DoSomething();
20 auto q = std::make_unique<Myclass[]>(count);
21 q[0].DoSomethingElse();
22 
23 The first hides naked NEW and DELETE from the source code.
24 The second hides NEW[] and DELETE[]. Both of course ensure destruction if
25 you don't use something like std::move(p) or q.release(). Both expressions require
26 that you identify the type only once, which is brief and less error prone.
27 
28 (Whereas this omission of [] might invite a runtime error:
29 std::unique_ptr<Myclass> q { safenew Myclass[count] }; )
30 
31 Some C++11 tricks needed here are (1) variadic argument lists and
32 (2) making the compile-time dispatch work correctly. You can't have
33 a partially specialized template function, but you get the effect of that
34 by other metaprogramming means.
35 */
36 
37 namespace std {
38  // For overloading resolution
39  template <typename X> struct __make_unique_result {
40  using scalar_case = unique_ptr<X>;
41  };
42 
43  // Partial specialization of the struct for array case
44  template <typename X> struct __make_unique_result<X[]> {
45  using array_case = unique_ptr<X[]>;
46  using element = X;
47  };
48 
49  // Now the scalar version of unique_ptr
50  template<typename X, typename... Args> inline
52  make_unique(Args&&... args)
53  {
55  { safenew X(forward<Args>(args)...) };
56  }
57 
58  // Now the array version of unique_ptr
59  // The compile-time dispatch trick is that the non-existence
60  // of the scalar_case type makes the above overload
61  // unavailable when the template parameter is explicit
62  template<typename X> inline
63  typename __make_unique_result<X>::array_case
64  make_unique(size_t count)
65  {
66  return typename __make_unique_result<X>::array_case
67  { safenew typename __make_unique_result<X>::element[count] };
68  }
69 }
70 #endif
71 
72 /*
73  * ArrayOf<X>
74  * Not to be confused with std::array (which takes a fixed size) or std::vector
75  * This maintains a pointer allocated by NEW X[]. It's cheap: only one pointer,
76  * with no size and capacity information for resizing as for vector, and if X is
77  * a built-in numeric or pointer type, by default there is no zero filling at
78  * allocation time.
79  */
80 
81 template<typename X>
82 class ArrayOf : public std::unique_ptr<X[]>
83 {
84 public:
85  ArrayOf() {}
86 
87  template<typename Integral>
88  explicit ArrayOf(Integral count, bool initialize = false)
89  {
90  static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
91  reinit(count, initialize);
92  }
93 
94  //ArrayOf(const ArrayOf&) PROHIBITED;
95  ArrayOf(const ArrayOf&) = delete;
96  ArrayOf(ArrayOf&& that)
97  : std::unique_ptr < X[] >
98  (std::move((std::unique_ptr < X[] >&)(that)))
99  {
100  }
102  {
103  std::unique_ptr<X[]>::operator=(std::move(that));
104  return *this;
105  }
106  ArrayOf& operator= (std::unique_ptr<X[]> &&that)
107  {
108  std::unique_ptr<X[]>::operator=(std::move(that));
109  return *this;
110  }
111 
112  template< typename Integral >
113  void reinit(Integral count,
114  bool initialize = false)
115  {
116  static_assert(std::is_unsigned<Integral>::value, "Unsigned arguments only");
117  if (initialize)
118  // Initialize elements (usually, to zero for a numerical type)
119  std::unique_ptr<X[]>::reset(safenew X[count]{});
120  else
121  // Avoid the slight initialization overhead
122  std::unique_ptr<X[]>::reset(safenew X[count]);
123  }
124 };
125 
126 /*
127  * ArraysOf<X>
128  * This simplifies arrays of arrays, each array separately allocated with NEW[]
129  * But it might be better to use std::Array<ArrayOf<X>, N> for some small constant N
130  * Or use just one array when sub-arrays have a common size and are not large.
131  */
132 template<typename X>
133 class ArraysOf : public ArrayOf<ArrayOf<X>>
134 {
135 public:
136  ArraysOf() {}
137 
138  template<typename Integral>
139  explicit ArraysOf(Integral N)
140  : ArrayOf<ArrayOf<X>>( N )
141  {}
142 
143  template<typename Integral1, typename Integral2 >
144  ArraysOf(Integral1 N, Integral2 M, bool initialize = false)
145  : ArrayOf<ArrayOf<X>>( N )
146  {
147  static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
148  static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
149  for (size_t ii = 0; ii < N; ++ii)
150  (*this)[ii] = ArrayOf<X>{ M, initialize };
151  }
152 
153  //ArraysOf(const ArraysOf&) PROHIBITED;
154  ArraysOf(const ArraysOf&) =delete;
156  {
157  ArrayOf<ArrayOf<X>>::operator=(std::move(that));
158  return *this;
159  }
160 
161  template< typename Integral >
162  void reinit(Integral count)
163  {
164  ArrayOf<ArrayOf<X>>::reinit( count );
165  }
166 
167  template< typename Integral >
168  void reinit(Integral count, bool initialize)
169  {
170  ArrayOf<ArrayOf<X>>::reinit( count, initialize );
171  }
172 
173  template<typename Integral1, typename Integral2 >
174  void reinit(Integral1 countN, Integral2 countM, bool initialize = false)
175  {
176  static_assert(std::is_unsigned<Integral1>::value, "Unsigned arguments only");
177  static_assert(std::is_unsigned<Integral2>::value, "Unsigned arguments only");
178  reinit(countN, false);
179  for (size_t ii = 0; ii < countN; ++ii)
180  (*this)[ii].reinit(countM, initialize);
181  }
182 };
183 
184 /*
185  * template class Maybe<X>
186  * Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed.
187  * You might also use it as a member.
188  * Initialize with create(), then use like a smart pointer,
189  * with *, ->, get(), reset(), or in if()
190  */
191 
192 // Placement-NEW is used below, and that does not cooperate with the DEBUG_NEW for Visual Studio
193 #ifdef _DEBUG
194 #ifdef _MSC_VER
195 #undef new
196 #endif
197 #endif
198 
199 template<typename X>
200 class Maybe {
201 public:
202 
203  // Construct as NULL
204  Maybe() {}
205 
206  // Supply the copy and move, so you might use this as a class member too
207  Maybe(const Maybe &that)
208  {
209  if (that.get())
210  create(*that);
211  }
212 
213  Maybe& operator= (const Maybe &that)
214  {
215  if (this != &that) {
216  if (that.get())
217  create(*that);
218  else
219  reset();
220  }
221  return *this;
222  }
223 
224  Maybe(Maybe &&that)
225  {
226  if (that.get())
227  create(::std::move(*that));
228  }
229 
231  {
232  if (this != &that) {
233  if (that.get())
234  create(::std::move(*that));
235  else
236  reset();
237  }
238  return *this;
239  }
240 
241  // Make an object in the buffer, passing constructor arguments,
242  // but destroying any previous object first
243  // Note that if constructor throws, we remain in a consistent
244  // NULL state -- giving exception safety but only weakly
245  // (previous value was lost if present)
246  template<typename... Args>
247  void create(Args&&... args)
248  {
249  // Lose any old value
250  reset();
251  // Create NEW value
252  pp = safenew(address()) X(std::forward<Args>(args)...);
253  }
254 
255  // Destroy any object that was built in it
257  {
258  reset();
259  }
260 
261  // Pointer-like operators
262 
263  // Dereference, with the usual bad consequences if NULL
264  X &operator* () const
265  {
266  return *pp;
267  }
268 
269  X *operator-> () const
270  {
271  return pp;
272  }
273 
274  X* get() const
275  {
276  return pp;
277  }
278 
279  void reset()
280  {
281  if (pp)
282  pp->~X(), pp = nullptr;
283  }
284 
285  // So you can say if(ptr)
286  explicit operator bool() const
287  {
288  return pp != nullptr;
289  }
290 
291 private:
292  X* address()
293  {
294  return reinterpret_cast<X*>(&storage);
295  }
296 
297  // Data
298 #if 0
299  typename ::std::aligned_storage<
300  sizeof(X)
301  // , alignof(X) // Not here yet in all compilers
302  >::type storage{};
303 #else
304  union {
305  double d;
306  char storage[sizeof(X)];
307  };
308 #endif
309  X* pp{ nullptr };
310 };
311 
312 // Restore definition of debug new
313 #ifdef _DEBUG
314 #ifdef _MSC_VER
315 #undef THIS_FILE
316 static char*THIS_FILE = __FILE__;
317 #define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__)
318 #endif
319 #endif
320 
321 /*
322  * A deleter for pointers obtained with malloc
323  */
324 struct freer { void operator() (void *p) const { free(p); } };
325 
326 /*
327  * A useful alias for holding the result of malloc
328  */
329 template< typename T >
330 using MallocPtr = std::unique_ptr< T, freer >;
331 
332 /*
333  * A useful alias for holding the result of strup and similar
334  */
335 template <typename Character = char>
336 using MallocString = std::unique_ptr< Character[], freer >;
337 
338 /*
339  * A deleter class to supply the second template parameter of unique_ptr for
340  * classes like wxWindow that should be sent a message called Destroy rather
341  * than be deleted directly
342  */
343 template <typename T>
344 struct Destroyer {
345  void operator () (T *p) const { if (p) p->Destroy(); }
346 };
347 
348 /*
349  * a convenience for using Destroyer
350  */
351 template <typename T>
352 using Destroy_ptr = std::unique_ptr<T, Destroyer<T>>;
353 
354 /*
355  * "finally" as in The C++ Programming Language, 4th ed., p. 358
356  * Useful for defining ad-hoc RAII actions.
357  * typical usage:
358  * auto cleanup = finally([&]{ ... code; ... });
359  */
360 
361 // Construct this from any copyable function object, such as a lambda
362 template <typename F>
363 struct Final_action {
364  Final_action(F f) : clean( f ) {}
366  F clean;
367 };
368 
369 // Function template with type deduction lets you construct Final_action
370 // without typing any angle brackets
371 template <typename F>
372 Final_action<F> finally (F f)
373 {
374  return Final_action<F>(f);
375 }
376 
377 #include <wx/utils.h> // for wxMin, wxMax
378 #include <algorithm>
379 
380 /*
381  * Set a variable temporarily in a scope
382  */
383 template< typename T >
384 struct RestoreValue {
386  void operator () ( T *p ) const { if (p) *p = oldValue; }
387 };
388 
389 template< typename T >
390 class ValueRestorer : public std::unique_ptr< T, RestoreValue<T> >
391 {
392  using std::unique_ptr< T, RestoreValue<T> >::reset; // make private
393  // But release() remains public and can be useful to commit a changed value
394 public:
395  explicit ValueRestorer( T &var )
396  : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
397  {}
398  explicit ValueRestorer( T &var, const T& newValue )
399  : std::unique_ptr< T, RestoreValue<T> >( &var, { var } )
400  { var = newValue; }
402  : std::unique_ptr < T, RestoreValue<T> > ( std::move(that) ) {};
404  {
405  if (this != &that)
406  std::unique_ptr < T, RestoreValue<T> >::operator=(std::move(that));
407  return *this;
408  }
409 };
410 
411 // inline functions provide convenient parameter type deduction
412 template< typename T >
414 { return ValueRestorer< T >{ var }; }
415 
416 template< typename T >
417 ValueRestorer< T > valueRestorer( T& var, const T& newValue )
418 { return ValueRestorer< T >{ var, newValue }; }
419 
420 /*
421  * A convenience for use with range-for
422  */
423 template <typename Iterator>
424 struct IteratorRange : public std::pair<Iterator, Iterator> {
425  using iterator = Iterator;
426  using reverse_iterator = std::reverse_iterator<Iterator>;
427 
428  IteratorRange (const Iterator &a, const Iterator &b)
429  : std::pair<Iterator, Iterator> ( a, b ) {}
430 
431  IteratorRange (Iterator &&a, Iterator &&b)
432  : std::pair<Iterator, Iterator> ( std::move(a), std::move(b) ) {}
433 
435  { return { this->rbegin(), this->rend() }; }
436 
437  Iterator begin() const { return this->first; }
438  Iterator end() const { return this->second; }
439 
440  reverse_iterator rbegin() const { return reverse_iterator{ this->second }; }
441  reverse_iterator rend() const { return reverse_iterator{ this->first }; }
442 
443  bool empty() const { return this->begin() == this->end(); }
444  explicit operator bool () const { return !this->empty(); }
445  size_t size() const { return std::distance(this->begin(), this->end()); }
446 
447  template <typename T> iterator find(const T &t) const
448  { return std::find(this->begin(), this->end(), t); }
449 
450  template <typename T> long index(const T &t) const
451  {
452  auto iter = this->find(t);
453  if (iter == this->end())
454  return -1;
455  return std::distance(this->begin(), iter);
456  }
457 
458  template <typename T> bool contains(const T &t) const
459  { return this->end() != this->find(t); }
460 
461  template <typename F> iterator find_if(const F &f) const
462  { return std::find_if(this->begin(), this->end(), f); }
463 
464  template <typename F> long index_if(const F &f) const
465  {
466  auto iter = this->find_if(f);
467  if (iter == this->end())
468  return -1;
469  return std::distance(this->begin(), iter);
470  }
471 
472  // to do: use std::all_of, any_of, none_of when available on all platforms
473  template <typename F> bool all_of(const F &f) const
474  {
475  auto notF =
476  [&](typename std::iterator_traits<Iterator>::reference v)
477  { return !f(v); };
478  return !this->any_of( notF );
479  }
480 
481  template <typename F> bool any_of(const F &f) const
482  { return this->end() != this->find_if(f); }
483 
484  template <typename F> bool none_of(const F &f) const
485  { return !this->any_of(f); }
486 
487  template<typename T> struct identity
488  { const T&& operator () (T &&v) const { return std::forward(v); } };
489 
490  // Like std::accumulate, but the iterators implied, and with another
491  // unary operation on the iterator value, pre-composed
492  template<
493  typename R,
494  typename Binary = std::plus< R >,
495  typename Unary = identity< decltype( *std::declval<Iterator>() ) >
496  >
498  R init,
499  Binary binary_op = {},
500  Unary unary_op = {}
501  ) const
502  {
503  R result = init;
504  for (auto&& v : *this)
505  result = binary_op(result, unary_op(v));
506  return result;
507  }
508 
509  // An overload making it more convenient to use with pointers to member
510  // functions
511  template<
512  typename R,
513  typename Binary = std::plus< R >,
514  typename R2, typename C
515  >
517  R init,
518  Binary binary_op,
519  R2 (C :: * pmf) () const
520  ) const
521  {
522  return this->accumulate( init, binary_op, std::mem_fn( pmf ) );
523  }
524 
525  // Some accumulations frequent enough to be worth abbreviation:
526  template<
527  typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
528  typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
529  >
530  R min( Unary unary_op = {} ) const
531  {
532  return this->accumulate(
533  std::numeric_limits< R >::max(),
534  (const R&(*)(const R&, const R&)) std::min,
535  unary_op
536  );
537  }
538 
539  template<
540  typename R2, typename C,
541  typename R = R2
542  >
543  R min( R2 (C :: * pmf) () const ) const
544  {
545  return this->min( std::mem_fn( pmf ) );
546  }
547 
548  template<
549  typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
550  typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
551  >
552  R max( Unary unary_op = {} ) const
553  {
554  return this->accumulate(
555  std::numeric_limits< R >::lowest(),
556  (const R&(*)(const R&, const R&)) std::max,
557  unary_op
558  );
559  }
560 
561  template<
562  typename R2, typename C,
563  typename R = R2
564  >
565  R max( R2 (C :: * pmf) () const ) const
566  {
567  return this->max( std::mem_fn( pmf ) );
568  }
569 
570  template<
571  typename Unary = identity< decltype( *std::declval<Iterator>() ) >,
572  typename R = decltype( std::declval<Unary>()( *std::declval<Iterator>() ) )
573  >
574  R sum( Unary unary_op = {} ) const
575  {
576  return this->accumulate(
577  R{ 0 },
578  std::plus< R >{},
579  unary_op
580  );
581  }
582 
583  template<
584  typename R2, typename C,
585  typename R = R2
586  >
587  R sum( R2 (C :: * pmf) () const ) const
588  {
589  return this->sum( std::mem_fn( pmf ) );
590  }
591 };
592 
593 template< typename Iterator>
595 make_iterator_range( const Iterator &i1, const Iterator &i2 )
596 {
597  return { i1, i2 };
598 }
599 
600 template< typename Container >
602 make_iterator_range( Container &container )
603 {
604  return { container.begin(), container.end() };
605 }
606 
607 template< typename Container >
609 make_iterator_range( const Container &container )
610 {
611  return { container.begin(), container.end() };
612 }
613 
614 #if !wxCHECK_VERSION(3, 1, 0)
615 // For using std::unordered_map on wxString
616 namespace std
617 {
618  template<typename T> struct hash;
619  template<> struct hash< wxString > {
620  size_t operator () (const wxString &str) const // noexcept
621  {
622  auto stdstr = str.ToStdWstring(); // no allocations, a cheap fetch
623  using Hasher = hash< decltype(stdstr) >;
624  return Hasher{}( stdstr );
625  }
626  };
627 }
628 #endif
629 
630 #endif // __AUDACITY_MEMORY_X_H__
Maybe & operator=(const Maybe &that)
Definition: MemoryX.h:213
void operator()(T *p) const
Definition: MemoryX.h:386
R min(R2(C::*pmf)() const ) const
Definition: MemoryX.h:543
memory.h template class for making an array of arrays.
Definition: MemoryX.h:133
bool contains(const T &t) const
Definition: MemoryX.h:458
reverse_iterator rend() const
Definition: MemoryX.h:441
iterator find(const T &t) const
Definition: MemoryX.h:447
reverse_iterator rbegin() const
Definition: MemoryX.h:440
const T && operator()(T &&v) const
Definition: MemoryX.h:488
IteratorRange(Iterator &&a, Iterator &&b)
Definition: MemoryX.h:431
bool none_of(const F &f) const
Definition: MemoryX.h:484
char storage[sizeof(X)]
Definition: MemoryX.h:306
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:113
X * address()
Definition: MemoryX.h:292
R min(Unary unary_op={}) const
Definition: MemoryX.h:530
ArraysOf(Integral1 N, Integral2 M, bool initialize=false)
Definition: MemoryX.h:144
Final_action(F f)
Definition: MemoryX.h:364
void reinit(Integral count, bool initialize)
Definition: MemoryX.h:168
~Maybe()
Definition: MemoryX.h:256
Definition: MemoryX.h:200
ArrayOf & operator=(ArrayOf &&that)
Definition: MemoryX.h:101
R accumulate(R init, Binary binary_op={}, Unary unary_op={}) const
Definition: MemoryX.h:497
void reset()
Definition: MemoryX.h:279
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:434
bool any_of(const F &f) const
Definition: MemoryX.h:481
iterator find_if(const F &f) const
Definition: MemoryX.h:461
std::unique_ptr< Character[], freer > MallocString
Definition: MemoryX.h:336
~Final_action()
Definition: MemoryX.h:365
R accumulate(R init, Binary binary_op, R2(C::*pmf)() const ) const
Definition: MemoryX.h:516
Iterator begin() const
Definition: MemoryX.h:437
ArrayOf(Integral count, bool initialize=false)
Definition: MemoryX.h:88
IteratorRange(const Iterator &a, const Iterator &b)
Definition: MemoryX.h:428
unique_ptr< X > scalar_case
Definition: MemoryX.h:40
ValueRestorer & operator=(ValueRestorer &&that)
Definition: MemoryX.h:403
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:595
bool empty() const
Definition: MemoryX.h:443
Maybe(const Maybe &that)
Definition: MemoryX.h:207
R sum(R2(C::*pmf)() const ) const
Definition: MemoryX.h:587
int min(int a, int b)
X * operator->() const
Definition: MemoryX.h:269
double d
Definition: MemoryX.h:305
ArrayOf(ArrayOf &&that)
Definition: MemoryX.h:96
R sum(Unary unary_op={}) const
Definition: MemoryX.h:574
ArraysOf & operator=(ArraysOf &&that)
Definition: MemoryX.h:155
ArraysOf(Integral N)
Definition: MemoryX.h:139
X & operator*() const
Definition: MemoryX.h:264
ValueRestorer< T > valueRestorer(T &var)
Definition: MemoryX.h:413
R max(R2(C::*pmf)() const ) const
Definition: MemoryX.h:565
Definition: MemoryX.h:324
void reinit(Integral count)
Definition: MemoryX.h:162
Memory.h template class for making an array of float, bool, etc.
Definition: MemoryX.h:82
long index(const T &t) const
Definition: MemoryX.h:450
Maybe()
Definition: MemoryX.h:204
long index_if(const F &f) const
Definition: MemoryX.h:464
X * get() const
Definition: MemoryX.h:274
std::reverse_iterator< TrackIter< TrackType > > reverse_iterator
Definition: MemoryX.h:426
std::unique_ptr< T, Destroyer< T >> Destroy_ptr
Definition: MemoryX.h:352
void operator()(void *p) const
Definition: MemoryX.h:324
ValueRestorer(T &var)
Definition: MemoryX.h:395
ArraysOf()
Definition: MemoryX.h:136
X * pp
Definition: MemoryX.h:309
bool all_of(const F &f) const
Definition: MemoryX.h:473
unique_ptr< X[]> array_case
Definition: MemoryX.h:45
std::unique_ptr< T, freer > MallocPtr
Definition: MemoryX.h:330
size_t size() const
Definition: MemoryX.h:445
void reinit(Integral1 countN, Integral2 countM, bool initialize=false)
Definition: MemoryX.h:174
R max(Unary unary_op={}) const
Definition: MemoryX.h:552
void create(Args &&...args)
Definition: MemoryX.h:247
#define safenew
Definition: MemoryX.h:8
void operator()(T *p) const
Definition: MemoryX.h:345
Iterator end() const
Definition: MemoryX.h:438
Maybe(Maybe &&that)
Definition: MemoryX.h:224
ArrayOf()
Definition: MemoryX.h:85