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