Maik Klein
Maik Klein

Reputation: 16148

Is it possible to have `internal pointers` without using an `Arc`?

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}}
  1. Could BoxRef be implemented? I had a quick look at owning_ref but it doesn't seem to solve the problem that I have.

  2. What other options do I have to express "internal pointers" in Rust?

Upvotes: 3

Views: 132

Answers (1)

dpc.pw
dpc.pw

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

Related Questions