Skip to content

Disambiguation of multiple Interpreters/VMs and associated data #5410

@kawogi

Description

@kawogi

Summary

I think there's a need for a way to give VMs an identity and associate user data with them. The user-data shall be accessible to the Rust-side that handles calls from a Python script.

(I'm very new to this project so I might have missed an existing feature that would solve my issue. Please let me know if that is the case.)

Expected use case

I'm working on a framework where multiple Python VMs shall run in parallel. All of them share the same API so every call from a Python Script ends up in the same Rust function. Imagine something simple such as fn increment_counter() where each script instance shall have its own counter.

fn increment_counter(vm: &VirtualMachine) {
   // where to store the counter and to select the one associated with `vm`?
}

As a workaround I abuse the wasm_id to disambiguate between multiple VMs and store all state in a global HashMap with the VM's id as key.

// pseudocode

thread_local! {
    pub(super) static COUNTERS: RefCell<HashMap<String, u32>> = RefCell::default();
}

fn increment_counter(vm: &VirtualMachine) {
    let vm_id = vm.wasm_id.as_ref().unwrap();
    API_CLIENTS.with_borrow_mut(|counters| {
        let mut counter = counters.get_mut(&self.id).expect("unknown VM");
        counter += 1;
    });
}

Alternatively: Assuming that only a single VM can be running per thread, I could use a global thread_local variable to indicate which VM is running and setting this whenever I plan to enter a VM.

Maybe a new field id or name would make this pattern a little more official. A name could also be used to name the VM in error messages and logs.

An even better approach might be to store the associated data itself within the VirtualMachine. IIUC this data would be the rust-counterpart of the Python context.

Suggested change (all names to be bike-shedded):

pub struct VirtualMachine<UserData = ()> {
    pub user_data: UserData,
}

The default should make it (mostly) backwards-compatible and also zero-cost for all existing implementations.

The above example would become:

fn increment_counter(vm: &VirtualMachine<AtomicU32>) {
    vm.user_data.fetch_add(1, Ordering::Relaxed);
}

As vm is passed immutably, one would have to rely on inner mutability for the UserData type.

I know VirtualMachine is a central structure with a lot of references so I don't expect this change to be accepted without a thorough discussion. If we can agree about a solution I would volunteer to do the implementation.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions