Skip to content
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

Pico - thoughts on multithreadedness #408

Open
rbalicki2 opened this issue Feb 20, 2025 · 0 comments
Open

Pico - thoughts on multithreadedness #408

rbalicki2 opened this issue Feb 20, 2025 · 0 comments
Labels

Comments

@rbalicki2
Copy link
Collaborator

rbalicki2 commented Feb 20, 2025

I have an inkling that separating the dependency stack from the storage will make something better. e.g. if the API was

struct Storage { ... }
// and DbStack would either be
struct DbStack<'db> {
  storage: &'db Storage,
  stack: Vec<Vec<Dependency>> // Notice the double Vec
}
// or
struct DbStack<'parent, 'db: 'parent> {
  storage: &'db Storage,
  parent_pointer: Option<&'parent mut DbStack>
  dependencies: Vec<Dependency>
}

Then we could invoke memoized functions like

let storage = create_storage(); // this is Sync
let stack = storage.create_stack(); // you can call this many times. It contains a reference to storage
memoized_function(stack); // this takes &mut stack

// since its Send you can
tokio::spawn(|| {
  let stack = &storage.create_stack();
  memoized_function(stack)
})

I think the stack is the only thing we care about being in one thread.

If everything is a DAG, deadlocks are avoidable (I added "no loops" to #339), e.g. in this case:

fn a(db_stack) {
  first(db_stack)
  second(db_stack)
}
fn b(db_stack) {
  second(db_stack)
  first(db_stack)
}

Both a and b could just wait for the other to complete first or second. And that's optimal behavior, anyway.

And you can't modify a source without &mut, so there can't be a dependency stack created in that case.


Anyway, even before we do multi-threadedness, this seems to clean things up conceptually.


I don't think a Vec is the right abstraction for the dependency stack. Instead, each function call has a pointer to the parent, and the parent has to await the children. So, I sort of imagine that calling child_memoized_function(db_stack) creates a new db_stack with a pointer to the parent.

Anyway, in a single threaded context, a Vec is fine.


I consider this exploratory and low-priority

@rbalicki2 rbalicki2 changed the title Pico - multithreadedness Pico - thoughts on multithreadedness Feb 20, 2025
@rbalicki2 rbalicki2 added the pico label Feb 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant