home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / dnet / dshterm1_0.lha / lib / st / async.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-04  |  8.6 KB  |  266 lines

  1. /* Asynchronous file input/output routines (c) Stone, The SST
  2.    Public domain. email: c9107253@cs.newcastle.edu.au
  3.  
  4.    See example programs for usage
  5. */
  6.  
  7. #include <exec/types.h>
  8. #include <exec/memory.h>
  9. #include <exec/ports.h>
  10. #include <dos/dos.h>
  11. #include <dos/dosextens.h>
  12. #include <proto/exec.h>
  13. #include <proto/dos.h>
  14. #include <st/st_proto.h>
  15.  
  16. /*
  17. NOTE:   Becareful  on implicit GetMsg's & Waits when calling ARead, AWrite,
  18. AStatus  or  AResultWait.   Always keep all GetMsg's in a single loop!  (so
  19. resort to AStatusQuick and AGetReply)
  20. */
  21.  
  22.  
  23. /*********************************************************/
  24. long            ASigBit(struct AFileHandle *afh)
  25. /*********************************************************
  26.  Call this to find the bit to wait on when waiting for
  27.            replies from the associated file
  28.    Note that several files may share the same reply port
  29. so all files sharing the port must be checked with AStatus
  30.  *********************************************************/
  31. { return(ASIGBIT(afh)); }
  32.  
  33.  
  34. /*********************************************************/
  35. long            AResult(struct AFileHandle *afh)
  36. /*********************************************************/
  37. { return(ARESULT1(afh)); }
  38.  
  39.  
  40. /*********************************************************/
  41. long            AStatusQuick(struct AFileHandle *afh)
  42. /*********************************************************/
  43. { return(afh->Status); }
  44.  
  45.  
  46. /*********************************************************/
  47. struct AFileHandle        *AGetReply(struct APort *aport)
  48. /*********************************************************
  49.        Attempt GetMsg a single message from the port
  50.  *********************************************************/
  51. {    struct AFileHandle *afh;
  52.     if(afh = (struct AFileHandle *)GetMsg(aport->Port))
  53.                                 afh->Status = ASTATUS_IDLE;
  54.     return(afh);
  55. }
  56.  
  57.  
  58. /*********************************************************/
  59. long                    AStatus(struct AFileHandle *afh)
  60. /*********************************************************
  61.               Return the status if not busy
  62. If busy remove messages until no more or we found our reply
  63.    WARNING: this possibly removes all pending messages
  64.         so be VERY careful with this and a 'Wait'
  65.        (best to use this with only a single file)
  66.  *********************************************************/
  67. {
  68. struct    AFileHandle *afh_reply;
  69.     if(afh->Status != ASTATUS_BUSY) return(afh->Status);
  70.     while(afh_reply = AGetReply(afh->APort)) if(afh_reply == afh) break;
  71.     return(afh->Status);
  72. }
  73.  
  74.  
  75. /*********************************************************/
  76. long                AResultWait(struct AFileHandle *afh)
  77. /*********************************************************
  78.         Wait until status is NOT ASTATUS_BUSY
  79.    Be careful with this routine also (see AStatus)
  80.  *********************************************************/
  81. {
  82.     while(AStatus(afh) == ASTATUS_BUSY) Wait(1<<ASIGBIT(afh));
  83.     return(ARESULT1(afh));
  84. }
  85.  
  86.  
  87. /*********************************************************/
  88. void            AClose(struct AFileHandle *afh)
  89. /*********************************************************
  90.                        Close a file
  91. Note: IF A PACKET IS PENDING THIS WILL WAIT AND ALL MSG'S
  92.           UP TO THIS PACKET WILL BE AGetReply'd
  93.      (so AStatus all other files if this is the case)
  94.  *********************************************************/
  95. {
  96.     if(!afh) return;
  97.  
  98. /** WAIT FOR THE PENDING PACKET IF NEED BE */
  99.     AResultWait(afh);
  100.  
  101. /** UNLINK US FROM THE PORT LIST OF OPEN FILES */
  102.     if(afh->Prev)
  103.         afh->Prev->Next = afh->Next;
  104.     else afh->APort->First = afh->Next;
  105.     if(afh->Next)
  106.         afh->Next->Prev = afh->Prev;
  107.  
  108. /** CLOSE THE FILE & FREE THE MEMORY */
  109.     if(afh->FileHandle && (afh->Flags&AFLAG_CLOSEONCLOSE))
  110.                             Close(((long)afh->FileHandle)>>2);
  111.     FreeMem(afh,sizeof(struct AFileHandle));
  112. }
  113.  
  114.  
  115. /*********************************************************/
  116. void            ASafeClose(struct AFileHandle **afh)
  117. /*********************************************************/
  118. { if(*afh) { AClose(*afh); *afh = 0; } }
  119.  
  120.  
  121. /*********************************************************/
  122. struct AFileHandle
  123.         *AMakeFD2AFD(struct APort *aport, long fd)
  124. /*********************************************************
  125.      Build an AFileDescriptor from the fd passed in
  126.              Default to no auto file close
  127.                (so Input() can be copied)
  128.  *********************************************************/
  129. {
  130. struct AFileHandle *afh;
  131.     if(!aport || !fd ||
  132.         !(afh = AllocMem(sizeof(struct AFileHandle),MEMF_PUBLIC | MEMF_CLEAR)))
  133.             return(0);
  134.     afh->FileHandle    = (struct FileHandle *)(fd<<2);
  135.     afh->Prev        = 0;
  136.     if(afh->Next    = aport->First) afh->Next->Prev = afh;
  137.     afh->APort        = aport;
  138.     afh->Status        = ASTATUS_FIRSTTIME;
  139.     afh->Flags        = AFLAG_NOCLOSE;
  140.     aport->First    = afh;
  141.     return(afh);
  142. }
  143.  
  144. /*********************************************************/
  145. struct AFileHandle
  146.         *AOpen(struct APort *aport,    char *name, long mode)
  147. /*********************************************************
  148.   Attempt to open a file with 'mode' and link into the
  149.           list of open files on the port APort
  150.    return NULL if file could not be opened or no memory
  151. **********************************************************/
  152. {
  153. long fd;
  154. struct AFileHandle *afh;
  155.     if(!(fd = Open(name, mode) )) return(0);
  156.     if(!(afh = AMakeFD2AFD(aport, fd))) {
  157.         Close(fd); return(0);
  158.     }
  159. /* CLOSE ACTUAL FILE ON A DELETE PORT OR EXPLICIT CLOSE */
  160.     afh->Flags = AFLAG_CLOSEONCLOSE;
  161.     return(afh);
  162. }
  163.  
  164.  
  165.  
  166.  
  167.  
  168. /*********************************************************/
  169. void             ADeletePort(struct APort *aport)
  170. /*********************************************************
  171.          Close & Free all opened files on this port
  172.                  Delete the port
  173. **********************************************************/
  174. {
  175.     if(!aport) return;
  176.     while(aport->First) AClose(aport->First);
  177.     DeletePort(aport->Port);
  178.     FreeMem(aport, sizeof(struct APort));
  179. }
  180.  
  181.  
  182. /*********************************************************/
  183. struct APort    *ACreatePort(void)
  184. /*********************************************************
  185.         Create a reply port for the dos packets
  186. **********************************************************/
  187. {
  188. struct APort *aport;
  189.     if(!(aport = (struct APort *)
  190.             AllocMem(sizeof(struct APort), MEMF_PUBLIC | MEMF_CLEAR)))
  191.                 return(0);
  192.     spf(aport->PortName, APORTNAMESIZE, "AIOReply.%08lx", aport);
  193.     if(!(aport->Port = CreatePort(aport->PortName, 0)))
  194.         { FreeMem(aport, sizeof(struct APort)); return(0); }
  195.     aport->First = 0;
  196.     return(aport);
  197. }
  198.  
  199.  
  200.  
  201. /*********************************************************/
  202. short    ASendPacket(struct AFileHandle *afh, long action,
  203.             long arg1, long arg2, long arg3, long arg4)
  204. /*********************************************************
  205.        Try and send a packet using the given handle
  206.       return 1 on ok, 0 if packet is already in use
  207.  *********************************************************/
  208. {
  209. struct StandardPacket *sp = &(afh->Pkt);
  210. struct MsgPort *port = afh->FileHandle->fh_Type;
  211.     if(afh->Status == ASTATUS_BUSY) return(0);
  212.     afh->Status = ASTATUS_BUSY;
  213.  
  214. /** ADDRESS NEGATIVE IF PLAIN FILE?? (I don't believe...) */
  215.     sp->sp_Msg.mn_Node.ln_Name =(char *)&(sp->sp_Pkt);
  216.     sp->sp_Pkt.dp_Link = &(sp->sp_Msg);
  217.     sp->sp_Pkt.dp_Port = afh->APort->Port;
  218.     sp->sp_Pkt.dp_Type = action;
  219.     sp->sp_Pkt.dp_Arg1 = arg1;
  220.     sp->sp_Pkt.dp_Arg2 = arg2; /* DESTINATION */
  221.     sp->sp_Pkt.dp_Arg3 = arg3; /* BUFSIZE */
  222.     sp->sp_Pkt.dp_Arg4 = arg4; /* ANOTHER THING */
  223.  
  224.     PutMsg(port, &(sp->sp_Msg));
  225.     return(1);
  226. }
  227.  
  228.  
  229.  
  230.  
  231. /*********************************************************/
  232. long    ARead(struct AFileHandle *afh, void *buf, long n)
  233. /*********************************************************
  234.                  Send a packet to read
  235.     This returns the results of the PREVIOUS packet
  236.                    of THIS filehandle
  237.    NOTE that the new packet is sent ONLY if the previous
  238.                  packet result is OK
  239. **********************************************************/
  240. {
  241. long prev_res;
  242.     if(AStatus(afh) == ASTATUS_FIRSTTIME) prev_res = -1;
  243.     else prev_res = AResultWait(afh);
  244.     if(prev_res) ASendPacket(afh, ACTION_READ,
  245.                             afh->FileHandle->fh_Args, (long)buf, n, 0);
  246.     return(prev_res);
  247. }
  248.  
  249. /*********************************************************/
  250. long    AWrite(struct AFileHandle *afh, void *buf, long n)
  251. /*********************************************************
  252.                  Send a packet to write
  253.     This returns the results of the PREVIOUS packet
  254.                 of THIS filehandle
  255.    NOTE that the new packet is sent ONLY if the previous
  256.                  packet result is OK
  257. **********************************************************/
  258. {
  259. long prev_res;
  260.     if(AStatus(afh) == ASTATUS_FIRSTTIME) prev_res = -1;
  261.     else prev_res = AResultWait(afh);
  262.     if(prev_res) ASendPacket(afh, ACTION_WRITE,
  263.                             afh->FileHandle->fh_Args, (long)buf, n, 0);
  264.     return(prev_res);
  265. }
  266.