summaryrefslogtreecommitdiff
path: root/ghc/lib/std/cbits/writeFile.c
diff options
context:
space:
mode:
authorsimonmar <unknown>2001-05-18 16:54:11 +0000
committersimonmar <unknown>2001-05-18 16:54:11 +0000
commitd9af408e5c512501cfa991f5e4a76c9154bca917 (patch)
tree627365b7dad9c2a5e1d892a1f631690b46e24a11 /ghc/lib/std/cbits/writeFile.c
parent5f6f90850d5c82dc56d13bbc035d635e1cb2106b (diff)
downloadhaskell-d9af408e5c512501cfa991f5e4a76c9154bca917.tar.gz
[project @ 2001-05-18 16:54:04 by simonmar]
I/O library rewrite ------------------- This commit replaces the old C/Haskell I/O implementation with a new Haskell-only one using the new FFI & hsc2hs. main points: - lots of code deleted: we're about 3000 lines of C lighter, but the amount of Haskell code is about the same. - performance is ok: some operations are faster, others are slower. There's still some tuning to do, though. - the new library is designed to handle read/write streams much better: a read/write stream gets a special kind of handle internally called a "DuplexHandle", which actually contains two separate handles, one for writing and one for reading. The upshot is that you can do simultaneous reading and writing to/from a socket or FIFO without any locking problems. The effect is similar to calling socketToHandle twice, except that finalization works properly (creating two separate Handles could lead to the socket being closed too early when one of the Handles is GC'd). - hConnectTo and withHandleFor are gone (no one responded to my mail on GHC users, but we can always bring 'em back if necessary). - I made a half-hearted attempt at keeping the system-specific code in one place: see PrelPosix.hsc. - I've rearranged the I/O tests and added lots more. ghc/tests/lib/IO now contains Haskell 98-only IO tests, ghc/test/lib/{IOExts, Directory, Time} now contain tests for the relevant libraries. I haven't quite finished in here yet, the IO tests work but the others don't yet. - I haven't done anything about Unicode yet, but now we can start to discuss what needs doing here. The new library is using MutableByteArrays for its buffers because that turned out to be a *lot* easier (and quicker) than malloc'd buffers - I hope this won't cause trouble for unicode translations though. WARNING: Windows users refrain from updating until we've had a chance to fix any issues that arise. Testing: the basic H98 stuff has been pretty thoroughly tested, but the new duplex handle stuff is still a little green.
Diffstat (limited to 'ghc/lib/std/cbits/writeFile.c')
-rw-r--r--ghc/lib/std/cbits/writeFile.c198
1 files changed, 0 insertions, 198 deletions
diff --git a/ghc/lib/std/cbits/writeFile.c b/ghc/lib/std/cbits/writeFile.c
deleted file mode 100644
index 383ec52459..0000000000
--- a/ghc/lib/std/cbits/writeFile.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * (c) The GRASP/AQUA Project, Glasgow University, 1994-1998
- *
- * $Id: writeFile.c,v 1.14 2000/04/12 17:33:16 simonmar Exp $
- *
- * hPutStr Runtime Support
- */
-
-#include "Rts.h"
-#include "stgio.h"
-
-#if defined(HAVE_WINSOCK_H) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
-#define USE_WINSOCK
-#endif
-
-#ifdef USE_WINSOCK
-#include <winsock.h>
-#endif
-
-StgInt
-writeFileObject(StgForeignPtr ptr, StgInt bytes)
-{
- int rc=0;
- IOFileObject* fo = (IOFileObject*)ptr;
-
- /* If we've got a r/w file object in our hand, flush the
- (input) buffer contents first.
- */
- if ( FILEOBJ_READABLE(fo) && FILEOBJ_JUST_READ(fo) ) {
- fo->flags = (fo->flags & ~FILEOBJ_RW_READ) | FILEOBJ_RW_WRITE;
- rc = flushReadBuffer(ptr);
- if (rc < 0) return rc;
- }
-
- return (writeBuffer(ptr, bytes));
-}
-
-StgInt
-writeBuffer(StgForeignPtr ptr, StgInt bytes)
-{
- int count;
- IOFileObject* fo = (IOFileObject*)ptr;
-
- char *pBuf = (char *) fo->buf + fo->bufRPtr;
-
- bytes -= fo->bufRPtr;
-
- /* Disallow short writes */
- if (bytes == 0 || fo->buf == NULL) {
- fo->bufRPtr = 0;
- return 0;
- }
-
- while ((count =
- (
-#ifdef USE_WINSOCK
- fo->flags & FILEOBJ_WINSOCK ?
- send(fo->fd, pBuf, bytes, 0) :
- write(fo->fd, pBuf, bytes))) < bytes) {
-#else
- write(fo->fd, pBuf, bytes))) < bytes) {
-#endif
- if ( count == -1 && errno == EAGAIN) {
- errno = 0;
- return FILEOBJ_BLOCKED_WRITE;
- }
- else if ( count == -1 && errno != EINTR ) {
- cvtErrno();
- stdErrno();
- return -1;
- }
- else {
- bytes -= count;
- pBuf += count;
- fo->bufRPtr += count;
- }
- }
- /* Signal that we've emptied the buffer */
- fo->bufRPtr = 0;
- fo->bufWPtr = 0;
- return 0;
-}
-
-
-/* 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 off, StgInt len)
-{
- IOFileObject* fo = (IOFileObject*)ptr;
- int count, total_count;
- int rc = 0;
- char *pBuf = (char *) buf+off;
-
- if (len == 0)
- return 0;
-
- /* First of all, check if we do need to flush the buffer .. */
- /* Note - in the case of line buffering, we do not currently check
- whether we need to flush buffer due to line terminators in the
- buffer we're outputting */
- 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), pBuf, len);
- fo->bufWPtr += len;
- return len;
- }
- /* If we do overflow, flush current contents of the buffer and
- directly output the chunk.
- (no attempt at splitting up the chunk is currently made)
- */
- if ( fo->buf != NULL && /* buffered and */
- (fo->bufWPtr + len >= (fo->bufSize)) /* there's not room */
- ) {
- /* Flush buffer */
- rc = writeFileObject(ptr, fo->bufWPtr);
- /* ToDo: undo buffer fill if we're blocking.. */
- if (rc != 0) {
- return rc;
- }
- }
-
- total_count = 0;
-
- while ((count =
- (
-#ifdef USE_WINSOCK
- fo->flags & FILEOBJ_WINSOCK ?
- send(fo->fd, pBuf, (int)len, 0) :
- write(fo->fd, pBuf, (int)len))) < len ) {
-#else
- write(fo->fd, pBuf, (int)len))) < len ) {
-#endif
- if ( count >= 0 ) {
- len -= count;
- pBuf += count;
- total_count += count;
- continue;
- } else if ( errno == EAGAIN ) {
- errno = 0;
- if (total_count > 0)
- return total_count; /* partial write */
- else
- return FILEOBJ_BLOCKED_WRITE;
- } else if ( errno != EINTR ) {
- cvtErrno();
- stdErrno();
- return -1;
- }
- }
-
- total_count += count;
- return total_count;
-}
-
-StgInt
-writeBufBA(StgForeignPtr ptr, StgByteArray buf, StgInt off, StgInt len)
-{
- return (writeBuf(ptr,(StgAddr)buf, off, len));
-}
-
-/* -----------------------------------------------------------------------------
- * write_ is just a simple wrapper around write/2 that restarts
- * on EINTR and returns FILEOBJ_BLOCKED_WRITE on EAGAIN.
- * -------------------------------------------------------------------------- */
-
-StgInt
-write_(StgForeignPtr ptr, StgAddr buf, StgInt len)
-{
- IOFileObject* fo = (IOFileObject*)ptr;
- int rc;
-
- while ((rc =
- (
-#ifdef USE_WINSOCK
- fo->flags & FILEOBJ_WINSOCK ?
- send(fo->fd, buf, (int)len, 0) :
- write(fo->fd, buf, (int)len))) < 0 ) {
-#else
- write(fo->fd, buf, (int)len))) < 0 ) {
-#endif
- if ( errno == EAGAIN ) {
- errno = 0;
- return FILEOBJ_BLOCKED_WRITE;
- } else if ( errno != EINTR ) {
- cvtErrno();
- stdErrno();
- return -1;
- }
- }
- return rc;
-}