Reputation: 16148
struct Device;
struct CommandBuffer {
device: &Device,
// ...
}
// Does not work because Rust does not allow internal pointers
struct Something {
device: Device,
command_buffer: CommandBuffer,
}
One solution would be to use an Arc
struct CommandBuffer {
device: Arc<Device>,
// ...
}
struct Something {
device: Arc<Device>,
command_buffer: CommandBuffer,
}
The downside of an Arc
is indirection, an atomic counter and the possibility of escaping the scope and keeping the Device
alive.
Now I don't think that you can work around the one level of indirection in Rust but could it be possible to create something between a Box
and an Arc
?
struct CommandBuffer {
device: BoxRef<Device>,
// ...
}
struct Something {
device: Box<Device>,
command_buffer: CommandBuffer,
}
The main problem that I had while trying to implement BoxRef
was that I need to be able to move a Box
even if there are currently borrows to it. That should technically be safe because of the level of indirection, but I don't think that this can currently be expressed in Rust.
let boxed_device = Box::new(device);
let device_ref = boxed_device.boxed_ref();
// Owner of the reference should be allowed to move
Something{device: boxed_device, CommandBuffer{device: device_ref}}
Could BoxRef
be implemented? I had a quick look at
owning_ref
but it doesn't seem to solve the problem that I have.
What other options do I have to express "internal pointers" in Rust?
Upvotes: 3
Views: 132
Reputation: 3466
This will work:
struct Device;
struct CommandBuffer<'a> {
device: &'a Device, // ...
}
struct Something<'a> {
device: &'a Device,
command_buffer: CommandBuffer<'a>,
}
fn main() {
let dev = Device;
let smth = Something {
device: &dev,
command_buffer: CommandBuffer { device: &dev },
};
}
You should not worry about Arc
performance that much.
The possibility of escaping the scope could be easily dealt with by just writing a newtype that keeps the Arc
private, and only implements Deref
to &T
without Clone
.
Upvotes: 2