-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disambiguation of multiple Interpreters/VMs and associated data #5410
Comments
Another (maybe less invasive and more versatile) approach would be to pass the aforementioned user-data as argument to the The passed data would be added as another parameter next to the let mut my_counter: u32 = 0;
interpreter.enter_with(&mut my_counter, |vm| { … });
fn increment_counter(vm: &VirtualMachine, counter: &mut u32) {
counter += 1;
} A huge benefit would be that the I don't know how hard that would be to implement in the macro so that there's no ambiguity between ordinary arguments coming from Python and UserData. |
Adding a customizable user data field requires customizable area of VirtualMachine, which leads generic type parameter which will be not very useful for most of users. On the other hand, adding a simple, probably incremental id for each VM can be easier and less fragile. Typically a pointer value of VM object can be an id of it, but I am not sure it is safe in RustPython. @coolreader18 Do you have a good idea? |
I'm facing a new problem which looks like it would benefit from a solution that doesn't rely on shared state via global variables: I have an some pseudocode to explain the problem: fn update(state: &Arc<Mutex<ApplicationState>>) {
let mut state_lock = state.lock().unwrap();
// work with the state here
interpreter.enter(|vm| {
vm.call_into_some_python_function();
// this function will in turn call `update_application_state` (see below)
});
// work with the state here even more
// state will be unlocked here; transaction completed
}
#[pymodule]
pub(crate) mod py_handlers {
#[pyfunction]
fn update_application_state(vm: &VirtualMachine) -> PyResult<()> {
// ← here I need access to the `MutexGuard`
}
} If I was able to pass the fn update(state: &Arc<Mutex<ApplicationState>>) {
let mut state_lock = state.lock().unwrap();
// work with the state here
interpreter.enter_with_userdata(&mut state_lock, |vm| {
vm.call_into_some_python_function();
// this function will in turn call `update_application_state` (see below)
});
// work with the state here even more
// state will be unlocked here; transaction completed
}
#[pymodule]
pub(crate) mod py_handlers {
#[pyfunction]
fn update_application_state(vm: &VirtualMachine, application_state: &mut MutexGuard<ApplicationState>) -> PyResult<()> {
application_state.update();
}
} I could imagine to work around this problem by storing the entire Is there an easier way to achieve that? |
This would imply that a VM never gets moved in memory (in other words |
I tried to implement the idea to get a feeling on how big the fallout would be … doesn't look good :( Adding the user data to just I hope there's a way to keep I'll wait for more feedback now and try to find a hack to work around the |
Is it possible to add a parameter to Then making a |
Here is a concept without a new type fn update(state: &Arc<Mutex<ApplicationState>>) {
let mut state_lock = state.lock().unwrap();
// work with the state here
let ptr = state_lock.deref_mut() as *mut u8; // This is ugly, but safe as long as this is only used in the lock
interpreter.enter(|vm| {
let context = vm.ctx.new_int(ptr);
vm.call_into_some_python_function(context);
// this function will pass context to `update_application_state`
});
// work with the state here even more
// state will be unlocked here; transaction completed
} |
Also I guess I would have to access the |
An idea that's been in my head for a while is an |
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.As a workaround I abuse the
wasm_id
to disambiguate between multiple VMs and store all state in a globalHashMap
with the VM's id as key.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
orname
would make this pattern a little more official. Aname
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):
The default should make it (mostly) backwards-compatible and also zero-cost for all existing implementations.
The above example would become:
As
vm
is passed immutably, one would have to rely on inner mutability for theUserData
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.The text was updated successfully, but these errors were encountered: