4 ms·
> using/try-resource/defer/scope, or higher order functions Those only cover cases where your resource's lifetime matches a stack frame's lifetime. It doesn't
by kentonv 11y ago
> using/try-resource/defer/scope, or higher order functions
Those only cover cases where your resource's lifetime matches a stack frame's lifetime. It doesn't cover the case where your resource's lifetime matches the lifetime of some owner object. For that you need destructors, by definition.
Ownership transfer is also very hard to model robustly unless you have linear types / move semantics (which even C++ didn't really have until C++11).
- pjmlp 11y agoYou can map them into higher level constructs that basically are a kind of reference counting on top of GC. For example, multiple threads sharing a socket connection. Just create a barrier and have a cleanup thread closing the socket when everyone joins. Similar patterns can be applied to other resources. Ownership transfer is usually not an issue in GC enabled languages in terms of data structures, specially if every thread keeps the OS resources locally for itself.
- pcwalton 11y ago> You can map them into higher level constructs that basically are a kind of reference counting on top of GC. > For example, multiple threads sharing a socket connection. Just create a barrier and have a cleanup thread closing the socket when everyone joins. Nobody's saying you can't do it. But RAII makes it way easier. When you implement reference counting manually, you'll find that you want something like a copy constructor, so you remember to bump the reference count every time a new instance of the object is assigned. Then you find that you'll want the compiler to automatically drop reference counts when the object goes out of scope, so you don't forget. Then you'll find you want move semantics, to allow transfer of references without adjusting the counts. You'll discover you want the correct behavior in the presence of exceptions. In short, you want RAII.
- pjmlp 11y ago> Nobody's saying you can't do it. But RAII makes it way easier. Except RAII doesn't work for heap allocated object and then it is back to reference counting. > You'll discover you want the correct behavior in the presence of exceptions. In short, you want RAII. Well, then one would have implemented a GC by hand with worse performance, specially in multi-threading contexts, unless there is someone on the team expert in hazard pointers and related performance tricks. Maybe a performance improvement would be for the ANSI C++ standard to mandate that that compilers give special treatment to *_ptr<>(), so that they can elide needless calls, but I don't see it happening. In FP languages one can use the concept of transactions, yes the M word, to encapsulate scope based workflows where the resources are to be released at the end. What I can definitely see killing GC is affine types becoming mainstream, but they need to be made more friendly for the average Joe developer. Rust made them easier than ATS or Cyclone, but still a bit hard. I think ParaSail's work might also be worth checking in this regard.
- dbaupp 11y agoA thread waiting on a barrier/joining other threads seems like reference counting by another name, to me. (Except, much more manual.)
- pjmlp 11y agoIt is, but I don't consider it much more manual, as it is done with help of the threading library and super easy in many languages with rich runtime libraries. Edit: I forgot to say that this is no much different that doing RAII FP style. Those M concepts are great.