home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 171.lha / SupLib / asyncop.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  3KB  |  179 lines

  1.  
  2. /*
  3.  *  ASYNCOP.C
  4.  */
  5.  
  6. typedef unsigned char    ubyte;
  7. typedef unsigned short    uword;
  8. typedef unsigned long    ulong;
  9. typedef struct Message    MSG;
  10. typedef struct MsgPort    PORT;
  11. typedef struct Task    TASK;
  12. typedef struct Node    NODE;
  13.  
  14. #define ASYMSG    struct _ASYMSG
  15. #define ASYHAN    struct _ASYHAN
  16.  
  17. ASYMSG {
  18.     MSG msg;
  19.     void (*func)();
  20.     long arg1;
  21.     long arg2;
  22.     long arg3;
  23. };
  24.  
  25. ASYHAN {
  26.     PORT *rport;    /*    Reply Port    */
  27.     PORT *port;     /*    Send Port    */
  28.     long acount;    /*    Messages Sent    */
  29.     long ccount;    /*    Messages Replied*/
  30.     long a4,a5;     /*    A4 and A5    */
  31. };
  32.  
  33. extern TASK *CreateTask();
  34. extern TASK *FindTask();
  35. extern PORT *CreatePort();
  36. extern void *AllocMem();
  37. extern void *GetMsg();
  38.  
  39. extern void asyhandler();
  40. extern void nop();
  41.  
  42.  
  43. ASYHAN *
  44. NewAsyncOp()
  45. {
  46.     register TASK *task;
  47.     register TASK *mytask = FindTask(NULL);
  48.     register ASYHAN *as = AllocMem(sizeof(ASYHAN), MEMF_CLEAR|MEMF_PUBLIC);
  49.     ASYMSG StartupMsg;
  50.  
  51.     as->rport = CreatePort(NULL, 0);
  52.     PutA4A5(&as->a4);
  53.     task = CreateTask("async.task", mytask->tc_Node.ln_Pri + 1, asyhandler, 4096);
  54.     task->tc_UserData = (APTR)as;
  55.  
  56.     Signal(task, SIGBREAKF_CTRL_F);
  57.     Wait(1 << as->rport->mp_SigBit);
  58.  
  59.     return(as);
  60. }
  61.  
  62.  
  63. StartAsyncOp(as, func, arg1, arg2, arg3)
  64. register ASYHAN *as;
  65. void (*func)();
  66. {
  67.     register ASYMSG *am = GetMsg(as->rport);    /*  Free Msg List   */
  68.  
  69.     if (!am) {
  70.     am = AllocMem(sizeof(ASYMSG), MEMF_PUBLIC|MEMF_CLEAR);
  71.     am->msg.mn_ReplyPort = as->rport;
  72.     }
  73.     am->func = func;
  74.     am->arg1 = arg1;
  75.     am->arg2 = arg2;
  76.     am->arg3 = arg3;
  77.     ++as->acount;
  78.     PutMsg(as->port, am);
  79. }
  80.  
  81. CheckAsyncOp(as, n)
  82. register ASYHAN *as;
  83. unsigned long n;
  84. {
  85.     if (n > as->acount)
  86.     n = as->acount;
  87.     return(n <= as->ccount);
  88. }
  89.  
  90. /*
  91.  *  acount = #messages sent
  92.  *  ccount = #messages replied
  93.  */
  94.  
  95. WaitAsyncOp(as, n)
  96. register ASYHAN *as;
  97. unsigned long n;
  98. {
  99.     if (n > as->acount)
  100.     n = as->acount;
  101.     while (n > as->ccount)
  102.     Wait(1 << as->rport->mp_SigBit);
  103.     Forbid();
  104.     as->ccount -= n;
  105.     Permit();
  106.     as->acount -= n;
  107. }
  108.  
  109. CloseAsyncOp(as)
  110. register ASYHAN *as;
  111. {
  112.     ASYMSG EndMsg;
  113.     ASYMSG *am;
  114.  
  115.     WaitAsyncOp(as, -1);                /*  Wait for all operations to complete */
  116.     while (am = GetMsg(as->rport))      /*  Free any messages   */
  117.     FreeMem(am, sizeof(ASYMSG));
  118.     EndMsg.func = NULL;
  119.     EndMsg.msg.mn_ReplyPort = as->rport;
  120.     PutMsg(as->port, &EndMsg);
  121.     WaitPort(as->rport);
  122.     GetMsg(as->rport);
  123.     DeletePort(as->rport);
  124.     FreeMem(as, sizeof(*as));
  125. }
  126.  
  127. static
  128. void
  129. asyhandler()
  130. {
  131.     register ASYHAN *as;
  132.     register ASYMSG *am;
  133.  
  134.     Wait(SIGBREAKF_CTRL_F);
  135.     as = (ASYHAN *)FindTask(NULL)->tc_UserData;
  136.     as->port = CreatePort(NULL, 0);
  137.     Signal(as->rport->mp_SigTask, 1 << as->rport->mp_SigBit);
  138.     for (;;) {
  139.     WaitPort(as->port);
  140.     am = GetMsg(as->port);
  141.     if (!am->func)
  142.         break;
  143.     CallAMFunc(&as->a4, &am->func);
  144.     ++as->ccount;
  145.     ReplyMsg(am);
  146.     }
  147.     DeletePort(as->port);
  148.     as->port = NULL;
  149.     Forbid();
  150.     ReplyMsg(am);
  151. }
  152.  
  153. #asm
  154.         ;
  155.         ;    load the lw array ptr with a4 & a5
  156.  
  157. _PutA4A5:   move.l  4(sp),A0
  158.         move.l  A4,(A0)+
  159.         move.l  A5,(A0)+
  160.         rts
  161.  
  162. _CallAMFunc:
  163.         move.l  4(sp),A0    ; &a4,a5
  164.         move.l  8(sp),A1    ; &func,arg1,arg2,arg3
  165.         movem.l D2/D3/A4/A5/A6,-(sp)
  166.         move.l  (A0)+,A4
  167.         move.l  (A0)+,A5
  168.         move.l  12(A1),-(sp)
  169.         move.l  8(A1),-(sp)
  170.         move.l  4(A1),-(sp)
  171.         move.l  (A1),A1
  172.         jsr     (A1)
  173.         add.w   #12,sp
  174.         movem.l (sp)+,D2/D3/A4/A5/A6
  175.         rts
  176.  
  177. #endasm
  178.  
  179.