GregoryConrad / rearch-rs

Re-imagined approach to application design and architecture
https://crates.io/crates/rearch
MIT License
81 stars 4 forks source link

Add `container.read_ref` API #48

Closed GregoryConrad closed 5 months ago

GregoryConrad commented 5 months ago

Returns a smart pointer that Derefs into references. Uses downgradable RwLock

GregoryConrad commented 5 months ago

I'm not even sure this is possible with the RwLockReadGuard::map from parking_lot. It works for one capsule because the mapping function has a signature:

F: FnOnce(&T) -> &U

So U can simply be MyCapsule::Data, but what about multiple capsules? We need to return a ref (&U), but that screws things up when we need to return multiple values. Even though what I'm trying to do is certainly safe (the capsule data's lifetime will live as long as read txn), I'm not sure it is possible in this API without unsafe.

Before I forget: we cannot just have a read_ref that works for one capsule at a time because:

  1. one thread holding multiple read locks can screw things up & cause panics IIRC
  2. But more importantly, if another capsule needs to be built as apart of a subsequent read_ref call, a write txn must be taken. that'll cause a deadlock, if not a panic.

We can't just return a ref of the capsules without somehow still holding the RwLockReadGuard either; that'd be unsafe as the temporary would be dropped and we'd have a ref.

So the solution is to return a struct that has:

GregoryConrad commented 5 months ago

Returning an Fn closure (will need to close over capsule ids) might be problematic. Will require generics and other not-so-fun things that shouldn't be needed.

Wondering if an API like this may be better (which would also prevent a user from holding the read lock too long):

let res = container.read_ref((a_capsule, b_capsule), |(a_data, b_data)| {
  let res = a_data + b_data;
  res
});