Newer
Older
* This file is part of Algorithms library toolkit.
* Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)
* Algorithms library toolkit is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Algorithms library toolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>.
*
* 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"
/**
* \brief
* Specialisation of copy on write pointer for classes based with copy on write pointer base.
*
* The class is essentially mimicking the behavior of shared_ptr. Additionaly the use of dereference (either through operator* or operator->) in non-constant context causes the managed pointer to ensure the referenced object is referenced from this class only.
*
* The class also uniques the referenced instances when they are equal.
*
* \tparam T the type of managed objects
*/
class cow_shared_ptr : std::shared_ptr < T > {
/**
* \brief
* Default initialization to null.
*/
explicit cow_shared_ptr ( ) : std::shared_ptr < T > ( nullptr ) {
/**
* \brief
* Constructor which takes ownership of the provided pointer.
*/
explicit cow_shared_ptr ( T * data ) : std::shared_ptr < T > ( data ) {
/**
* \brief
* Copy constructor to create new instance of shared pointer reffering the same data.
*
* \param other the source instance
*/
cow_shared_ptr ( const cow_shared_ptr & other ) : std::shared_ptr < T > ( other ) {
/**
* \brief
* Copy version of user conversion constructor to create new instance of shared pointer reffering the same data.
*
* \param other the source instance
*/
template < class Y >
cow_shared_ptr ( const cow_shared_ptr < Y > & other ) : std::shared_ptr < T > ( other ) {
}
/**
* \brief
* Move constructor to create new instance of shared pointer reffering the same data.
*
* \param other the source instance
*/
cow_shared_ptr ( cow_shared_ptr && other ) noexcept : std::shared_ptr < T > ( std::move ( other ) ) {
/**
* \brief
* Move version of user conversion constructor to create new instance of shared pointer reffering the same data.
*
* \param other the source instance
*/
template < class Y >
cow_shared_ptr ( cow_shared_ptr < Y > && other ) noexcept : std::shared_ptr < T > ( std::move ( other ) ) {
}
/**
* \brief
* The destructor of the shared pointer.
*/
~cow_shared_ptr ( ) noexcept {
}
/**
* \brief
* Copy assignment operator to change reffered instace to source one.
*
* \param other the source instance
*/
cow_shared_ptr & operator =( const cow_shared_ptr & other ) {
static_cast < std::shared_ptr < T > & > ( * this ) = static_cast < const std::shared_ptr < T > & > ( other );
/**
* \brief
* Copy version of user conversion assignment operator to change reffered instace to source one.
*
* \param other the source instance
*/
template < class Y >
cow_shared_ptr & operator =( const cow_shared_ptr < Y > & other ) {
static_cast < std::shared_ptr < T > & > ( * this ) = static_cast < const std::shared_ptr < T > & > ( other );
return * this;
}
/**
* \brief
* Move assignment operator to change reffered instace to source one.
*
* \param other the source instance
*/
cow_shared_ptr & operator =( cow_shared_ptr && other ) noexcept {
static_cast < std::shared_ptr < T > & > ( * this ) = static_cast < std::shared_ptr < T > && > ( other );
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
* \brief
* Move version of user conversion assignment operator to change reffered instace to source one.
*
* \param other the source instance
*/
template < class Y >
cow_shared_ptr & operator =( cow_shared_ptr < Y > && other ) noexcept {
static_cast < std::shared_ptr < T > & > ( * this ) = static_cast < std::shared_ptr < T > && > ( other );
return * this;
}
/**
* \brief
* Sets the shared pointer to nullptr.
*/
void reset ( ) noexcept {
return std::shared_ptr < T >::reset ( );
}
/**
* \brief
* Sets the shared pointer to value.
*
* \param ptr the value to store
*/
template < class Y >
void reset( Y * ptr ) {
return std::shared_ptr < T >::reset ( ptr );
}
/**
* \brief
* Operator arrow to chain dereferece to inner managed pointer.
*
* \return the managed pointer
*/
/**
* \brief
* Operator arrow to chain dereferece to inner managed pointer.
*
* \return the managed pointer
*/
/**
* \brief
* Operator dereference to access the inner managed pointer.
*
* \return reference to managed data
*/
/**
* \brief
* Operator dereference to access the inner managed pointer.
*
* \return reference to managed data
*/
/**
* Getter of the raw managed pointer.
*
* \return the managed pointer
*/
return std::shared_ptr < T >::get ( );
/**
* Getter of the raw managed pointer.
*
* \return the managed pointer
*/
return std::shared_ptr < T >::get ( );
/**
* \brief
* Tests whether the managed pointer is referenced from one location only (or the class stores null pointer).
*
* \return bool true if the managed pointer is referenced from one location only, false otherwise
*/
return std::shared_ptr < T >::unique ( );
/**
* \brief
* Getter of the number how many times the managed pointer is referenced.
*
* \return the use count
*/
unsigned use_count ( ) const {
return std::shared_ptr < T >::use_count ( );
/**
* Tests the instance whether the managed pointer is valid
*
* \return true if the managed pointer is not null and the use count is nonzero, false otherwise
*/
explicit operator bool( ) const {
/**
* \brief
* Ensures the managed pointer is unique by copy constructing the managed instance if needed.
*/
static_cast < std::shared_ptr < T > & > ( * this ) = std::shared_ptr < T > ( ext::clone ( * std::shared_ptr < T >::get ( ) ) );
/**
* \brief
* Specialisation of swap method to copy on write shared pointers.
*
* \param first the first instance
* \param second the second instance
*/
friend void swap ( cow_shared_ptr & first, cow_shared_ptr & second ) {
std::swap ( static_cast < std::shared_ptr < T > & > ( first ), static_cast < std::shared_ptr < T > & > ( second ) );
/**
* \brief
* Managed pointer simulating value like behavior.
*
* The class is supposed to be similar to unique_ptr but allows copying of managed instance by clone method or its copy constructor.
*
* \tparam T type of managed instance
*/
/**
* \brief
* Pointer to managed object.
*/
/**
* \brief
* Default initialization to null.
*/
/**
* \brief
* Constructor which takes ownership of the provided pointer.
*/
/**
* \brief
* Conversion constructor to simplify type casting.
*
* \tparam R the type of the managed resource of the source smart pointer
*
* \param other the source instance
*/
template < class R >
smart_ptr ( smart_ptr < R > other ) : m_Data ( other.release ( ) ) {
}
/**
* \brief
* Copy constructor of the smart pointer. Internally uses clone (if available) or copy constructor of the managed resource.
*
* \param other the source instance
*/
smart_ptr ( const smart_ptr & other ) : m_Data ( ext::clone ( * other.m_Data ) ) {
/**
* \brief
* Move constructor of the smart pointer. Passes ownership of the managed resource from source to constructed instance
*
* \param other the source instance
*/
smart_ptr ( smart_ptr && other ) noexcept : m_Data ( other.release ( ) ) {
/**
* \brief
* The destructor of the shared pointer, responsible for freeing the managed resource.
*/
~smart_ptr ( ) noexcept {
delete m_Data;
}
/**
* \brief
* Copy operator of assignment. Internally uses clone (if available) or copy constructor of the managed resource.
*
* \param other the source instance
*/
smart_ptr & operator =( const smart_ptr & other ) {
if ( this == & other ) return * this;
delete m_Data;
m_Data = ext::clone ( * other.m_Data );
/**
* \brief
* Copy operator of assignment. Passes ownership of the managed resource from source to this instance.
*
* \param other the source instance
*/
smart_ptr & operator =( smart_ptr && other ) noexcept {
swap ( this->m_Data, other.m_Data );
return * this;
}
/**
* \brief
* Operator arrow to chain dereferece to inner managed pointer.
*
* \return the managed pointer
*/
/**
* \brief
* Operator arrow to chain dereferece to inner managed pointer.
*
* \return the managed pointer
*/
/**
* \brief
* Operator dereference to access the inner managed pointer.
*
* \return reference to managed data
*/
T & operator *( ) {
return * m_Data;
}
/**
* \brief
* Operator dereference to access the inner managed pointer.
*
* \return reference to managed data
*/
* Getter of the raw managed pointer.
*
* \return the managed pointer
*/
* Getter of the raw managed pointer.
*
* \return the managed pointer
*/
/**
* \brief
* Releases the shared resource and returns it.
*
* \return the released shared resource
*/
* Tests the instance whether the managed pointer is valid
*
* \return true if the managed pointer is not null, false otherwise
*/
* Operator to print the copy on write shared pointer to the output stream.
*
* \param out the output stream
* \param map the copy on write shared pointer to print
*
* \tparam T the type of managed instances inside the copy on write shared pointer
*
* \return the output stream from the \p out
*/
std::ostream & operator <<( std::ostream & out, const ext::cow_shared_ptr < T > & ptr ) {
* Operator to print the smart pointer to the output stream.
*
* \param out the output stream
* \param map the smart pointer to print
*
* \tparam T the type of managed instances inside the smart pointer
*
* \return the output stream from the \p out
*/
std::ostream & operator <<( std::ostream & out, const ext::smart_ptr < T > & ptr ) {
* Specialisation of the compare structure implementing the three-way comparison
*
* \tparam T the type of managed resource inside the copy on write shared pointer
*/
struct compare < ext::cow_shared_ptr < T > > {
* Implementation of the three-way comparison
*
* \param first the left operand of the comparison
* \param second the right operand of the comparison
*
* \return negative value of left < right, positive value if left > right, zero if left == right
*/
int operator ()( const ext::cow_shared_ptr < T > & first, const ext::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 );
}
};
* Specialisation of the compare structure implementing the three-way comparison
*
* \tparam T the type of managed resource inside the shared pointer
*/
* Implementation of the three-way comparison
*
* \param first the left operand of the comparison
* \param second the right operand of the comparison
*
* \return negative value of left < right, positive value if left > right, zero if left == right
*/
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 );
}
};
* Specialisation of the compare structure implementing the three-way comparison
*
* \tparam T the type of managed resource inside the unique pointer
*/
* Implementation of the three-way comparison
*
* \param first the left operand of the comparison
* \param second the right operand of the comparison
*
* \return negative value of left < right, positive value if left > right, zero if left == right
*/
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 );
}
* Specialisation of the compare structure implementing the three-way comparison
*
* \tparam T the type of managed resource inside the smart pointer
*/
struct compare < ext::smart_ptr < T > > {
/**
* Implementation of the three-way comparison
*
* \param first the left operand of the comparison
* \param second the right operand of the comparison
*
* \return negative value of left < right, positive value if left > right, zero if left == right
*/
int operator ()( const ext::smart_ptr < T > & first, const ext::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;