mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-17 08:37:17 -04:00
Prototype of shared_ptr
This commit is contained in:
parent
cd66712396
commit
c770c5874f
131
tstl/include/shared_ptr.hpp
Normal file
131
tstl/include/shared_ptr.hpp
Normal 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
|
50
tstl/test_suite/shared_ptr.cpp
Normal file
50
tstl/test_suite/shared_ptr.cpp
Normal 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();
|
||||
}
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user