push рор
push рор

Reputation: 59

How to make not owning pointers like shared_ptr?

In my resource manager, the createTexture method should produce a pointer to the texture. And I want to delete a resource when only the manager owns it. How can I achieve this? If I use shared_ptr, the resource manager will store its shared_ptr pointer to the texture and will not be able to delete it.

class ResourceManager
{
    vector<shared_ptr<Texture>> _textres;

public:
    shared_ptr<Texture> CreateTexture()
    {
        auto tex = shared_ptr<Texture>(new Texture);
        _textures.push_back(tex);
        return tex;
    }
}

int main
{
    ResourceManager rm;

    {
        auto tex = rm.CreateTexture();
        // Do something with texture...
    }

    // Problem here: ResourceManager doesn't remove the texture because he owns it
}

Upvotes: 1

Views: 109

Answers (2)

metal
metal

Reputation: 6332

I think what you're asking for is a shared_ptr that invokes a callback when the count is decremented to 1. Your manager registers for that callback in the CreateTexture() function when it creates the smart pointer and then checks whether to invoke it whenever someone decrements the reference count.

Corner case to watch out for: the count will start as 1, and you don't want to delete it then.

Compare the C++ FAQ's implementation of an intrusive reference-counted smart pointer as a starting point. The work ahead of you is to add a std::function or other callable to be invoked at the right time.

Implementing smart pointers can be a little tricky, especially when you mix in threading, but for other starting points, you can compare implementations from boost::shared_ptr, which became standardized, and Loki's SharedPtr, which is described in the classic Modern C++ Design by Alexandrescu.

An alternative to re-implementing shared_ptr would be to use its custom deleter to invoke the callback, but you'll have to play some games to make that work.

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385104

What you need is:

  • A vector of weak_ptr instead of shared_ptr
  • A shared_ptr whose deleter function (invoked when no more non-weak references are in scope) looks up the object in the vector and removes that entry

A custom deleter may be provided using the shared_ptr constructor. Be sure to actually do the deletion as well, because that behaviour will no longer be automatic.

Also be careful about some confusions with respect to weak_ptr behaviour during deleter invocation; you could always switch to a raw pointer instead which basically has the same effect without any of the burning questions.

Note that this change makes your manager no longer "own" the textures, but per your described semantics ("delete a resource when only the manager owns it") it never really did anyway.

Upvotes: 2

Related Questions