home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * ASYNCOP.C
- */
-
- typedef unsigned char ubyte;
- typedef unsigned short uword;
- typedef unsigned long ulong;
- typedef struct Message MSG;
- typedef struct MsgPort PORT;
- typedef struct Task TASK;
- typedef struct Node NODE;
-
- #define ASYMSG struct _ASYMSG
- #define ASYHAN struct _ASYHAN
-
- ASYMSG {
- MSG msg;
- void (*func)();
- long arg1;
- long arg2;
- long arg3;
- };
-
- ASYHAN {
- PORT *rport; /* Reply Port */
- PORT *port; /* Send Port */
- long acount; /* Messages Sent */
- long ccount; /* Messages Replied*/
- long a4,a5; /* A4 and A5 */
- };
-
- extern TASK *CreateTask();
- extern TASK *FindTask();
- extern PORT *CreatePort();
- extern void *AllocMem();
- extern void *GetMsg();
-
- extern void asyhandler();
- extern void nop();
-
-
- ASYHAN *
- NewAsyncOp()
- {
- register TASK *task;
- register TASK *mytask = FindTask(NULL);
- register ASYHAN *as = AllocMem(sizeof(ASYHAN), MEMF_CLEAR|MEMF_PUBLIC);
- ASYMSG StartupMsg;
-
- as->rport = CreatePort(NULL, 0);
- PutA4A5(&as->a4);
- task = CreateTask("async.task", mytask->tc_Node.ln_Pri + 1, asyhandler, 4096);
- task->tc_UserData = (APTR)as;
-
- Signal(task, SIGBREAKF_CTRL_F);
- Wait(1 << as->rport->mp_SigBit);
-
- return(as);
- }
-
-
- StartAsyncOp(as, func, arg1, arg2, arg3)
- register ASYHAN *as;
- void (*func)();
- {
- register ASYMSG *am = GetMsg(as->rport); /* Free Msg List */
-
- if (!am) {
- am = AllocMem(sizeof(ASYMSG), MEMF_PUBLIC|MEMF_CLEAR);
- am->msg.mn_ReplyPort = as->rport;
- }
- am->func = func;
- am->arg1 = arg1;
- am->arg2 = arg2;
- am->arg3 = arg3;
- ++as->acount;
- PutMsg(as->port, am);
- }
-
- CheckAsyncOp(as, n)
- register ASYHAN *as;
- unsigned long n;
- {
- if (n > as->acount)
- n = as->acount;
- return(n <= as->ccount);
- }
-
- /*
- * acount = #messages sent
- * ccount = #messages replied
- */
-
- WaitAsyncOp(as, n)
- register ASYHAN *as;
- unsigned long n;
- {
- if (n > as->acount)
- n = as->acount;
- while (n > as->ccount)
- Wait(1 << as->rport->mp_SigBit);
- Forbid();
- as->ccount -= n;
- Permit();
- as->acount -= n;
- }
-
- CloseAsyncOp(as)
- register ASYHAN *as;
- {
- ASYMSG EndMsg;
- ASYMSG *am;
-
- WaitAsyncOp(as, -1); /* Wait for all operations to complete */
- while (am = GetMsg(as->rport)) /* Free any messages */
- FreeMem(am, sizeof(ASYMSG));
- EndMsg.func = NULL;
- EndMsg.msg.mn_ReplyPort = as->rport;
- PutMsg(as->port, &EndMsg);
- WaitPort(as->rport);
- GetMsg(as->rport);
- DeletePort(as->rport);
- FreeMem(as, sizeof(*as));
- }
-
- static
- void
- asyhandler()
- {
- register ASYHAN *as;
- register ASYMSG *am;
-
- Wait(SIGBREAKF_CTRL_F);
- as = (ASYHAN *)FindTask(NULL)->tc_UserData;
- as->port = CreatePort(NULL, 0);
- Signal(as->rport->mp_SigTask, 1 << as->rport->mp_SigBit);
- for (;;) {
- WaitPort(as->port);
- am = GetMsg(as->port);
- if (!am->func)
- break;
- CallAMFunc(&as->a4, &am->func);
- ++as->ccount;
- ReplyMsg(am);
- }
- DeletePort(as->port);
- as->port = NULL;
- Forbid();
- ReplyMsg(am);
- }
-
- #asm
- ;
- ; load the lw array ptr with a4 & a5
-
- _PutA4A5: move.l 4(sp),A0
- move.l A4,(A0)+
- move.l A5,(A0)+
- rts
-
- _CallAMFunc:
- move.l 4(sp),A0 ; &a4,a5
- move.l 8(sp),A1 ; &func,arg1,arg2,arg3
- movem.l D2/D3/A4/A5/A6,-(sp)
- move.l (A0)+,A4
- move.l (A0)+,A5
- move.l 12(A1),-(sp)
- move.l 8(A1),-(sp)
- move.l 4(A1),-(sp)
- move.l (A1),A1
- jsr (A1)
- add.w #12,sp
- movem.l (sp)+,D2/D3/A4/A5/A6
- rts
-
- #endasm
-
-