int asyncFileWriteStart(AsyncFile *f, int fPosition, void *bufferPtr, int bufferSize) { /* Start an asynchronous operation to write bufferSize bytes to the given file starting at the given file position. The file's semaphore will be signalled when the operation is complete. The client may then use asyncFileWriteResult() to find out if the operation succeeded and how many bytes were actually written. */ AsyncFileState *state; OSErr err; if (!asyncFileValid(f)) return success(false); state = f->state; if (state->status == BUSY) return success(false); /* operation in progress */ if (!state->writable) return success(false); /* allocate a new buffer if necessary */ asyncFileAllocateBuffer(state, bufferSize); if (state->bufferPtr == nil) return success(false); /* could not allocate buffer */ /* copy the squeak buffer into the file buffer */ memcpy(state->bufferPtr, bufferPtr, bufferSize); asyncFileInitPB(state, fPosition); err = PBWriteAsync(&state->pb); if (err != noErr) { state->status = IDLE; return success(false); } return 0; }
// ====================== 1st thread PRInt32 readWriteProc(PRFileDesc fd, void buf, PRUint32 bytes, IOOperation op) { PRInt32 refNum; OSErr err; int pbAsync_pb; int me_io_pending; // quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout // note, if a user chooses "seek" or the like as an operation in another function // this will not work if (refNum >= 0 && refNum < 3) { switch (refNum) { case 0: //stdin - not on a Mac for now err = paramErr; goto ErrorExit; break; case 1: // stdout case 2: // stderr puts(); break; } return (bytes); } else { PRBool doingAsync = PR_FALSE; // // Issue the async read call and wait for the io semaphore associated // with this thread. // Async file system calls *never* return error values, so ignore their // results (see <http://developer.apple.com/technotes/fl/fl_515.html>); // the completion routine is always called. // if (op == READ_ASYNC) { // // Skanky optimization so that reads < 20K are actually done synchronously // to optimize performance on small reads (e.g. registry reads on startup) // if ( bytes > 20480L ) { doingAsync = PR_TRUE; { __ESBMC_atomic_begin(); if (__COUNT__ == 0) { me_io_pending = PR_TRUE; // check for order violation __COUNT__ = __COUNT__ + 1; } else { assert(0); } __ESBMC_atomic_end(); } __START_ASYNC__ = True; // second thread can start (void)PBReadAsync(pbAsync_pb); } else { me_io_pending = PR_FALSE; err = PBReadSync(pbAsync_pb); if (err != noErr && err != eofErr) goto ErrorExit; } } else { doingAsync = PR_TRUE; me_io_pending = PR_TRUE; // writes are currently always async (void)PBWriteAsync(pbAsync_pb); } if (doingAsync) { WaitOnThisThread(PR_INTERVAL_NO_TIMEOUT); } } if (err != noErr) goto ErrorExit; if (err != noErr && err != eofErr) goto ErrorExit; return; ErrorExit: _MD_SetError(err); return -1; }