Uploaded by Gaurav Vasishtha

SharedPtr2

advertisement
#include<iostream>
#include<atomic>
using namespace std;
template <typename T>
class SharedPtr {
private:
T* ptr; std::atomic<int>* refCount;
public:
//Default Ctor SharedPtr() : ptr(nullptr), refCount(nullptr) {}
SharedPtr(nullptr_t): SharedPtr(){}
explicit SharedPtr(T* rawPtr) : ptr(rawPtr), refCount(new std::atomic<int>(1)) {}
template <typename U>
explicit SharedPtr(U* rawPtr) : ptr(rawPtr), refCount(new std::atomic<int>(1)) {}
//Copy Ctor SharedPtr(const SharedPtr& other) : ptr(other.ptr), refCount(other.refCount) {
if (ptr)
(*refCount).fetch_add(1, std::memory_order_relaxed);
}
template <typename U> // How this works if it works??
SharedPtr(const SharedPtr<U>& other) : ptr(other.get()), refCount(other.getRefCount()) {
if (ptr) {
(*refCount).fetch_add(1, std::memory_order_relaxed);
}
}
//Copy Assignment SharedPtr& operator=(const SharedPtr& other) {
if (this != &other) {
swap(*this,SharedPtr(other));
/*release();
ptr = other.ptr;
refCount = other.refCount;
if (ptr) {
(*refCount).fetch_add(1, std::memory_order_relaxed);
}*/
}
return *this;
}
template <typename U>
SharedPtr& operator=(const SharedPtr<U>& other) {
if (this != &other) {
swap(*this,SharedPtr(other)); /*release();
ptr = other.ptr;
refCount = other.refCount;
if (ptr) {
(*refCount).fetch_add(1, std::memory_order_relaxed);
}*/
}
return *this;
}
// Move Ctors
SharedPtr(SharedPtr&& other) noexcept : SharedPtr() {swap(*this, other);}
template <typename U>
SharedPtr(SharedPtr<U>&& other) noexcept : SharedPtr() {swap(*this, other);}
//Move Assignment
SharedPtr& operator=(SharedPtr&& other) noexcept {
if (this != &other) {
release();
ptr = other.ptr;
refCount = other.refCount;//swap(*this, other);
other.ptr = nullptr;
other.refCount = nullptr;
}
return *this;
}
template <typename U>
SharedPtr& operator=(SharedPtr<U>&& other) noexcept {
release();
//swap(*this, other);
ptr = other.get();
refCount = other.getRefCount();
other.resetToNull();
return *this;
}
~SharedPtr() { release();}
T& operator*() const {return *ptr;}
T* operator->() const { return ptr; }
int use_count() const { return refCount ? refCount->load(std::memory_order_acquire) : 0;}
T* get() const { return ptr;}
std::atomic<int>* getRefCount() const { return refCount; }
bool unique() const { return use_count() == 1;}
void resetToNull() {
ptr = nullptr;
refCount = nullptr;
}
void reset(T* rawPtr) {
release();
ptr = rawPtr;
if (ptr)
refCount = new std::atomic<int>(1);
else refCount = nullptr;
}
void swap(SharedPtr& lhs, SharedPtr& rhs) noexcept {
std::swap(lhs.ptr, rhs.ptr);
std::swap(lhs.refCount, rhs.refCount);
}
void swap(SharedPtr& lhs, SharedPtr&& rhs) noexcept {
std::swap(lhs.ptr, rhs.ptr);
std::swap(lhs.refCount, rhs.refCount);
}
void release() {
if (ptr && refCount && (*refCount).fetch_sub(1, std::memory_order_release) == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
delete ptr;
delete refCount;
}
}
};
template<typename T, typename... Args>
SharedPtr<T> make_shared(Args&&... args) {
return SharedPtr<T>(new T(std::forward<Args>(args)...));
}
class Base {
public:
virtual void print() const {
std::cout << "Base class\n";
}
};
class Derived : public Base {
public:
void print() const override {
std::cout << "Derived class\n";
}
};
int main() {
SharedPtr<Base> ptr1(new Base);
SharedPtr<Base> ptrC(ptr1);
SharedPtr<Base> ptr2(new Derived);
SharedPtr<Derived> dtr1(new Derived);
//SharedPtr<Base> mt1(dtr1);
//SharedPtr<Base> ptr3(ptr2);
std::cout << "dtr1 use count: " << dtr1.use_count() << "\n";
std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";
std::cout << "ptrC use count: " << ptrC.use_count() << "\n";
//ptr1 = std::move(ptr2); // or ptr1 = std::move(dtr1);
std::cout<<"After\n";
std::cout << "dtr1 use count: " << dtr1.use_count() << "\n";
std::cout << "ptr1 use count: " << ptr1.use_count() << "\n";
std::cout << "ptr2 use count: " << ptr2.use_count() << "\n";
std::cout << "ptrC use count: " << ptrC.use_count() << "\n";
return 0;
}
Download