[project @ 2000-03-10 15:23:40 by simonmar]
authorsimonmar <unknown>
Fri, 10 Mar 2000 15:23:40 +0000 (15:23 +0000)
committersimonmar <unknown>
Fri, 10 Mar 2000 15:23:40 +0000 (15:23 +0000)
Fix h{Fill,Put}Buf(BA)?.  They now work in the presence of
partial/blocking reads and writes, and hPutBuf now doesn't hold on to
the handle while it's blocking.

ghc/lib/std/cbits/readFile.c
ghc/lib/std/cbits/stgio.h
ghc/lib/std/cbits/writeFile.c

index 432a738..a68f3aa 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
  *
- * $Id: readFile.c,v 1.10 2000/01/18 12:42:12 simonmar Exp $
+ * $Id: readFile.c,v 1.11 2000/03/10 15:23:40 simonmar Exp $
  *
  * hGetContents Runtime Support
  */
@@ -105,8 +105,19 @@ readBlock(StgForeignPtr ptr)
 }
 
 /* Filling up a (block-buffered) buffer of length len */
+
+/* readChunk(FileObjet *, void *, int)
+ * returns:
+ *  -1                             error
+ *  -2                             object closed
+ *  FILEOBJ_BLOCKED_CONN_WRITE     blocking while flushing
+ *                                 buffer of connected handle.
+ *  FILEOBJ_BLOCKED_READ           didn't read anything; would block
+ *  n, where n > 0                 read n bytes into buffer.
+ */
+
 StgInt
-readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len)
+readChunk(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len)
 {
     IOFileObject* fo = (IOFileObject*)ptr;
     int count=0,rc=0, total_count;
@@ -159,7 +170,7 @@ readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len)
        return count;
 
     len -= count;
-    p = buf;
+    p = buf+off;
     p += count;
     total_count = count;
 
@@ -172,28 +183,28 @@ readChunk(StgForeignPtr ptr, StgAddr buf, StgInt len)
 #else
                 read(fd, p, len))) <= 0 ) {
 #endif
-       if ( count == 0 ) { /* EOF */
-           break;
+        /* EOF */
+       if ( count == 0 ) {
+            FILEOBJ_SET_EOF(fo);
+            return total_count;
+
+        /* Blocking */
        } else if ( count == -1 && errno == EAGAIN) {
-           /* ToDo: partial/blocked reads??????  Looks like we don't recover
-            * from this properly.
-            */
            errno = 0;
-           return FILEOBJ_BLOCKED_READ;
+            if (total_count > 0) 
+               return total_count; /* partial read */
+           else
+              return FILEOBJ_BLOCKED_READ;
+
+        /* Error */
        } else if ( count == -1 && errno != EINTR) {
            cvtErrno();
            stdErrno();
            return -1;
-       }
-        total_count += count;
-       len -= count;
-       p += count;
+        }
     }
 
     total_count += count;
-    /* ToDo: might point beyond the end of the buffer??? */
-    fo->bufWPtr = total_count;
-    fo->bufRPtr = 0;
     return total_count;
 }
 
index fcda181..5203040 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: stgio.h,v 1.16 1999/12/08 15:47:08 simonmar Exp $
+ * $Id: stgio.h,v 1.17 2000/03/10 15:23:40 simonmar Exp $
  *
  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1999
  *
@@ -161,7 +161,7 @@ StgInt  get_prog_argc(void);
 
 /* readFile.c */
 StgInt readBlock (StgForeignPtr);
-StgInt readChunk (StgForeignPtr,StgAddr,StgInt);
+StgInt readChunk (StgForeignPtr,StgAddr,StgInt,StgInt);
 StgInt readLine  (StgForeignPtr);
 StgInt readChar  (StgForeignPtr);
 
@@ -230,8 +230,8 @@ StgInt toClockSec (StgInt, StgInt, StgInt, StgInt, StgInt, StgInt, StgInt, StgBy
 /* writeError.c */
 void    writeErrString__ (StgAddr, StgByteArray, StgInt);
 /* writeFile.c */
-StgInt writeBuf  (StgForeignPtr, StgAddr, StgInt);
-StgInt writeBufBA  (StgForeignPtr, StgByteArray, StgInt);
+StgInt writeBuf  (StgForeignPtr, StgAddr, StgInt, StgInt);
+StgInt writeBufBA  (StgForeignPtr, StgByteArray, StgInt, StgInt);
 StgInt writeFileObject (StgForeignPtr, StgInt);
 StgInt writeBuffer (StgForeignPtr, StgInt);
 
index 5255ea9..eed60e9 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
  *
- * $Id: writeFile.c,v 1.12 1999/12/08 15:47:08 simonmar Exp $
+ * $Id: writeFile.c,v 1.13 2000/03/10 15:23:40 simonmar Exp $
  *
  * hPutStr Runtime Support
  */
@@ -82,15 +82,21 @@ writeBuffer(StgForeignPtr ptr, StgInt bytes)
 }
 
 
+/* ToDo: there's currently no way for writeBuf to return both a
+ * partial write and an indication that the write blocked.  It needs
+ * two calls: one to get the partial result, and the next one to block.
+ * This matches Unix write/2, but is rather a waste.
+ */
+
 StgInt
-writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
+writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt off, StgInt len)
 {
     IOFileObject* fo = (IOFileObject*)ptr;
-    int count;
+    int count, total_count;
     int rc = 0;
-    char *pBuf = (char *) buf;
+    char *pBuf = (char *) buf+off;
 
-    if (len == 0 )
+    if (len == 0)
        return 0;
 
     /* First of all, check if we do need to flush the buffer .. */
@@ -100,10 +106,10 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
     if ( fo->buf != NULL                    &&   /* buffered and */
          (fo->bufWPtr + len < (fo->bufSize))      /* there's room */
        ) {
-       /* Block copying is likely to be cheaper than, flush, followed by write */
-       memcpy(((char*)fo->buf + fo->bufWPtr), buf, len);
+       /* Block copying is likely to be cheaper than flush, followed by write */
+       memcpy(((char*)fo->buf + fo->bufWPtr), pBuf, len);
        fo->bufWPtr += len;
-       return 0;
+       return len;
     }
     /* If we do overflow, flush current contents of the buffer and
        directly output the chunk.
@@ -120,6 +126,8 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
        }
     }
 
+    total_count = 0;
+
     while ((count = 
                (
 #ifdef USE_WINSOCK
@@ -132,10 +140,14 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
         if ( count >= 0 ) {
             len -= count;
            pBuf += count;
+            total_count += count;
            continue;
        } else if ( errno == EAGAIN ) {
            errno = 0;
-           return FILEOBJ_BLOCKED_WRITE;
+            if (total_count > 0)
+                return total_count; /* partial write */
+           else
+               return FILEOBJ_BLOCKED_WRITE;
        } else if ( errno != EINTR ) {
            cvtErrno();
            stdErrno();
@@ -143,11 +155,12 @@ writeBuf(StgForeignPtr ptr, StgAddr buf, StgInt len)
        }
     }
 
-    return 0;
+    total_count += count;
+    return total_count;
 }
 
 StgInt
-writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt len)
+writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt off, StgInt len)
 { 
-    return (writeBuf(ptr,(StgAddr)buf, len)); 
+    return (writeBuf(ptr,(StgAddr)buf, off, len)); 
 }