Instantly share code, notes, and snippets.
Created
October 27, 2015 23:49
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save goldsborough/1640aed80a605df058a7 to your computer and use it in GitHub Desktop.
A smart shared-pointer class.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename T> | |
class SharedPointer | |
{ | |
public: | |
using size_t = std::size_t; | |
using pointer_t = T*; | |
using const_pointer_t = const T*; | |
using reference_t = T&; | |
using const_reference_t = const T&; | |
using deleter_t = std::function<void(pointer_t)>; | |
explicit SharedPointer(pointer_t pointer = nullptr, | |
const deleter_t& deleter = std::default_delete<T>()) noexcept | |
: _pointer(pointer) | |
, _delete(deleter) | |
, _count(new std::atomic<size_t>(1)) | |
{ } | |
SharedPointer(const SharedPointer& other) noexcept | |
: _pointer(other._pointer) | |
, _delete(other._delete) | |
, _count(other._count) | |
{ | |
++(*_count); | |
} | |
template<typename U> | |
SharedPointer(const SharedPointer<U>& other) noexcept | |
: _pointer(other._pointer) | |
, _delete(other._delete) | |
, _count(other._count) | |
{ | |
++(*_count); | |
} | |
SharedPointer(SharedPointer&& other) noexcept | |
: SharedPointer() | |
{ | |
swap(other); | |
} | |
template<typename U> | |
SharedPointer(SharedPointer<U>&& other) noexcept | |
: SharedPointer() | |
{ | |
swap(other); | |
} | |
SharedPointer& operator=(SharedPointer other) noexcept | |
{ | |
swap(other); | |
return *this; | |
} | |
template<typename U> | |
SharedPointer& operator=(SharedPointer<U> other) noexcept | |
{ | |
swap(other); | |
return *this; | |
} | |
template<typename U> | |
void swap(SharedPointer<U>& other) noexcept | |
{ | |
// Enable Argument-Dependent-Lookup (ADL) | |
using std::swap; | |
swap(_pointer, other._pointer); | |
swap(_delete, other._delete); | |
swap(_count, other._count); | |
} | |
template<typename U, typename V> | |
friend void swap(SharedPointer<U>& first, SharedPointer<V>& second) noexcept | |
{ | |
first.swap(second); | |
} | |
~SharedPointer() | |
{ | |
if (--(*_count) == 0) | |
{ | |
_delete(_pointer); | |
delete _count; | |
} | |
} | |
reference_t operator*() | |
{ | |
return *_pointer; | |
} | |
const_reference_t operator*() const | |
{ | |
return *_pointer; | |
} | |
pointer_t operator->() | |
{ | |
return _pointer; | |
} | |
const_pointer_t operator->() const | |
{ | |
return _pointer; | |
} | |
template<typename U> | |
bool operator==(const SharedPointer<U>& other) | |
{ | |
return _pointer == other._pointer; | |
} | |
template<typename U> | |
bool operator!=(const SharedPointer<U>& other) | |
{ | |
return _pointer != other._pointer; | |
} | |
template<typename U> | |
bool operator<=(const SharedPointer<U>& other) | |
{ | |
return _pointer <= other._pointer; | |
} | |
template<typename U> | |
bool operator>=(const SharedPointer<U>& other) | |
{ | |
return _pointer >= other._pointer; | |
} | |
template<typename U> | |
bool operator<(const SharedPointer<U>& other) | |
{ | |
return _pointer < other._pointer; | |
} | |
template<typename U> | |
bool operator>(const SharedPointer<U>& other) | |
{ | |
return _pointer > other._pointer; | |
} | |
operator bool() | |
{ | |
return _pointer != nullptr; | |
} | |
pointer_t get() | |
{ | |
return _pointer; | |
} | |
const_pointer_t get() const | |
{ | |
return _pointer; | |
} | |
pointer_t release() | |
{ | |
auto pointer = _pointer; | |
_pointer = nullptr; | |
return pointer; | |
} | |
void reset(pointer_t new_pointer = nullptr) | |
{ | |
auto count = _count->load(); | |
// Then it would now be 0, but we can keep the 1 | |
// stored in the pointer for efficiency | |
if (count == 1) _delete(_pointer); | |
else | |
{ | |
_count->store(count - 1); | |
_count = new std::atomic<size_t>(1); | |
} | |
_pointer = new_pointer; | |
} | |
size_t count() const | |
{ | |
return _count->load(); | |
} | |
private: | |
pointer_t _pointer; | |
deleter_t _delete; | |
std::atomic<size_t>* _count; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment