154 lines
5.2 KiB
C++
154 lines
5.2 KiB
C++
/*!********************************************************************
|
|
|
|
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<
|
|
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
|