I want to run one thread and send Box<FnOnce()> for execution.
Background thread will peek up one by one Box<FnOnce()> and execute them.
Sounds like std::sync::mpsc or crossbeam,
but I have no idea how to stop them gracefully.
If user want to quit my program I want background thread to process only current job and then exit.
So I need clear operation for channel to clear it and then send "quit" message.
Or I need some kind of priority for messages, so I just send "quit" message with the highest priority and background thread peek up it first.
The easiest thing in this case (I think) would be to have another channel—or perhaps an atomic somewhere—that tells the worker when to stop. Before checking the work queue, the worker must check the status channel/atomic to see if it should stop.
Although something like thread::park() could be better than this, provided the master thread unparks it when sending a task, thread::yield_now purpose is precisely this: to avoid busy-looping:
Shared Arc<AtomicBool> which is checked after a closure is received from the channel seems like the simplest solution here. Usual termination condition when channel is closed if there are no senders should be used to signal cancelation if the channel is empty.
An alternative solution is to add a second channel and a select!, but that seems more complex and doesn’t guarantee. The order you want. If you add a quite channel, don’t send a dummy () message, just drop a sender instead. Dropping a sender is a valid selectable way to transfer information, which is guaranteed to work even in presence of panics, and to work only once.