Callbacks vs Event-and-dispactch


#1

I was trying to do some async operation in background thread and was wondering which is more recommended in Rust:

so the background thread has an mpsc::Receiver and run it in a loop. The foreground thread has the corresponding Sender.

Way 1: Using Events (as Enums)

using channel::<Event>()

enum Event {
    One {
         field_0: SomeType_0,
         field_1: SomeType_1,
    },
    Two(SomeType_2),
    ....
}

Background thread - Running Worker Object:

for it in recv.iter() {
    match it {
         Event::One { field_0, field_1, } => self.execute_one(field_0, field_1),
         Event::Two(val) => self.execute_two(val),
         ....
     }
}

ForeGround thread:

sender.send(Event::One { field_0: SomeType_0::new(), field_1: SomeType_1::new(), });
sender.send(Event::Two(SomeType_3::new());

Way 2: Callbacks (Like in boost::asio etc):

using channel::<FnOnce(&mut WorkerObject)>() // Don't know the exact representation, but you get the idea - read on for more understanding of the intent

Background thread - Running Worker Object:

loop {
    let closure = recv.recv();
    closure(&mut self);
}

ForeGround thread:

sender.send(|worker: &mut WorkerObject| worker.execute_one(SomeType_0::new(), SomeType_1::new());
sender.send(|worker: &mut WorkerObject| worker.execute_two(SomeType_2::new());

So which out of these two is more preferable in general and in rust ?


#2

If you try the second approach be aware that you’re going to run into the FnBox issue.


#3
  • bump *

#4

My understanding is that callback based approach is more flexible, but less peformant (you need to allocate closures on the heap) and can lead to more convoluted code. Enum based events should be faster, simpler and more rigid, but I am by no means an expert in this area.

For enum approach, you can look at the mio library. For callbacks, there is GJ