fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. struct Fn {
  5. void * parameters;
  6. void (*function)(void *);
  7. struct Fn * next;
  8. };
  9.  
  10. #define SPLICE_2(l,r) l##r
  11. #define SPLICE_1(l,r) SPLICE_2(l,r)
  12. #define SPLICE(l,r) SPLICE_1(l,r)
  13.  
  14. #define PARAM_0(...)
  15. #define PARAM_1(type, ...) type p1; PARAM_0(__VA_ARGS__)
  16. #define PARAM_2(type, ...) type p2; PARAM_1(__VA_ARGS__)
  17. #define PARAM_3(type, ...) type p3; PARAM_2(__VA_ARGS__)
  18. #define PARAM_4(type, ...) type p4; PARAM_3(__VA_ARGS__)
  19. #define PARAMS(N, ...) SPLICE(PARAM_, N)(__VA_ARGS__)
  20.  
  21. #define CPARAM_0
  22. #define CPARAM_1 parameters->p1
  23. #define CPARAM_2 parameters->p2, CPARAM_1
  24. #define CPARAM_3 parameters->p3, CPARAM_2
  25. #define CPARAM_4 parameters->p4, CPARAM_3
  26. #define CPARAMS(N) SPLICE(CPARAM_, N)
  27.  
  28. #define SPARAM_0(...)
  29. #define SPARAM_1(value, ...) parameters->p1 = (value); SPARAM_0(__VA_ARGS__)
  30. #define SPARAM_2(value, ...) parameters->p2 = (value); SPARAM_1(__VA_ARGS__)
  31. #define SPARAM_3(value, ...) parameters->p3 = (value); SPARAM_2(__VA_ARGS__)
  32. #define SPARAM_4(value, ...) parameters->p4 = (value); SPARAM_3(__VA_ARGS__)
  33. #define SPARAMS(N, ...) SPLICE(SPARAM_, N)(__VA_ARGS__)
  34.  
  35. #define MAKE_DEFERRABLE(name, N, ...) \
  36.   struct deferred_ ## name ## _parameters { PARAMS(N, __VA_ARGS__) }; \
  37.   void deferred_ ## name (void * p) { \
  38.   struct deferred_ ## name ## _parameters * parameters = p; \
  39.   printf(" -- Calling deferred " #name "\n"); \
  40.   (void)name(CPARAMS(N)); \
  41.   }
  42.  
  43. struct Fn * deferred_fns = NULL;
  44.  
  45. #define DEFER(name, N, ...) \
  46.   do { \
  47.   printf(" -- Deferring a call to " #name "\n"); \
  48.   if (deferred_fns == NULL) { \
  49.   deferred_fns = malloc(sizeof(*deferred_fns)); \
  50.   deferred_fns->next = NULL; \
  51.   } else { \
  52.   struct Fn * f = malloc(sizeof(*f)); \
  53.   f->next = deferred_fns; \
  54.   deferred_fns = f; \
  55.   } \
  56.   deferred_fns->function = &(deferred_ ## name); \
  57.   struct deferred_ ## name ##_parameters * parameters = malloc(sizeof(*parameters)); \
  58.   SPARAMS(N,__VA_ARGS__); \
  59.   deferred_fns->parameters = parameters; \
  60.   } while(0)
  61.  
  62.  
  63. void run_deferred_fns(void) {
  64. while (deferred_fns != NULL) {
  65. deferred_fns->function(deferred_fns->parameters);
  66. free(deferred_fns->parameters);
  67. struct Fn * bye = deferred_fns;
  68. deferred_fns = deferred_fns->next;
  69. free(bye);
  70. }
  71. }
  72.  
  73.  
  74. void foo(int x) {
  75. printf("foo: %d\n", x);
  76. }
  77.  
  78. void bar(void) {
  79. puts("bar");
  80. }
  81.  
  82. void baz(int x, double y) {
  83. printf("baz: %d %f\n", x, y);
  84. }
  85.  
  86. MAKE_DEFERRABLE(foo, 1, int);
  87. MAKE_DEFERRABLE(bar, 0);
  88. MAKE_DEFERRABLE(baz, 2, int, double);
  89.  
  90. int main(void) {
  91. DEFER(foo, 1, 42);
  92. DEFER(bar, 0);
  93. DEFER(foo, 1, 21);
  94. DEFER(baz, 2, 42, 3.14);
  95. run_deferred_fns();
  96. return 0;
  97. }
  98.  
Success #stdin #stdout 0s 2288KB
stdin
Standard input is empty
stdout
 -- Deferring a call to foo
 -- Deferring a call to bar
 -- Deferring a call to foo
 -- Deferring a call to baz
 -- Calling deferred baz
baz: 42 3.140000
 -- Calling deferred foo
foo: 21
 -- Calling deferred bar
bar
 -- Calling deferred foo
foo: 42