Search code examples
c++pointersboostshared

Boost shared pointers C++ : shared pointer unable to free resource on release


I'm running into a problem where I can't get rid of the last shared pointer and I kinda need it actually.

So what I have is a manager and some worker threads. The manager keeps a collection of shared pointers to different resources. A worker may ask the manager for a shared pointer to a resource. There will always be 1 or more workers with a shared pointer to the resource. My end goal is that when all workers are done with the resource, the resource is deleted. However, in this scheme, the manager always maintains a shared pointer to the resource so even when no workers are hanging on to the shared pointer, the resource won't get deleted b/c the ref count should always be at least 1 since the manager is hanging onto it. I need the manager to hang on to a shared pointer to the reference so that if any worker comes asking for a shared pointer, the manager will be able to provide it one.


edit: When the resource is created a worker already has it. So at its creation its ref count should be two (manager has it, and a single worker has it). When the ref count hits one (only the manager has it), I would like it to be deleted. If the resource had already been deleted and a worker comes looking for it, the resource shall be recreated.


edit2: some code:

SomeSharedPointer Manager::getResource(String unique_id) 
{ // if unique id exists, return its mapped shared pointer, if unique id doesn't exist, create the resource, assign it a shared pointer, and stick it in the map 
}


class Worker
{
    SomeSharedPointer my_sp;

    Worker()
    {
       String someUniqueId = "http://blah.com"
       my_sp = Manager::getResource(someUniqueId);
       // do some work on the resource
    }

    ~Worker()
    {
        my_sp.reset(); // done with resource
    }
}

Solution

  • Why is the manager holding a shared_ptr (strong reference) to the object if it doesn't need to retain control, only pass it on? Not seeing your code, it seems like having the manager hold a weak_ptr and then pass that on to the workers, who lock it into a shared_ptr on their end. That will allow the manager to pass on references without owning one of its own.

    class Worker
    {
        SomeSharedPointer my_sp;
    
        Worker()
        {
            String someUniqueId = "http://blah.com"
            weak_ptr wp = Manager::getResource(someUniqueId);
            my_sp = wp.lock();
    
            // do some work on the resource
        }
    
        ~Worker()
        {
            //my_sp.reset(); // handled automatically, as part of how shared pointers work
        }
    }
    

    If a worker finishes and releases the resource, it will be destroyed and the manager will no longer be able to hand out references (which can be tested in getResource and reloaded). This doesn't seem quite optimal, but is part of your design, so it should work like that well.

    Edit: You could also have getResource return a shared pointer, and have the manager hold the weak pointer, attempt to lock, do checking/reloading internally, and then return the shared pointer. As weak_ptrs can't be directly created, that may work somewhat better.

    On the other hand, you could provide a function to compliment the one providing the workers with the pointer that releases it and does count checking in the manager.