diff --git a/module-1/homework/SharedPointer/src/control/control.h b/module-1/homework/SharedPointer/src/control/control.h index b2fc359b..ca32b3ce 100644 --- a/module-1/homework/SharedPointer/src/control/control.h +++ b/module-1/homework/SharedPointer/src/control/control.h @@ -4,25 +4,81 @@ class SharedCount { public: - // Your code goes here... + size_t Get() const { + return counter_.load(); + } + + virtual bool Empty() { + return counter_ > 0; + } + + virtual bool Remove() { + if (counter_ == 0) { + return false; + } + + --counter_; + return true; + } + + void Add() { + ++counter_; + } protected: - // Your code goes here... + std::atomic counter_{0}; }; class SharedWeakCount : public SharedCount { public: - // Your code goes here... + void AddWeak() { + ++weak_counter_; + } + + bool RemoveWeak() { + if (weak_counter_ == 0) { + return false; + } + + --weak_counter_; + return true; + } + + size_t GetWeak() const { + return weak_counter_.load(); + } + + bool Empty() override { + return (counter_ == 0) and (weak_counter_ == 0); + } protected: - // Your code goes here... + std::atomic weak_counter_{0}; }; template class ControlBlock : public SharedWeakCount { public: - // Your code goes here... + explicit ControlBlock(T* value) : value_{value} { + assert(value_ != nullptr); + Add(); + } + + ControlBlock(ControlBlock&) = delete; + void operator=(ControlBlock&) = delete; + + bool Remove() override { + if (SharedCount::Remove()) { + if (Get() == 0) { + Deleter deleter; + deleter(value_); + value_ = nullptr; + } + return true; + } + return false; + } private: - // Your code goes here... + T* value_; }; \ No newline at end of file diff --git a/module-1/homework/SharedPointer/src/shared_ptr/shared_ptr.h b/module-1/homework/SharedPointer/src/shared_ptr/shared_ptr.h index 2a60bbcf..5cb1eea2 100644 --- a/module-1/homework/SharedPointer/src/shared_ptr/shared_ptr.h +++ b/module-1/homework/SharedPointer/src/shared_ptr/shared_ptr.h @@ -2,6 +2,50 @@ #include "../control/control.h" +template +struct GetPureType { + using type = T; +}; + +template +struct GetPureType { + using type = T; +}; + +template +struct GetPureType { + using type = T; +}; + +struct TypeDeleter { + template + void operator()(T* p) { + delete p; + } +}; + +struct ArrayDeleter { + template + void operator()(T* p) { + delete[] p; + } +}; + +template +struct ChooseDeleter { + using deleter = TypeDeleter; +}; + +template +struct ChooseDeleter { + using deleter = ArrayDeleter; +}; + +template +struct ChooseDeleter { + using deleter = ArrayDeleter; +}; + // SharedPtr template class WeakPtr; @@ -9,7 +53,8 @@ class WeakPtr; template class SharedPtr { public: - using element_type = // Your code goes here... + using element_type = typename GetPureType::type; + using deleter_type = typename ChooseDeleter::deleter; constexpr SharedPtr() noexcept = default; ~SharedPtr(); @@ -56,24 +101,172 @@ class SharedPtr { friend class WeakPtr; private: - // Your code goes here... + element_type* value_{nullptr}; + SharedWeakCount* counter_{nullptr}; }; +template +SharedPtr MakeShared(Args&&... args) { + return SharedPtr(new T(std::forward(args)...)); +} -// MakeShared -// Your code goes here... -// MakeShared +template +SharedPtr::~SharedPtr() { + if (counter_) { + counter_->Remove(); + if (counter_->Empty()) { + delete counter_; + } + } +} -// SharedPtr -// Your code goes here... -// SharedPtr +template +template +SharedPtr::SharedPtr(Y* p) : value_{p}, counter_{new ControlBlock(p)} { +} + +template +template +SharedPtr::SharedPtr(Y* p, Deleter) noexcept + : value_{p}, counter_{new ControlBlock(p)} { +} + +template +SharedPtr::SharedPtr(const SharedPtr& other) noexcept + : value_{other.value_}, counter_{other.counter_} { + counter_->Add(); +} + +template +SharedPtr::SharedPtr(SharedPtr&& other) noexcept + : value_{other.value_}, counter_{other.counter_} { + other.value_ = nullptr; + other.counter_ = nullptr; +} + +template +SharedPtr& SharedPtr::operator=(const SharedPtr& other) noexcept { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + counter_->Add(); + return *this; +} + +template +template +SharedPtr& SharedPtr::operator=(const SharedPtr& other) noexcept { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + counter_->Add(); + return *this; +} + +template +SharedPtr& SharedPtr::operator=(SharedPtr&& other) noexcept { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + other.value_ = nullptr; + other.counter_ = nullptr; + return *this; +} + +template +template +SharedPtr& SharedPtr::operator=(SharedPtr&& other) noexcept { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + other.value_ = nullptr; + other.counter_ = nullptr; + return *this; +} + +template +void SharedPtr::Reset() noexcept { + if (counter_) { + counter_->Remove(); + value_ = nullptr; + counter_ = nullptr; + } +} + +template +template +void SharedPtr::Reset(Y* p) noexcept { + if (counter_) { + counter_->Remove(); + if (counter_->Empty()) { + delete counter_; + } + } + + value_ = p; + counter_ = new ControlBlock(p); +} + +template +template +void SharedPtr::Reset(Y* p, Deleter) noexcept { + if (counter_) { + counter_->Remove(); + if (counter_->Empty()) { + delete counter_; + } + } + + value_ = p; + counter_ = new ControlBlock(p); +} + +template +void SharedPtr::Swap(SharedPtr& other) noexcept { + std::swap(counter_, other.counter_); + std::swap(value_, other.value_); +} + +template +T* SharedPtr::Get() const noexcept { + return value_; +} + +template +int64_t SharedPtr::UseCount() const noexcept { + if (counter_ == nullptr) { + return 0; + } + return counter_->Get(); +} + +template +T& SharedPtr::operator*() const noexcept { + return *value_; +} + +template +T* SharedPtr::operator->() const noexcept { + return value_; +} + +template +typename SharedPtr::element_type& SharedPtr::operator[](std::ptrdiff_t idx) const { + return value_[idx]; +} + +template +SharedPtr::operator bool() const noexcept { + return counter_ != nullptr; +} // WeakPtr template class WeakPtr { public: - using element_type = // Your code goes here... + using element_type = typename GetPureType::type; + using deleter_type = typename ChooseDeleter::deleter; // Special-member functions constexpr WeakPtr() noexcept = default; @@ -100,9 +293,102 @@ class WeakPtr { friend class SharedPtr; public: - // Your code goes here... + element_type* value_{nullptr}; + SharedWeakCount* counter_{nullptr}; }; -// WeakPtr -// Your code goes here... -// WeakPtr \ No newline at end of file +template +template +WeakPtr::WeakPtr(const SharedPtr& other) : value_{other.value_}, counter_{other.counter_} { + counter_->AddWeak(); +} + +template +WeakPtr::WeakPtr(const WeakPtr& other) noexcept + : value_{other.value_}, counter_{other.counter_} { + counter_->AddWeak(); +} + +template +WeakPtr::WeakPtr(WeakPtr&& other) noexcept : value_{other.value_}, counter_{other.counter_} { + other.value_ = nullptr; + other.counter_ = nullptr; +} + +template +template +WeakPtr& WeakPtr::operator=(const SharedPtr& other) { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + counter_->AddWeak(); + return *this; +} + +template +WeakPtr& WeakPtr::operator=(const WeakPtr& other) noexcept { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + counter_->AddWeak(); + return *this; +} + +template +WeakPtr& WeakPtr::operator=(WeakPtr&& other) noexcept { + Reset(); + value_ = other.value_; + counter_ = other.counter_; + other.value_ = nullptr; + other.counter_ = nullptr; + return this; +} + +template +WeakPtr::~WeakPtr() { + if (counter_ == nullptr) { + assert(value_ == nullptr); + return; + } + + counter_->RemoveWeak(); + if (counter_->Empty()) { + delete counter_; + } +} + +template +void WeakPtr::Reset() noexcept { + if (counter_) { + counter_->RemoveWeak(); + if (counter_->Empty()) { + delete counter_; + } + } + + value_ = nullptr; + counter_ = nullptr; +} + +template +void WeakPtr::Swap(WeakPtr& other) noexcept { + std::swap(value_, other.value_); + std::swap(counter_, other.counter_); +} + +template +bool WeakPtr::Expired() noexcept { + return counter_ == nullptr || counter_->Get() == 0; +} + +template +SharedPtr WeakPtr::Lock() const noexcept { + SharedPtr shared; + if (counter_ == nullptr || counter_->Get() == 0) { + return shared; + } + + shared.value_ = value_; + shared.counter_ = counter_; + return shared; +} \ No newline at end of file