File: ClientDataHelpers.h

package info (click to toggle)
audacity 3.7.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 125,252 kB
  • sloc: cpp: 358,238; ansic: 75,458; lisp: 7,761; sh: 3,410; python: 1,503; xml: 1,385; perl: 854; makefile: 122
file content (154 lines) | stat: -rw-r--r-- 5,328 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*!********************************************************************

Audacity: A Digital Audio Editor

@file ClientDataHelpers.h
@brief Some implementation details for ClientData

Paul Licameli

**********************************************************************/

#ifndef __AUDACITY_CLIENT_DATA_HELPERS__
#define __AUDACITY_CLIENT_DATA_HELPERS__

#include <memory>
#include <mutex>
#include <type_traits>

namespace ClientData {
   // Helpers to define ClientData::Site class template

//! Statically specify whether there is mutual exclusion (separately for the table of factories, and for the per-host container of client objects).
/*! Used as non-type template parameter of ClientData::Site */
enum LockingPolicy {
   NoLocking,
   NonrecursiveLocking, //!< using std::mutex
   RecursiveLocking,    //!< using std::recursive_mutex
};

//! Statically specify how the ClientData::Site implements its copy constructor and assignment.
/*! (Move construction and assignment always work.)
 Used as non-type template parameter of ClientData::Site */
enum CopyingPolicy {
   SkipCopying,     //!< ignore the source and leave empty
   ShallowCopying,  //!< copy pointers only; won't compile for std::unique_ptr
   DeepCopying,     //!< point to new sub-objects; these must define a Clone() member; won't compile for std::weak_ptr
};

// forward declarations
struct Base;
template<
   typename Covariant,
   template<typename> class Owner
> struct Cloneable;

//! Conversion allowing operator * on any @b Pointer parameter of ClientData::Site
/*! Return value should be bound to a const reference */
template< typename Ptr > static inline
   const Ptr &Dereferenceable( Ptr &p )
      { return p; }
//! Overload of ClientData::Dereferenceable returns an rvalue
template< typename Obj > static inline
   std::shared_ptr<Obj> Dereferenceable( std::weak_ptr<Obj> &p )
      { return p.lock(); }

//! Decorator template injects type Lock and method lock() into interface of @b Object
/*!
 @tparam Object decorated class
 @tparam LockingPolicy one of ClientData::LockingPolicy
 */
template< typename Object, LockingPolicy > struct Lockable{};
//! Specialization for trivial, non-locking policy
template< typename Object > struct Lockable< Object, NoLocking >
: Object {
   //! Empty class
   struct Lock{};
   Lock lock() const { return {}; }
};
//! Specialization for real locking with std::mutex
template< typename Object > struct Lockable< Object, NonrecursiveLocking >
: Object, std::mutex {
   using Lock = std::unique_lock< std::mutex >;
   Lock lock() const { return Lock{ *this }; }
};
//! Specialization for real locking with std::recursive_mutex
template< typename Object > struct Lockable< Object, RecursiveLocking >
: Object, std::recursive_mutex {
   using Lock = std::unique_lock< std::recursive_mutex >;
   Lock lock() const { return Lock{ *this }; }
};

//! Decorated reference to a ClientData::Lockable, with a current lock on it
/*! Uses inheritance to benefit from the empty base class optimization if possible */
template< typename Lockable > struct Locked
   : private Lockable::Lock
{
   explicit Locked( Lockable &object )
      : Lockable::Lock( object.lock() )
      , mObject( object )
   {}
   Lockable &mObject;
};

//! Decorator template injects copy and move operators for container of pointers
template< typename Container, CopyingPolicy > struct Copyable{};
//! Specialization that ignores contents of the source when copying (not when moving).
template< typename Container > struct Copyable< Container, SkipCopying >
: Container {
   Copyable() = default;
   Copyable( const Copyable & ) {}
   Copyable &operator=( const Copyable & ) { return *this; }
   Copyable( Copyable && ) = default;
   Copyable &operator=( Copyable&& ) = default;
};
//! Specialization that copies pointers, not sub-objects; [strong guarantee](@ref Strong-guarantee) for assignment
template< typename Container > struct Copyable< Container, ShallowCopying >
: Container {
   Copyable() = default;
   //! Call through to operator =
   Copyable( const Copyable &other )
   { *this = other;  }
   //! @excsafety{Strong}
   Copyable &operator=( const Copyable &other )
   {
      if (this != &other) {
         // Build then swap for strong exception guarantee
         Copyable temp;
         for ( auto &&ptr : other )
            temp.push_back( ptr );
         this->swap( temp );
      }
      return *this;
   }
   Copyable( Copyable && ) = default;
   Copyable &operator=( Copyable&& ) = default;
};
//! Specialization that clones sub-objects when copying;  [strong guarantee](@ref Strong-guarantee) for assignment
template< typename Container > struct Copyable< Container, DeepCopying >
: Container {
   Copyable() = default;
   //! Call through to operator =
   Copyable( const Copyable &other )
   { *this = other;  }
   //! @excsafety{Strong}
   Copyable &operator=( const Copyable &other )
   {
      if (this != &other) {
         // Build then swap for strong exception guarantee
         Copyable temp;
         for ( auto &&p : other ) {
            using Ptr = decltype( p->Clone() );
            temp.push_back( p ? p->Clone() : Ptr{} );
         }
         this->swap( temp );
      }
      return *this;
   }
   Copyable( Copyable && ) = default;
   Copyable &operator=( Copyable&& ) = default;
};

}

#endif