Using C++11 smart pointers for asset manager

Started by
22 comments, last by l0calh05t 10 years, 3 months ago

So, i'm working on a small asset manager for my engine, and i'm using type inference and smart pointers from C++ to add the assets to an unordered_map. I add a string and the smart pointer to this set:


assets.insert(make_pair('my-bitmap', make_shared<Bitmap>(100,100)));

This assets is a member of the AssetsManager, which it's single instance is stored in a member of the Scene object. Is that a good practice? Is this more efficient than another solution, since i don't have to work on pointers manually? Also, what happens when i remove the Scene object?

Advertisement


Is that a good practice?

It seems OK to me.


Is this more efficient than another solution, since i don't have to work on pointers manually?

No. Why would it more efficient? The point of smart pointers is that it is easier to get things right. It actually generally sacrifices a bit of efficiency in the process. But that's OK.


Also, what happens when i remove the Scene object?

The shared pointer gets destroyed, which means that the reference counter will be decremented. If it reaches 0 (which means no one else is using this resource), the Bitmap will be destroyed and its memory released.

So, it should work like a charm? Amazing! biggrin.png

Why are you using shared_ptr?

To me it seems "natural" that an asset manager "owns" the assets exclusively. It seems to be strange that an asset can outlive the manager, so no shared ownership should be required.

Having said this, unique_ptr is the more obvious solution to your problem.

Do not use shared_ptr unless you really need shared ownership, especially if efficiency is your concern.

Why are you using shared_ptr?

To me it seems "natural" that an asset manager "owns" the assets exclusively. It seems to be strange that an asset can outlive the manager, so no shared ownership should be required.

Having said this, unique_ptr is the more obvious solution to your problem.

Do not use shared_ptr unless you really need shared ownership, especially if efficiency is your concern.

I disagree.

Having a shared_ptr in asset manager and handing out weak_ptr to asset users is a solid strategy.

[Thats reply to cdoubleplusgood's post, in the meantime someone posted so just want to clarify as I didn't quote the original post ;)]

Question is - whats his plan to retrieve assets from manager? If he uses unique_ptr, he shouldn't really store any reference/pointer so he has to query manager every time he uses an asset, which will probably be every frame. He can't really pre-fetch assets that he uses and release them when he's done.

Also, when using shared_ptr manager knows when its the only owner left and can release resource (or keep it for some time before releasing completly).

How would unique_ptr be used in such pipeline?


Where are we and when are we and who are we?
How many people in how many places at how many times?

Having a shared_ptr in asset manager and handing out weak_ptr to asset users is a solid strategy.

I don't understand this strategy. Why weak_ptr? The users will have to lock and check for expiration everytime using the asset. If you already have shared_ptr in the manager, why not for the users?

[Thats reply to cdoubleplusgood's post, in the meantime someone posted so just want to clarify as I didn't quote the original post ;)]

Question is - whats his plan to retrieve assets from manager? If he uses unique_ptr, he shouldn't really store any reference/pointer so he has to query manager every time he uses an asset, which will probably be every frame. He can't really pre-fetch assets that he uses and release them when he's done.

Also, when using shared_ptr manager knows when its the only owner left and can release resource (or keep it for some time before releasing completly).

How would unique_ptr be used in such pipeline?

I don't know what the OP's manager actually does and what he wants to achieve. Of course, using shared_ptr for automatic resource management can be very convenient. However, he asked for efficiency, and shared_ptr is not the most efficient way to maintain pointers, especially because shared_ptr is thread safe even if you don't need it: The reference counters are always synchronized.

Having a shared_ptr in asset manager and handing out weak_ptr to asset users is a solid strategy.

I don't understand this strategy. Why weak_ptr? The users will have to lock and check for expiration everytime using the asset. If you already have shared_ptr in the manager, why not for the users?

Because they're users. Giving out only weak_ptr's opens up the possibility to, f.ex. unload some resources that aren't actually being used in favor of some other high priority resources. This would need some mechnanism to avoid thrashing, tho. If you used shared_ptr instead, you wouldn't have the possibility to track actual usage.

Of course, using shared_ptr for automatic resource management can be very convenient. However, he asked for efficiency, and shared_ptr is not the most efficient way to maintain pointers, especially because shared_ptr is thread safe even if you don't need it: The reference counters are always synchronized.
This is certainly correct, and something to always keep in mind when copying around shared pointers. Passing around a shared or weak pointer is not close to a no-op as compared to passing around a raw pointer.

However, in the context of an asset manager you need to consider that the rather slow atomic increments/decrements used in the shared pointer are entirely neglegible compared to only a single disk access for loading an asset. We're talking of 30-50 nanoseconds versus 8-10 milliseconds.

Formally, giving out a weak pointer as suggested by Mnemotic is the correct thing to do (though giving out shared pointers would probably work just fine 90% of the time too), seeing how the manager owns the resources and should be allowed to toss them on a as-needed base, but safely so no resources "disappear" while in use.

This topic is closed to new replies.

Advertisement