#include <cstddef>
template <typename T>
struct smart_ptr_wrapper {
T* raw_pointer;
size_t strong_count;
size_t weak_count;
// Should be used if wrapper is constructed from
// shared pointer
smart_ptr_wrapper(T* raw_pointer) :
raw_pointer(raw_pointer), strong_count(0), weak_count(0)
{ }
void dispose_wrapped_object() {
delete raw_pointer;
}
};
#define SHARED_PTR_FRIEND_DECLARATIONS \
template <typename Z> friend class weak_ptr; \
// Shared pointer implementation
template <typename T>
class shared_ptr {
// Declare friend smart pointer classes
SHARED_PTR_FRIEND_DECLARATIONS
private:
// Shared wrapper implementation
typedef smart_ptr_wrapper<T> shared_ptr_wrapper;
shared_ptr_wrapper* wrapper;
private:
// Shared wrapper additional routines
void increase_reference_count() {
++(wrapper->strong_count);
}
void decrease_reference_count() {
--(wrapper->strong_count);
if (wrapper->strong_count == 0) {
wrapper->dispose_wrapped_object();
}
// Dispose the wrapper if there are no more
// references to this object
// @note This should actually lock the wrapper to
// preserve thread safety
if (wrapper->strong_count == 0 && wrapper->weak_count == 0) {
delete wrapper;
}
}
public:
// Default constructor to grant syntax flexibility
explicit shared_ptr(T* pointer = NULL) : wrapper(new shared_ptr_wrapper(pointer)) {
increase_reference_count();
}
shared_ptr(const shared_ptr& p) : wrapper(p.wrapper) {
increase_reference_count();
}
shared_ptr& operator= (shared_ptr& p) {
// Set new reference counts
decrease_reference_count();
p.increase_reference_count();
// Set new wrapper
wrapper = p.wrapper;
return *this;
}
~shared_ptr() {
decrease_reference_count();
}
// @todo
// void swap(...)
// void set(...) or reset(...)
T* get () const { return wrapper->raw_pointer; }
T* operator-> () const { return get(); }
T& operator* () const { return *get(); }
// User comparison operation
operator void* () const {
return (get() == NULL);
}
};
template <typename T>
class weak_ptr {
private:
// Weak wrapper implementation
// Weak wrapper implementation
typedef smart_ptr_wrapper<T> weak_ptr_wrapper;
weak_ptr_wrapper* wrapper;
private:
// Shared wrapper additional routines
void increase_reference_count() {
++(wrapper->weak_count);
}
void decrease_reference_count() {
--(wrapper->weak_count);
// Dispose the wrapper if there are no more
// references to this object
// @note This should actually lock the wrapper to
// preserve thread safety
if (wrapper->strong_count == 0 && wrapper->weak_count == 0) {
delete wrapper;
}
}
public:
// Default constructor to grant syntax flexibility
weak_ptr() : wrapper(NULL) { }
weak_ptr(const shared_ptr<T>& pointer) : wrapper(pointer.wrapper) {
increase_reference_count();
}
weak_ptr(const weak_ptr& p) : wrapper(p.wrapper) {
increase_reference_count();
}
weak_ptr& operator= (weak_ptr& p) {
// Set new reference counts
// @note If this is 'just-a-pointer', which was created
// using default constructor then our wrapper would be 'NULL'
if (wrapper != NULL) {
decrease_reference_count();
}
p.increase_reference_count();
// Set new wrapper
wrapper = p.wrapper;
return *this;
}
~weak_ptr() {
decrease_reference_count();
}
// @todo
// void swap(...)
// @note Actually should be 'lock' instead of simply get
// to preserve thread safety
/*
@deprecated
T* get () const {
size_t reference_count = wrapper->reference_count;
size_t dummy_reference_count = wrapper->pointer.wrapper->reference_count;
// If our object has no actual strong references left, we
// return NULL, because the actual object should be destroyed
// at this point
// @note Actually, object will be disposed when there are no WEAK references
// to it left. Still this way of memory management is the only way to check
// whether the object actually exists at the 'get' call moment.
//
// What we could achieve here in terms of 'fast' response would be object disposing
// right after the first wrong 'get' call. Yet this would require more code and
// therefore (because I see no actual benefit in that approach) isn't done..
return (dummy_reference_count >= reference_count) ? NULL : wrapper->pointer.get();
}
*/
T* get() const { return (wrapper->strong_count == 0) ? NULL: wrapper->raw_pointer; }
T* operator-> () const { return get(); }
T& operator* () const { return *get(); }
// User comparison operation
operator void* () const {
return (get() == NULL);
}
};
int main() {
shared_ptr<int> sp1(new int(4));
weak_ptr<int> wp1(sp1);
wp1 = weak_ptr<int>(sp1);
return 0;
}