Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!tut.cis.ohio-state.edu!ucbvax!HERMES.BERKELEY.EDU!dillon From: dillon@HERMES.BERKELEY.EDU (Matt Dillon) Newsgroups: comp.sys.amiga.tech Subject: Re: I wanna have a DOSGate! Message-ID: <8906122312.AA02273@hermes.Berkeley.EDU> Date: 12 Jun 89 23:12:30 GMT Sender: daemon@ucbvax.BERKELEY.EDU Lines: 318 :So use asynchronous I/O, and Wait() on both the pipe-handler and your :events (I assume menupicks and timers and such?). See the latest :AmyTransactor for John Toebes/et. al.'s excellent article on the :subject. Also, Matt Dillon has a library somewhere for doing async :I/O, to go with his libraries to do just about everything else under :the sun :-). : :Someone else suggested multitasking it off as a seperate task, but :that won't work here. If the person doesn't type anything in the past, :say, 5 minutes, the BBS has to assume he's gone to lunch, i.e. we have :to be waiting on a timer as well as on file and modem i/o. Might as :well just do it in the BBS instead of spawning it off. Yes, it is in my suplib link library. The code is pretty old and not all that pretty, but here it is (below) Note that various system #include's are missing (I use a precompiled include file for all the system stuff). There are references to other routines in suplib but what they do ought to be obvious. I also just noticed (not having looked at the routines for a year or two) that it doesn't error check the buffer allocations.. oops. -Matt /* * XFIO.C * * Simple File IO with asyncronous READ and WRITE capability * Perfect for protocol transfer applications * * xfi = xfopen(name, modes, bufsize) ("r", "w", "w+") * n = xfread(xfi, buf, bytes) ASYNCRONOUS READ * err = xfwrite(xfi, buf, bytes) ASYNCRONOUS WRITE * err = xfclose(xfi) * * RESTRICTIONS: NO seeking. You can do one of xfread() or xfwrite() * for a given open XFIle handle (not both). * * xfwrite() returns a cumulative error (once an error occurs, it will not * do any more writes). xfclose() returns the cumulative write error * (since the last write may have been asyncronous and thus the error * unknown at the time). * * Two buffers are created each bufsize/2 bytes in size. for writing, * one buffers is sent asyncronously while the other fills. For reading, * one buffer is filling while the other is being read. */ #define XFI struct _XFI #define XFBUF struct _XFBUF #define MSGPORT struct MsgPort #define FH struct FileHandle #define STDPKT struct StandardPacket XFBUF { long bufsize; long idx; long max; char buf[4]; /* actually bufsize bytes long */ }; XFI { char ro; /* read only, else write only */ char pend; /* packet pending */ char err; /* cumulative error */ char reserved; XFBUF *asbuf; XFBUF *usbuf; FH *fh; STDPKT sp; /* asyncronous message */ MSGPORT rp; /* reply port for pending pkts */ }; extern FH *Open(); extern void *malloc(), *FindTask(); /*BREAKUP xfopen.c */ void * xfopen(file, mode, bytes) char *file; char *mode; { register XFI *xfi = malloc(sizeof(XFI)); register long nbytes = bytes >> 1; int ap = 0; BZero(xfi, sizeof(XFI)); if (mode[0] == 'w') { if (mode[1] == '+') { ap = 1; if ((xfi->fh = Open(file, 1005)) == NULL) xfi->fh = Open(file, 1006); goto ok; } xfi->fh = Open(file, 1006); goto ok; } xfi->fh = Open(file, 1005); ok: if (xfi->fh) { if (ap) Seek(xfi->fh, 0, 1); xfi->fh = (FH *)((long)xfi->fh << 2); /* BTOC() */ xfi->asbuf = malloc(sizeof(XFBUF) + nbytes); /* a little more */ xfi->usbuf = malloc(sizeof(XFBUF) + nbytes); /* then we need */ BZero(xfi->asbuf, sizeof(XFBUF)); BZero(xfi->usbuf, sizeof(XFBUF)); xfi->ro = (mode[0] == 'r'); xfi->asbuf->bufsize = xfi->usbuf->bufsize = nbytes; xfi->rp.mp_Node.ln_Type = NT_MSGPORT; xfi->rp.mp_Node.ln_Name = "XFIO-Async"; xfi->rp.mp_Flags = PA_SIGNAL; xfi->rp.mp_SigBit = AllocSignal(-1); xfi->rp.mp_SigTask = FindTask(NULL); NewList(&xfi->rp.mp_MsgList); if (xfi->ro) __xfstartasync(xfi, ACTION_READ); } else { free(xfi); xfi = NULL; } return(xfi); } /*BREAKUP xfclose.c */ xfclose(xfi) register XFI *xfi; { int err = 1; if (xfi) { if (xfi->pend) { xfi->pend = 0; WaitPort (&xfi->rp); GetMsg (&xfi->rp); } if (!xfi->ro && xfi->usbuf->idx) Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx); err = xfi->err; Close((long)xfi->fh >> 2); free(xfi->asbuf); free(xfi->usbuf); FreeSignal(xfi->rp.mp_SigBit); free(xfi); } return(err); } /*BREAKUP xfseek.c */ xfseek(xfi, pos) /* may not work */ XFI *xfi; long pos; { if (xfi) { if (xfi->pend) { WaitPort (&xfi->rp); GetMsg (&xfi->rp); xfi->pend = 0; if (!xfi->ro) { if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) { xfi->err = 1; return(1); } } } if (!xfi->ro && xfi->usbuf->idx) { Write((long)xfi->fh >> 2, xfi->usbuf->buf, xfi->usbuf->idx); xfi->usbuf->idx = 0; } Seek((long)xfi->fh >> 2, pos, -1); if (xfi->ro) { XFBUF *asbuf = xfi->asbuf; xfi->asbuf = xfi->usbuf; xfi->usbuf = asbuf; xfi->usbuf->idx = xfi->usbuf->max = 0; __xfstartasync(xfi, ACTION_READ); } } } /*BREAKUP xfgets.c */ xfgets(xfi, buf, n) XFI *xfi; char *buf; { register XFBUF *usbuf = xfi->usbuf; register int i, idx; if (!xfi->ro) return(-1); --n; for (i = 0;;) { for (idx = usbuf->idx; idx < usbuf->max && i < n; ++idx, ++i) { if ((buf[i] = usbuf->buf[idx]) == '\n') { buf[i] = 0; usbuf->idx = idx+1; return(i); } } usbuf->idx = idx; buf[i] = 0; if (i == n) return(i); if (xfi->pend == 0) /* EOF */ return(-1); WaitPort (&xfi->rp); GetMsg (&xfi->rp); xfi->pend = 0; if (xfi->sp.sp_Pkt.dp_Res1 <= 0) { /* EOF */ if (i == 0) return(-1); return(i); } xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1; xfi->asbuf->idx = 0; usbuf = xfi->asbuf; /* swap bufs*/ xfi->asbuf = xfi->usbuf; xfi->usbuf = usbuf; __xfstartasync(xfi, ACTION_READ); /* new async*/ } } /*BREAKUP xfread.c */ xfread(xfi, buf, n) XFI *xfi; char *buf; { register XFBUF *usbuf = xfi->usbuf; register int orig = n; register int diff; if (!xfi->ro) return(0); while ((diff = usbuf->max - usbuf->idx) < n) { movmem(usbuf->buf + usbuf->idx, buf, diff); /* copy entire buf */ buf += diff; n -= diff; if (xfi->pend == 0) { xfi->usbuf->idx = xfi->usbuf->max; return(orig - n); } WaitPort (&xfi->rp); GetMsg (&xfi->rp); xfi->pend = 0; if (xfi->sp.sp_Pkt.dp_Res1 <= 0) { /* EOF */ xfi->usbuf->idx = xfi->usbuf->max; return(orig - n); } xfi->asbuf->max = xfi->sp.sp_Pkt.dp_Res1; xfi->asbuf->idx = 0; usbuf = xfi->asbuf; /* swap bufs*/ xfi->asbuf = xfi->usbuf; xfi->usbuf = usbuf; __xfstartasync(xfi, ACTION_READ); /* new async*/ } movmem(usbuf->buf + usbuf->idx, buf, n); usbuf->idx += n; return(orig); } /*BREAKUP xfwrite.c */ xfwrite(xfi, buf, n) XFI *xfi; char *buf; { register XFBUF *usbuf = xfi->usbuf; register int diff; if (xfi->ro || xfi->err) return(1); while ((diff = usbuf->bufsize - usbuf->idx) < n) { movmem(buf, usbuf->buf + usbuf->idx, diff); /* copy buf */ buf += diff; n -= diff; if (xfi->pend) { WaitPort(&xfi->rp); GetMsg (&xfi->rp); xfi->pend = 0; if (xfi->sp.sp_Pkt.dp_Res1 != xfi->sp.sp_Pkt.dp_Arg3) { xfi->err = 1; return(1); } } usbuf = xfi->asbuf; xfi->asbuf = xfi->usbuf; xfi->usbuf = usbuf; usbuf->idx = 0; __xfstartasync(xfi, ACTION_WRITE); } movmem(buf, usbuf->buf + usbuf->idx, n); usbuf->idx += n; return(xfi->err); } /*BREAKUP xfstartasync.c */ __xfstartasync(xfi, action) register XFI *xfi; { xfi->sp.sp_Msg.mn_Node.ln_Name = (char *)&(xfi->sp.sp_Pkt); xfi->sp.sp_Pkt.dp_Link = &(xfi->sp.sp_Msg); xfi->sp.sp_Pkt.dp_Port = &xfi->rp; xfi->sp.sp_Pkt.dp_Type = action; xfi->sp.sp_Pkt.dp_Arg1 = xfi->fh->fh_Arg1; xfi->sp.sp_Pkt.dp_Arg2 = (long)xfi->asbuf->buf; xfi->sp.sp_Pkt.dp_Arg3 = xfi->asbuf->bufsize; PutMsg (xfi->fh->fh_Type, &xfi->sp); xfi->pend = 1; }