3 ms·
Then the lists should only have a weak_ptr to the object. Something is handling both list [1], that something could own the object, or maybe something external
by letzjuc 13y ago
Then the lists should only have a weak_ptr to the object.
Something is handling both list [1], that something could own the object, or maybe something external to that. Giving ownership of the object to both list is a design error [2].
[1] e.g. if the two list are an implementation detail of a data structure, the data-structure itself could own the objects in the lists.
[2] Do non-deterministic garbage collectors that handle cycles allow you to have a resource with multiple owners? Yes. Should you do it? No, god, please don't.
- ori_b 13y agoIt's only a design error when you don't have a GC. Imagine you have an arbitrary long lived connected cyclic graph that can be incrementally updated from multiple short lived worker threads. With a GC, this is a no brainer: just put the objects in the graph. No workarounds, no extra tracking. Without a GC, on removing a node, you have to walk to essentially do a mark/sweep of the graph to find dead nodes that were connected through the node you removed.
- letzjuc 13y agoHave a vector of shared_ptr that own the objects in the graph and build a graph with weak_ptr ? Removing an object is just as easy as removing an element from the vector. (If you test the weak_ptrs on use, that's actually the only thing you would need to do).
- mikeash 13y agoIsn't that equivalent to using a shared_ptr directly, just unnecessarily complicated? Reference counting works fine as long as you don't have cycles, of course.
- letzjuc 13y agoThe solution above works even if your graph has cycles. Of course if you know that it doesn't you can just build the graph with unique_ptrs.
- mikeash 13y agoIt works with cycles, as long as you can know exactly when you want to remove something from the graph (as opposed to having it be removed when no longer referenced). Reference counting works fine that way too, though. It's a bit more work, but you just dive into the structure and manually remove references which breaks any cycles it may be involved in.
- danbruc 13y agoshared_ptr means reference counting, reference counting means you lose determinism because you no longer know if releasing a reference will trigger releasing a resource. Delay and offload releasing the resource to a separate thread, you lose your guarantees when a resource is actually freed, too, just like using a garbage collector. And I know it for the .NET GC, they tried a reference counting GC as alternative to a collecting GC and it performed worse and comes with the cycle trouble.
- dllthomas 13y agoIsn't it better to walk the graph than all your objects, other things being equal? Of course, not having to implement the garbage collector yourself is a benefit.
- mikeash 13y agoSharing immutable data between multiple places with no single master owner is a perfectly reasonable thing to do in a program.
- letzjuc 13y agoI fail to see why you need cycles' support for that.
- mikeash 13y agoYou asked for a situation where the lifetime of a resource can't be directly tied to the lifetime of a single storage location. Cycles are a different matter.
- letzjuc 13y ago>You asked for a situation where the lifetime of a resource can't be directly tied to the lifetime of a single storage location. I don't think I asked for that but correct me if I did (maybe I'm just not understanding your point). Anyways, could you elaborate why shared_ptr, unique_ptr, and weak_ptr don't work in that case?
- mikeash 13y agoOops, wasn't you, but the OP I was responding to initially. shared_ptr works fine for my example. Shared immutable state is a case where reference counting works extremely well, since immutability implies no cycles.
- danbruc 13y agoI am mostly developing business applications. The user decided to view a couple of orders, orders reference products and some of the orders reference the same product. Who owns the product? Definitely non of the orders and neither the form showing the order. Well, I could attach them to the main form, but now they stay in scope until you close the application. This is not what we wanted. I could implement referencing counting - use shared_ptr - but well, the designers of garbage collectors tried it and found reference counting garbage collectors perform worse than collecting garbage collectors. Am I missing a obvious solution?
- letzjuc 13y agoIt's simple. The key is that something has to have _ownership_ of the products. [1] User decides to view a couple of orders. Orders reference products. Those products are managed by something (e.g. an unordered_map of shared_ptr). The order can check, is my product there? If so, i'll copy the shared_ptr to it. Otherwise, I create a shared_ptr for a product and store a copy in the manager. When the order's destructor is triggered, you check the count of the shared_ptr. If it is 2 (i.e. the order and the manager), the order removes the shared_ptr. [1] Single ownership is the key concept, not reference counting which is just an implementation detail.
- danbruc 13y agohttps://news.ycombinator.com/item?id=7315392 https://news.ycombinator.com/item?id=7315392 https://news.ycombinator.com/item?id=7315575 https://news.ycombinator.com/item?id=7315575 (Don't want to duplicate the comment once again.)