IME, callbacks of any kind are to be avoided if at all possible. Absolutelyeverything is simpler in a more functional, call-and-return style. This why
coroutines in Lua can be so powerful; often they're used to invert
contination callbacks so you can use an easier consumer design pattern in
Lua code. But if possible it's best to avoid all the trouble entirely at the
C or C++ layer.
This is also why message passing designs are preferred by myself and others.
The OS primitives are built so that each actors executes a pull its consumer
role, and a push in its producer role, with the OS intermediating.