patterncppMinor
Alternate "weak" pointer implementation
Viewed 0 times
pointerimplementationweakalternate
Problem
```
namespace Impl
{
template
class SharedPtrCounter
{
public:
SharedPtrCounter(T* e) : element(e)
{
}
void IncrementFlimsyCounter()
{
++flimsyCounter;
}
void DecrementFlimsyCounter()
{
if(--flimsyCounter == 0 && !element)
{
delete this;
}
}
void Kill()
{
element = nullptr;
if(flimsyCounter == 0)
{
delete this;
}
}
int Count() const
{
return flimsyCounter;
}
T* Element() const
{
return element;
}
private:
int flimsyCounter = 0;
T* element;
};
}
template class FlimsyPtr;
template
class SharedPtr // limited implementation of actual shared pointer (only 1 instance allowed, can be promoted though)
{
friend class FlimsyPtr;
public:
using ElementType = T;
template
static SharedPtr Make(Args && ...args) { return SharedPtr(new T(std::forward(args)...)); }
SharedPtr() : element(nullptr), counter(nullptr)
{
}
~SharedPtr()
{
if(counter)
{
counter->Kill();
}
}
SharedPtr(const SharedPtr&) = delete;
SharedPtr& operator = (const SharedPtr&) = delete;
SharedPtr(SharedPtr&& shared)
{
element = shared.element;
counter = shared.counter;
shared.element = nullptr;
shared.counter = nullptr;
}
void Reset()
{
if(counter)
{
counter->Kill();
element = nullptr;
counter = nullptr;
}
}
int Count() const
{
return counter ? counter->Count() : 0;
}
ElementType* Get() const
{
return element;
}
ElementType* operator -> ()
{
return element;
}
private:
SharedPtr(ElementT
namespace Impl
{
template
class SharedPtrCounter
{
public:
SharedPtrCounter(T* e) : element(e)
{
}
void IncrementFlimsyCounter()
{
++flimsyCounter;
}
void DecrementFlimsyCounter()
{
if(--flimsyCounter == 0 && !element)
{
delete this;
}
}
void Kill()
{
element = nullptr;
if(flimsyCounter == 0)
{
delete this;
}
}
int Count() const
{
return flimsyCounter;
}
T* Element() const
{
return element;
}
private:
int flimsyCounter = 0;
T* element;
};
}
template class FlimsyPtr;
template
class SharedPtr // limited implementation of actual shared pointer (only 1 instance allowed, can be promoted though)
{
friend class FlimsyPtr;
public:
using ElementType = T;
template
static SharedPtr Make(Args && ...args) { return SharedPtr(new T(std::forward(args)...)); }
SharedPtr() : element(nullptr), counter(nullptr)
{
}
~SharedPtr()
{
if(counter)
{
counter->Kill();
}
}
SharedPtr(const SharedPtr&) = delete;
SharedPtr& operator = (const SharedPtr&) = delete;
SharedPtr(SharedPtr&& shared)
{
element = shared.element;
counter = shared.counter;
shared.element = nullptr;
shared.counter = nullptr;
}
void Reset()
{
if(counter)
{
counter->Kill();
element = nullptr;
counter = nullptr;
}
}
int Count() const
{
return counter ? counter->Count() : 0;
}
ElementType* Get() const
{
return element;
}
ElementType* operator -> ()
{
return element;
}
private:
SharedPtr(ElementT
Solution
You should probably try to understand the reasoning behind
If you only need to check alive status then I suggest using
If you are in a single threaded environment then your implementation is okay. But if you ensure the shared_ptr is cleaned up before you return then shared_ptr's life won't be extended.
std::weak_ptr::lock. After you get the pointer you need to be sure that it won't get deleted by another thread while you are using it. That's why it returns a shared_ptr to let the calling code decide when the object is allowed to be deleted.if(auto ptr = flimsy.Get())
{
// set and alive,
// however ptr cannot be used because another thread can still delete the owning SharedPtr at any point.
}If you only need to check alive status then I suggest using
std::weak_ptr::expired().if(!weak.expired())
{
// set and alive. no ptr to work with
}If you are in a single threaded environment then your implementation is okay. But if you ensure the shared_ptr is cleaned up before you return then shared_ptr's life won't be extended.
if(auto ptr = weak.lock())
{
// set and alive,
// ptr can be used
//at the end of the block ptr will be cleaned up and won't prevent cleanup
}Code Snippets
if(auto ptr = flimsy.Get())
{
// set and alive,
// however ptr cannot be used because another thread can still delete the owning SharedPtr at any point.
}if(!weak.expired())
{
// set and alive. no ptr to work with
}if(auto ptr = weak.lock())
{
// set and alive,
// ptr can be used
//at the end of the block ptr will be cleaned up and won't prevent cleanup
}Context
StackExchange Code Review Q#99087, answer score: 3
Revisions (0)
No revisions yet.