home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / program / code / andylib / c / CoRoutine next >
Encoding:
Text File  |  1994-05-19  |  2.4 KB  |  130 lines

  1. /* CoRoutine.c - High level routines for coroutines package
  2.  *
  3.  *  01-10-90 AA   Started
  4.  *
  5.  */
  6.  
  7. #include "tracker.h"
  8.  
  9. #include "CoRtn.h"
  10. #include <stdlib.h>
  11. #include <signal.h>
  12.  
  13. #define FALSE 0
  14. #define TRUE (!FALSE)
  15.  
  16. context *__launch_co(coproc p, context *from, void *handle);
  17. context *__switch_co(context *to, context *from);
  18. void __kill_co(context *co);
  19.  
  20. static coroutine *costack = NULL;       /* List of all coroutines     */
  21. static context mainprog;                /* Save slot for main program */
  22. static coroutine *currentco = MAIN_CO;
  23.  
  24. /* Malloc and free routines exported to assembler */
  25.  
  26. void *comalloc(size_t size)
  27. {  return malloc(size);
  28. }
  29.  
  30. void cofree(void *m)
  31. {  free(m);
  32. }
  33.  
  34. static context *getslot(coroutine *co)
  35. {  if (co == MAIN_CO)
  36.       return &mainprog;
  37.  
  38.    return &co->ctx;
  39. }
  40.  
  41. static coroutine *unhitch(coroutine *stack, coroutine *onetokill)
  42. {  if (!stack)
  43.       return NULL;
  44.  
  45.    if (stack == onetokill)
  46.    {  coroutine *next = stack->next;
  47.       cofree(onetokill);
  48.       return next;
  49.    }
  50.  
  51.    stack->next = unhitch(stack->next, onetokill);
  52.    return stack;
  53. }
  54.  
  55. coroutine *create_co(coproc p, void *handle)
  56. {  coroutine *new;
  57.  
  58.    if (new = comalloc(sizeof(coroutine)), !new)
  59.       return NULL;
  60.  
  61.    new->comain = p;
  62.    new->handle = handle;
  63.    new->active = 0;
  64.  
  65.    new->next = costack;
  66.    costack   = new;
  67.  
  68.    return new;
  69. }
  70.  
  71. int delete_co(coroutine *co)
  72. {  if (co == currentco || co == MAIN_CO)
  73.       return FALSE;
  74.  
  75.    if (co->active)
  76.       __kill_co(getslot(co));
  77.  
  78.    costack = unhitch(costack, co);
  79.    return TRUE;
  80. }
  81.  
  82. int monitor_co(coroutine *co)
  83. {  if (co == MAIN_CO)
  84.       return 1;
  85.    else
  86.       return co->active;
  87. }
  88.  
  89. int start_co(coroutine *co)
  90. {  if (co == currentco || co == MAIN_CO)
  91.       return FALSE;
  92.  
  93.    if (co->active)
  94.       __kill_co(getslot(co));
  95.  
  96.    co->active = 0;
  97.    return goto_co(co);
  98. }
  99.  
  100. int goto_co(coroutine *co)
  101. {  context *old, *new;
  102.    coroutine *oldcurrent;
  103.    int stillgoing;
  104.  
  105.    if (co == currentco)
  106.       return FALSE;
  107.  
  108.    old = getslot(currentco);
  109.    new = getslot(co);
  110.  
  111.    oldcurrent = currentco;
  112.    currentco = co;
  113.  
  114.    if (monitor_co(co))
  115.       stillgoing = (int) __switch_co(new, old);
  116.    else
  117.       stillgoing = (int) __launch_co(co->comain, old,
  118.                      co == MAIN_CO ? NULL : co->handle);
  119.  
  120.    currentco = oldcurrent;
  121.  
  122.    if (stillgoing == -1)
  123.       return FALSE;
  124.  
  125.    if (co != MAIN_CO)
  126.       co->active = !!stillgoing;
  127.  
  128.    return TRUE;
  129. }
  130.