0

I want to have a pool of shared objects whose class name is Shader. I want a "client" to be able to request a Shader with certain parameters from the pool manager, and if there's one already in the pool the manager will return a pointer or reference to it, otherwise it creates a new Shader and adds it to the pool before returning its reference. Easy enough so far.

However, I also want the Shaders to be automatically deleted when all the clients have finished with them. Is this possible by implementing the pool as a container of std::weak_ptr and returning std::shared_ptr to the clients? Ie if I call weak_ptr::lock() multiple times on the same object are the shared_ptrs it returns linked to each other correctly, or does it return independent shared_ptrs leading to undefined behaviour? cpprefrence.com implies the latter, but they don't explictly point out the danger of that, and it seems to me that an opportunity was missed to make weak_ptr considerably more useful.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
realh
  • 962
  • 2
  • 7
  • 22
  • How would your container know if its element got invalidated? You would need to perform some garbage collecting if you don't plan on using reference counting. – luk32 Jan 22 '15 at 17:18

2 Answers2

1

Calling weak_ptr::lock() multiple times is ok, the returned shared_ptr is configured properly, i.e. all shared_ptr-s having the common pointee are sharing the reference counter.

Note that lock() returns non-null pointer iff there is at least one shared_ptr pointing to the object. If there was none then the object would have been already destroyed. Hence lock() absolutely must implement sharing right otherwise it would break on every call.

Finally shared_ptr supports custom deleter functions, they may be useful to remove stale entries from the cache.

Community
  • 1
  • 1
Nick Zavaritsky
  • 1,429
  • 8
  • 19
  • Yes, the custom deleter should be handy for exactly that. – realh Jan 22 '15 at 20:15
  • If shaders remove themselves from pool during destruction then there are no need for special deleters. – Öö Tiib Jan 22 '15 at 22:20
  • @ÖöTiib yes this is a working option but in my opinion, making shaders aware of the cache is a somewhat sloppy design. At least there are some benefits in keeping them separated. – Nick Zavaritsky Jan 22 '15 at 22:29
  • @NickZavaritsky OP describes factory method from where "clients" can request shared shaders. I would make that method and the pool as static members of shader to keep its public interface small and clear. I'm unsure what about such design is sloppy. – Öö Tiib Jan 22 '15 at 22:41
  • @ÖöTiib my idea was that shader object should have the single responsibility of being a shader, making it responsible for the cache goes against SOLID principles. Sorry there is nothing sloppy in your design, please excuse me. I suggest we conclude this discussion now) – Nick Zavaritsky Jan 22 '15 at 23:25
1

Is this possible by implementing the pool as a container of std::weak_ptr and returning std::shared_ptr to the clients?

Yes.

Ie if I call weak_ptr::lock() multiple times on the same object are the shared_ptrs it returns linked to each other correctly, or does it return independent shared_ptrs leading to undefined behaviour?

weak_ptr::lock() returns shared_ptr linked to other shared_ptrs to that object or empty shared_ptr when there are no other shared_ptrs (IOW weak_ptr::expired() is true).

cpprefrence.com implies the latter, but they don't explictly point out the danger of that, and it seems to me that an opportunity was missed to make weak_ptr considerably more useful.

I can not understand how you read that implication.

Öö Tiib
  • 10,809
  • 25
  • 44
  • My wrong inference was because I read too quickly and misinterpreted what *this meant in a weak_ptr (I stupidly thought it would be the raw pointer owned by weak_ptr) and didn't spot that shared_ptr had a constructor accepting weak_ptr &. – realh Jan 22 '15 at 20:14