HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Alternate "weak" pointer implementation

Submitted by: @import:stackexchange-codereview··
0
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

Solution

You should probably try to understand the reasoning behind 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.