I have a vector of unique_ptrs which point to Models, Meshes, etc like this:
std::vector<std::unique_ptr<Model>> mLoadedModels;
I choose unique_ptr because it automatically frees the data upon vector destructor, and also because later on if I need to for example reload all the models (due to OpenGL context tear down/created) I can just internally in my resource manager reset() and make it point to a new Model instance and it wouldnt affect the rest of the system.
My question though is, how would you share the contents of the vector with other systems? You cant just pass the unique_ptr around, because that would change the ownership (due to its unique_ptr), and I want sole ownership in the rersource manager.
The solution I came up with is the following, to wrap the access in the following struct:
template<typename T>
struct Handle
{
Handle(std::unique_ptr<T>& resource) : mResource(resource)
{
}
T& operator*() { return mResource.get(); }
const T& operator*() const { return mResource.get(); }
T* operator->() { return mResource.get(); }
const T* operator->() const { return mResource.get(); }
private:
std::unique_ptr<T>& mResource;
};
typedef Handle<Model> ModelPtr;
ModelPtr GetModel(const std::string& modelName);
// example:
ModelPtr monkey = GetModel("Monkey");
monkey->dance();
// reload resources, and then monkey dereferences to the new Model instance
It feels abit gimmicky though, surely theres a better, more straightforward solution to this?
There is a simple solution to this.
Pass around vec[n].get()
-- raw pointers. So long as you don't store them, and always get them back from the owner, and the owner doesn't destroy them while you are using them, you are safe.
If you aren't willing to follow that level of discipline, what you need is a std::shared_ptr
in the vector
, and pass around and store std::weak_ptr
s. The weak_ptr
s will auto-invalidate when the last shared_ptr
goes away (and by policy, the only persistent shared_ptr
is the one in the owning vector
).
This has the added advantage that if you are in the middle of doing work on an element and the vector
clears itself, you don't segfault. You access a weak_ptr
by .lock()
, which returns a shared_ptr
, during whose lifetime the raw pointer is guaranteed to be good.
The downside is that this ups the cost, the upside is that it allows for weak shared ownership and lazy notification of invalidation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With