fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdarg.h>
  5. #include <ucontext.h>
  6.  
  7. enum { STATE_ONE, STATE_TWO, STATE_DONE };
  8.  
  9. struct execution_state {
  10. int state_;
  11. ucontext_t main_ctx_;
  12. ucontext_t alt_ctx_;
  13. char alt_stack_[32*1024];
  14. } es;
  15.  
  16. void deferred_print (const char *fmt, ...) {
  17. va_list ap;
  18. while (es.state_ == STATE_ONE) {
  19. es.state_ = STATE_TWO;
  20. swapcontext(&es.main_ctx_, &es.alt_ctx_);
  21. }
  22. va_start(ap, fmt);
  23. vprintf(fmt, ap);
  24. va_end(ap);
  25. }
  26.  
  27. void state_one () {
  28. puts(__func__);
  29. deferred_print("this is a deferred print from %s\n", __func__);
  30. es.state_ = STATE_DONE;
  31. }
  32.  
  33. void state_two () {
  34. puts(__func__);
  35. if (rand() > RAND_MAX/4) es.state_ = STATE_ONE;
  36. setcontext(&es.main_ctx_);
  37. }
  38.  
  39. void state_machine () {
  40. while (es.state_ != STATE_DONE) {
  41. (void (*[])()){ state_one, state_two }[es.state_]();
  42. }
  43. }
  44.  
  45. void es_init () {
  46. es.state_ = STATE_ONE;
  47. getcontext(&es.alt_ctx_);
  48. es.alt_ctx_.uc_stack.ss_sp = es.alt_stack_;
  49. es.alt_ctx_.uc_stack.ss_size = sizeof(es.alt_stack_);
  50. es.alt_ctx_.uc_link = &es.main_ctx_;
  51. makecontext(&es.alt_ctx_, state_machine, 0);
  52. srand((unsigned)time(0));
  53. }
  54.  
  55. int main () {
  56. es_init();
  57. puts("start");
  58. state_machine();
  59. puts("finish");
  60. return 0;
  61. }
  62.  
Success #stdin #stdout 0s 2324KB
stdin
Standard input is empty
stdout
start
state_one
state_two
state_two
state_two
this is a deferred print from state_one
finish