I've been thinking about a way to write code that is both dependency free and blocking free for several use cases. (A serial protocol for example)
I've seen solutions where the dependencies are injected into the library code, and the library calls the dependency that way, but if the library is expecting polling, or blocking behavior, that isn't good. E.g. If a uart driver needs a delay(ms)
function, that's bad; I don't want the uart driver to block.
Instead, I imagine the library code to return instructions back to the app code, describing what the app should do. (redux-saga for react does something like this, where they return 'effects' - I like that)
So instead of the library code blocking with the delay function - return an 'effect' (stealing redux-saga terms) describing how long to wait. TASK_WAIT_10MS
or something like that. It doesn't have to be the returned value, but the idea is that the library code communicates what it needs from the user.
Pseudo code.
enum states {
STATE_ONE,
STATE_TWO,
STATE_DONE
}
enum effects {
TASK_ONE,
TASK_TWO,
TASK_THREE
}
struct state {
...
}
enum states get_state(...);
enum effects code_state_one(...);
enum effects code_state_two(...);
void main() {
struct state my_data;
enum effects my_tasks;
while (get_state(my_data) != STATE_DONE)
{
switch (get_state(my_data))
{
case STATE_ONE:
my_tasks = code_state_one(...);
break;
case STATE_TWO:
my_tasks = code_state_two(...);
break;
}
switch (my_tasks)
{
case TASK_ONE:
// Perform SYSTEM DEPENDENT task and pass result back to code_state_x
break;
case TASK_TWO:
// Perform SYSTEM DEPENDENT task and pass result back to code_state_x
break;
case TASK_THREE:
// Perform SYSTEM DEPENDENT task and pass result back to code_state_x
break;
}
}
}