Skip to content
Snippets Groups Projects
Commit f9a0273c authored by Simon Marlow's avatar Simon Marlow
Browse files

[project @ 2000-03-10 15:23:40 by simonmar]

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.
parent 2f4676b4
No related merge requests found
/*
* (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;
}
......
/* -----------------------------------------------------------------------------
* $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);
......
/*
* (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));
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment