diff --git a/alib2std/src/extensions/memory.hpp b/alib2std/src/extensions/memory.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5e39fdbb3471f12d80f9590088f8bb05b75c28ba --- /dev/null +++ b/alib2std/src/extensions/memory.hpp @@ -0,0 +1,123 @@ +#ifndef _MEMORY_HPP__ +#define _MEMORY_HPP__ + +namespace std { + +template<class T> +class cow_shared_ptr { + 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; + } + }; + +public: + cow_shared_ptr ( ) { + attach ( NULL ); + } + + cow_shared_ptr ( T * data ) { + attach ( new cow_shared_ptr_data( data ) ); + } + + cow_shared_ptr ( const cow_shared_ptr<T> & other ) { + attach ( other.m_Data ); + } + + cow_shared_ptr ( cow_shared_ptr<T> && other ) noexcept { + attach ( other.m_Data ); + } + + ~cow_shared_ptr ( ) noexcept { + deattach ( ); + } + + cow_shared_ptr<T> & operator = ( const cow_shared_ptr<T> & other ) { + if(this == &other) return *this; + + deattach ( ); + attach ( other.m_Data ); + + return *this; + } + + cow_shared_ptr<T> & operator = ( cow_shared_ptr<T> && other ) noexcept { + swap(*this, other); + return *this; + } + + T * operator -> ( ) { + make_unique( ); + return m_Data->m_Data; + } + + T const * operator -> ( ) const { + return m_Data->m_Data; + } + + T & operator * ( ) { + make_unique( ); + return *(m_Data->m_Data); + } + + T const & operator * ( ) const { + return *(m_Data->m_Data); + } + + T * get () { + make_unique( ); + return m_Data->m_Data; + } + + T const * get () const { + return m_Data->m_Data; + } + + bool unique ( ) const { + return m_Data == NULL || m_Data->m_UseCount == 1; + } + +private: + void attach ( cow_shared_ptr<T>::cow_shared_ptr_data * data ) { + m_Data = data; + if(m_Data) m_Data->m_UseCount++; + } + + void deattach ( ) { + if(m_Data && --(m_Data->m_UseCount) <= 0) delete m_Data; + m_Data = NULL; + } + + void make_unique( ) { + if(unique( )) return; + + typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp = m_Data; + deattach( ); + attach(new cow_shared_ptr_data(new T(*(tmp->m_Data)))); + } + + cow_shared_ptr_data * m_Data; + + friend void swap ( cow_shared_ptr<T> & first, cow_shared_ptr<T> & second ) { + typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp = first.m_Data; + first.m_Data = second.m_Data; + second.m_Data = tmp; + } +}; + +template<class T> +const cow_shared_ptr<T>& make_const(cow_shared_ptr<T>& ptr) { + return static_cast<const cow_shared_ptr<T>&>(ptr); +} + +template<class T> +const cow_shared_ptr<T>& make_const(const cow_shared_ptr<T>& ptr) { + return ptr; +} + +} /* namespace std */ + +#endif // _MEMORY_HPP__ diff --git a/alib2std/src/memory b/alib2std/src/memory new file mode 100644 index 0000000000000000000000000000000000000000..1d4b97f7375d7ca82c4167abb6d24f2610dfc0d4 --- /dev/null +++ b/alib2std/src/memory @@ -0,0 +1,7 @@ +#ifndef __MEMORY_HEADER_WRAPPER_ +#define __MEMORY_HEADER_WRAPPER_ + +#include <bits/../memory> +#include "extensions/memory.hpp" + +#endif /* __MEMORY_HEADER_WRAPPER_ */ diff --git a/alib2std/test-src/extensions/SetTest.cpp b/alib2std/test-src/extensions/SetTest.cpp index 712b4cd16afb6bdc66402cdcf8392928b1439e60..15ffd03fe0954887cf73e342c66d5f9f4ffb0c10 100644 --- a/alib2std/test-src/extensions/SetTest.cpp +++ b/alib2std/test-src/extensions/SetTest.cpp @@ -43,35 +43,12 @@ void SetTest::test2() { CPPUNIT_ASSERT_EQUAL(secondMinusFirst.size(), 2ul); } -class Moveable { - int& moves; - int& copies; - -public: - Moveable(int& moves, int& copies) : moves(moves), copies(copies) { - moves = 0; - copies = 0; - } - - Moveable(const Moveable& src) : moves(src.moves), copies(src.copies) { - copies++; - } - - Moveable(Moveable&& src) : moves(src.moves), copies(src.copies) { - moves++; - } - - bool operator<(const Moveable&) const { - return false; - } -}; - void SetTest::test3() { int moves; int copies; - std::set<Moveable> set = {Moveable(moves, copies)}; - std::set<Moveable> set2; + std::set<SetTest::Moveable> set = {SetTest::Moveable(moves, copies)}; + std::set<SetTest::Moveable> set2; for(Moveable moveable : std::make_moveable_set(set)) { set2.insert(std::move(moveable)); diff --git a/alib2std/test-src/extensions/SetTest.h b/alib2std/test-src/extensions/SetTest.h index ce6f31b5ee5f0f9cfd1747dd6d7fd42c36c4d821..91091fa046505b2111484df75d2c4bd6e53169aa 100644 --- a/alib2std/test-src/extensions/SetTest.h +++ b/alib2std/test-src/extensions/SetTest.h @@ -10,6 +10,30 @@ class SetTest : public CppUnit::TestFixture CPPUNIT_TEST( test2 ); CPPUNIT_TEST_SUITE_END(); +public: +class Moveable { + int& moves; + int& copies; + +public: + Moveable(int& moves, int& copies) : moves(moves), copies(copies) { + moves = 0; + copies = 0; + } + + Moveable(const Moveable& src) : moves(src.moves), copies(src.copies) { + copies++; + } + + Moveable(Moveable&& src) : moves(src.moves), copies(src.copies) { + moves++; + } + + bool operator<(const Moveable&) const { + return false; + } +}; + public: void setUp(); void tearDown(); diff --git a/alib2std/test-src/extensions/SharedPtrTest.cpp b/alib2std/test-src/extensions/SharedPtrTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e30aaa5b3d053426ee0ff02e59f9a99356507da --- /dev/null +++ b/alib2std/test-src/extensions/SharedPtrTest.cpp @@ -0,0 +1,42 @@ +#include "SharedPtrTest.h" +#include <memory> + +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SharedPtrTest, "bits" ); +CPPUNIT_TEST_SUITE_REGISTRATION( SharedPtrTest ); + +void SharedPtrTest::setUp() { +} + +void SharedPtrTest::tearDown() { +} + +void SharedPtrTest::testSharedPtr1() { + int moves; + int copies; + + std::cow_shared_ptr<SharedPtrTest::Moveable> one(new SharedPtrTest::Moveable(moves, copies)); + + CPPUNIT_ASSERT(one.unique()); + CPPUNIT_ASSERT(moves == 0); + CPPUNIT_ASSERT(copies == 0); + + std::cow_shared_ptr<SharedPtrTest::Moveable> two(one); + + CPPUNIT_ASSERT(!one.unique()); + CPPUNIT_ASSERT(moves == 0); + CPPUNIT_ASSERT(copies == 0); + + std::make_const(two).get(); + + CPPUNIT_ASSERT(!one.unique()); + CPPUNIT_ASSERT(moves == 0); + CPPUNIT_ASSERT(copies == 0); + + two.get(); + + CPPUNIT_ASSERT(one.unique()); + CPPUNIT_ASSERT(moves == 0); + CPPUNIT_ASSERT(copies == 1); + +} + diff --git a/alib2std/test-src/extensions/SharedPtrTest.h b/alib2std/test-src/extensions/SharedPtrTest.h new file mode 100644 index 0000000000000000000000000000000000000000..9bf5bcb05ed0bfe5f3aaaa6195a2d4375b65b405 --- /dev/null +++ b/alib2std/test-src/extensions/SharedPtrTest.h @@ -0,0 +1,43 @@ +#ifndef TYPE_TRAITS_TEST_H_ +#define TYPE_TRAITS_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class SharedPtrTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( SharedPtrTest ); + CPPUNIT_TEST( testSharedPtr1 ); + CPPUNIT_TEST_SUITE_END(); + +public: +class Moveable { + int& moves; + int& copies; + +public: + Moveable(int& moves, int& copies) : moves(moves), copies(copies) { + moves = 0; + copies = 0; + } + + Moveable(const Moveable& src) : moves(src.moves), copies(src.copies) { + copies++; + } + + Moveable(Moveable&& src) : moves(src.moves), copies(src.copies) { + moves++; + } + + bool operator<(const Moveable&) const { + return false; + } +}; + +public: + void setUp(); + void tearDown(); + + void testSharedPtr1(); +}; + +#endif // TYPE_TRAITS_TEST_H_