Newer
Older
/*
* memoru.hpp
*
* Created on: May 1, 2015
* Author: Jan Travnicek
*/
#ifndef __MEMORY_HPP_
#define __MEMORY_HPP_
#include <memory>
#include <utility>
#include "compare.hpp"
#include "type_traits.hpp"
#include "clone.hpp"
class cow_shared_ptr;
class cow_shared_ptr_base {
template < typename T, typename Enable >
friend class cow_shared_ptr;
template < class T >
class cow_shared_ptr < T, typename std::enable_if < std::is_base_of < cow_shared_ptr_base, T >::value >::type > {
cow_shared_ptr ( const cow_shared_ptr & other ) {
cow_shared_ptr ( cow_shared_ptr && other ) noexcept {
m_Data = other.m_Data;
other.m_Data = NULL;
}
~cow_shared_ptr ( ) noexcept {
cow_shared_ptr & operator =( const cow_shared_ptr & other ) {
cow_shared_ptr & operator =( cow_shared_ptr && other ) noexcept {
T & operator *( ) {
make_unique ( );
return * m_Data;
return m_Data;
}
bool unique ( ) const {
return m_Data == NULL || m_Data->m_UseCount == 1;
}
int getUseCount ( ) const {
if ( m_Data == NULL ) return 0;
return m_Data->m_UseCount;
}
explicit operator bool( ) const {
return getUseCount ( ) == 0;
}
private:
void attach ( T * data ) {
m_Data = data;
if ( m_Data && ( --( m_Data->m_UseCount ) <= 0 ) ) delete m_Data;
T * tmp = m_Data;
detach ( );
tmp = std::clone ( tmp );
friend void swap ( cow_shared_ptr & first, cow_shared_ptr & second ) {
template < class T >
class cow_shared_ptr < T, typename std::enable_if < !std::is_base_of < cow_shared_ptr_base, T >::value >::type > {
struct cow_shared_ptr_data {
T * m_Data;
int m_UseCount;
cow_shared_ptr_data ( T * data ) : m_Data ( data ), m_UseCount ( 0 ) { }
~cow_shared_ptr_data ( ) {
delete m_Data;
}
attach ( data ? new cow_shared_ptr_data ( data ) : NULL );
cow_shared_ptr ( const cow_shared_ptr & other ) {
cow_shared_ptr ( cow_shared_ptr && other ) noexcept {
m_Data = other.m_Data;
other.m_Data = NULL;
}
~cow_shared_ptr ( ) noexcept {
cow_shared_ptr & operator =( const cow_shared_ptr & other ) {
cow_shared_ptr & operator =( cow_shared_ptr && other ) noexcept {
T & operator *( ) {
make_unique ( );
return * ( m_Data->m_Data );
T const & operator *( ) const {
return * ( m_Data->m_Data );
return m_Data->m_Data;
}
bool unique ( ) const {
return m_Data == NULL || m_Data->m_UseCount == 1;
int getUseCount ( ) const {
if ( m_Data == NULL ) return 0;
return m_Data->m_UseCount;
}
explicit operator bool( ) const {
return getUseCount ( ) == 0;
}
void attach ( typename cow_shared_ptr < T >::cow_shared_ptr_data * data ) {
if ( m_Data && ( --( m_Data->m_UseCount ) <= 0 ) ) delete m_Data;
typename cow_shared_ptr < T >::cow_shared_ptr_data * tmp = m_Data;
detach ( );
attach ( new cow_shared_ptr_data ( std::clone ( tmp->m_Data ) ) );
}
cow_shared_ptr_data * m_Data;
friend void swap ( cow_shared_ptr & first, cow_shared_ptr & second ) {
typename cow_shared_ptr < T >::cow_shared_ptr_data * tmp = first.m_Data;
template < class R >
smart_ptr ( smart_ptr < R > other ) : m_Data ( other.release ( ) ) {
}
smart_ptr ( const smart_ptr & other ) : m_Data ( std::clone ( other.m_Data ) ) {
smart_ptr ( smart_ptr && other ) noexcept : m_Data ( other.release ( ) ) {
}
~smart_ptr ( ) noexcept {
delete m_Data;
}
smart_ptr & operator =( const smart_ptr & other ) {
if ( this == & other ) return * this;
delete m_Data;
m_Data = std::clone ( other.m_Data );
return * this;
}
smart_ptr & operator =( smart_ptr && other ) noexcept {
swap ( this->m_Data, other.m_Data );
return * this;
}
T * operator ->( ) {
return m_Data;
}
return m_Data;
}
T & operator *( ) {
return * m_Data;
}
return * m_Data;
}
T * get ( ) {
return m_Data;
}
explicit operator bool( ) const {
return m_Data;
}
};
std::ostream & operator <<( std::ostream & out, const std::cow_shared_ptr < T > & ptr ) {
out << * ptr;
return out;
std::ostream & operator <<( std::ostream & out, const std::shared_ptr < T > & ptr ) {
out << * ptr;
return out;
}
template < class T >
std::ostream & operator <<( std::ostream & out, const std::unique_ptr < T > & ptr ) {
out << * ptr;
return out;
}
template < class T >
std::ostream & operator <<( std::ostream & out, const std::smart_ptr < T > & ptr ) {
out << * ptr;
return out;
}
template < class T >
struct compare < cow_shared_ptr < T > > {
int operator ()( const cow_shared_ptr < T > & first, const cow_shared_ptr < T > & second ) const {
if ( first.get ( ) == second.get ( ) ) return 0;
if ( !first ) return -1;
if ( !second ) return 1;
static compare < typename std::decay < T >::type > comp;
return comp ( * first, * second );
}
};
template < class T >
struct compare < std::shared_ptr < T > > {
int operator ()( const std::shared_ptr < T > & first, const std::shared_ptr < T > & second ) const {
if ( first.get ( ) == second.get ( ) ) return 0;
if ( !first ) return -1;
if ( !second ) return 1;
static compare < typename std::decay < T >::type > comp;
return comp ( * first, * second );
}
};
template < class T >
struct compare < std::unique_ptr < T > > {
int operator ()( const std::unique_ptr < T > & first, const std::unique_ptr < T > & second ) const {
if ( first.get ( ) == second.get ( ) ) return 0;
if ( !first ) return -1;
if ( !second ) return 1;
static compare < typename std::decay < T >::type > comp;
return comp ( * first, * second );
}
};
template < class T >
struct compare < smart_ptr < T > > {
int operator ()( const smart_ptr < T > & first, const smart_ptr < T > & second ) const {
if ( first.get ( ) == second.get ( ) ) return 0;
if ( !first ) return -1;
if ( !second ) return 1;
static compare < typename std::decay < T >::type > comp;