Prototype of shared_ptr

This commit is contained in:
Baptiste Wicht 2016-09-29 15:33:13 +02:00
parent cd66712396
commit c770c5874f
No known key found for this signature in database
GPG Key ID: C5566B6C7F884532
3 changed files with 183 additions and 0 deletions

131
tstl/include/shared_ptr.hpp Normal file
View File

@ -0,0 +1,131 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
// http://www.opensource.org/licenses/MIT)
//=======================================================================
#ifndef SHARED_PTR_H
#define SHARED_PTR_H
#include <tuple.hpp>
#include <algorithms.hpp>
#include <deleter.hpp>
namespace std {
/*!
* \brief A shared_ptr ptr of type T.
*
* TODO
*/
template <typename T, typename D = default_delete<T>>
struct shared_ptr {
using pointer_type = T*; ///< The pointer type
using reference_type = T&; ///< The reference type
using element_type = T; ///< The element type
constexpr shared_ptr() : ptr(), control_block() {}
constexpr explicit shared_ptr(decltype(nullptr)) : ptr(), control_block() {}
template<typename U>
explicit shared_ptr(U* ptr) : ptr(ptr) {
control_block = new control_block_impl<U, default_delete<U>>(ptr);
control_block->counter = 1;
}
template<typename U, typename Deleter>
shared_ptr(U* ptr, Deleter deleter) : ptr(ptr) {
control_block = new control_block_impl<U, Deleter>(ptr, deleter);
control_block->counter = 1;
}
shared_ptr(const shared_ptr& rhs) : ptr(rhs.ptr), control_block(rhs.control_block) {
__sync_fetch_and_add(&control_block->counter, 1);
}
shared_ptr& operator=(const shared_ptr& rhs){
if(this != &rhs){
this->ptr = rhs.ptr;
this->control_block = rhs.control_block;
__sync_fetch_and_add(&control_block->counter, 1);
}
return *this;
}
shared_ptr(shared_ptr&& rhs) : ptr(rhs.ptr), control_block(rhs.control_block) {
rhs.ptr = nullptr;
rhs.control_block = nullptr;
}
shared_ptr& operator=(shared_ptr&& rhs){
if(this != &rhs){
this->ptr = rhs.ptr;
this->control_block = rhs.control_block;
rhs.ptr = nullptr;
rhs.control_block = nullptr;
}
return *this;
}
~shared_ptr(){
if(__sync_fetch_and_sub(&control_block->counter, 1) == 1){
control_block->destroy();
delete control_block;
}
}
pointer_type get() const {
return ptr;
}
pointer_type operator->() const {
return get();
}
reference_type operator*() const {
return *get();
}
/*!
* \brief Converts the shared ptr to a boolean, indicating if it points to something or not
*/
explicit operator bool() const {
return get();
}
private:
struct control_block_t {
volatile size_t counter;
virtual void destroy() = 0;
virtual ~control_block_t(){}
};
template <typename U, typename Deleter>
struct control_block_impl : control_block_t {
U* ptr;
Deleter deleter;
control_block_impl(U* ptr) : ptr(ptr) {}
control_block_impl(U* ptr, Deleter d) : ptr(ptr), deleter(d){}
virtual void destroy(){
if(ptr){
deleter(ptr);
}
}
};
pointer_type ptr;
control_block_t* control_block;
};
} //end of namespace std
#endif

View File

@ -0,0 +1,50 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
// http://www.opensource.org/licenses/MIT)
//=======================================================================
#include <cstdio>
#include <cstring>
#include <shared_ptr.hpp>
#include "test.hpp"
namespace {
void test_base(){
std::shared_ptr<int> a(new int);
*a.get() = 99;
check(*a.get() == 99);
}
struct kiss {
int* ref;
kiss(int* ref) : ref(ref) {}
~kiss(){
++(*ref);
}
};
void test_destructor() {
int counter = 0;
{
std::shared_ptr<kiss> a(new kiss(&counter));
auto b = a;
auto c = a;
}
check(counter == 1, "destruct: Invalid destructors");
}
} //end of anonymous namespace
void shared_ptr_tests(){
test_base();
test_destructor();
}

View File

@ -17,6 +17,7 @@ void list_tests();
void traits_tests();
void algorithms_tests();
void circular_buffer_tests();
void shared_ptr_tests();
int main(){
string_tests();
@ -25,6 +26,7 @@ int main(){
circular_buffer_tests();
tuple_tests();
vector_tests();
shared_ptr_tests();
list_tests();
printf("All tests finished\n");