I am toying with a non-trivial Rust project to get a feel for the language. There's a pattern I keep seeing in my code which isn't easy to express in Rust. I wonder what the "right thing to do" is here.
The pattern is as follows. I have some container, which contains some components of different types. The container as a whole is send-able . The components form a complex graph (with cycles). What I'd like to do is something like this: - Declare a pool of objects of some types, which is held by the container. - Declare pointer-to-object whose scope is the container; that is, the lifetime of the pointer is the lifetime of the container. The pointer can be freely passed around, cloned, etc. but (for mutable objects), only one mutable access is allowed at a time. This calls for something between GC pointers and RC pointers. GC is out, because it isn't send-able. RC is out, because it doesn't allow for loops. So right now I use explicit pools and a semi-safe (that is, unsafe...) "smart pointer" type. And I don't support dropping objects until the whole container is done (which is OK in my specific app but isn't really a good solution). Ideally what I'd like to see is separating heaps from tasks. That is, suppose that GC pointers had a heap attribute (like borrowed pointers have a lifetime attribute). By default, each task has a heap, but it is also possible to define additional heaps (like we have the static lifetime and can also define additional lifetimes). So, the container could hold a heap and then many components with heap-scoped pointers. The whole thing is send-able and GC is done in the scope of each heap on its own (like today). There are implications on the type system (no mixing pointers between different heaps, unless the heaps are nested) - this seems very similar to the lifetimes type checking... Overall this seems very symmetrical with lifetimes. Basically, lifetimes == static (compile-time computable) free/malloc; heaps == dynamic (run-time computable) free/malloc. One interesting pattern allowed by this is ad-hoc actors (there are others of course). Currently, if one wants to write actor-style code, one ties in the GC pointers to one heap of one actor, which means one forces the parallelization policy to one task per actor. One could argue that the run-time should be good enough that any aggregation of actor threads to OS threads would be done optimally (which is a good goal); but in some apps, to get good performance one would like to control this. If we could separate heaps from tasks, we could spawn fewer tasks (roughly the number of OS threads) and use application code to decide which actor runs when and where (e.g., in combination with thread affinity to ensure better cache locality). At any rate - is this something that makes sense in the Rust view? If so, is there a chance of something like that being added (a completely separate question :-)?
_______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
