3 ms·
[edit: deleted first half of my comment - it was just duplication of existing top comment] ----- Even better, when possible (it isn't always), is to avoid usi
by quietbritishjim 4y ago
[edit: deleted first half of my comment - it was just duplication of existing top comment]
-----
Even better, when possible (it isn't always), is to avoid using mutexes at all, and instead have the data structure owned by a relevant thread. When you need to access a data structure, pass a message to that thread, and then just access the data structure freely when you get there. (Of course the inter thread queue uses a mutex or some other synchronisation mechanism, and the queue itself effectively acts as a synchronisation mechanism.)
struct SomeMsg {
SomeMsg() {
thread_foo->pass_message(std::bind_front(this, &SomeMsg::handle_foo));
}
void handle_foo(Foo& foo) {
// ... use foo ...
thread_bar->pass_message(std::bind_front(this, &SomeMsg::handle_bar));
}
void handle_bar(Bar& bar) {
// ... etc. ...
}
};
- smallstepforman 4y agoYou’ve just described Actors. Now take the next step and add a work stealing schedular for a fuller Actor system.
- MontagFTB 4y agoI’ve been toying with these lately, too. My solution was to give each actor an executor where it will run: actor<int> foo(stlab::default_executor, “name”, 42); auto f = foo.send([](auto& x){ std::cout << x << ‘\n’; // prints 42 }); Each call to ‘send’ returns a stlab::future which can have a continuation chained, etc. The nice thing about these is the executor based interface is generic. The actor could be dedicated to a thread, run on an OS-provided thread pool, etc. At the time the actor is running, the thread it is on is temporarily given the name of the actor to ease debugging.
- quietbritishjim 4y agoAlmost. If each thread were an Actor (I think that's what you're saying?) then that would structure the code around each type of work e.g. here is the code for all the database operations. That's not a very useful way to group things for the developer. The way I wrote it above, the code is structured around a single activity across all the types of work it has to do.
- kps 4y agoChrome does this, more or less, with different syntax. https://chromium.googlesource.com/chromium/src/+/main/docs/threading_and_tasks.md https://chromium.googlesource.com/chromium/src/+/main/docs/t...
- loeg 4y ago> (Of course the inter thread queue uses a mutex or some other synchronisation mechanism, and the queue itself effectively acts as a synchronisation mechanism.) I'd suggest using MPSC queues for this purpose (assuming the recipient is a single thread rather than a pool).