#ifdef _WIN32
HANDLE hdl;
OVERLAPPED write_ovl;
- BYTE *write_buf;
+ BYTE pending_byte;
BOOL writing;
#else
int fd;
sp_close(port);
RETURN_FAIL("CreateEvent() failed");
}
- port->write_buf = NULL;
port->writing = FALSE;
}
RETURN_FAIL("CloseHandle() failed");
port->hdl = INVALID_HANDLE_VALUE;
if (port->nonblocking) {
- if (port->writing)
- /* Write should have been stopped by closing the port, so safe to free buffer. */
- free(port->write_buf);
/* Close event handle created for overlapped writes. */
if (CloseHandle(port->write_ovl.hEvent) == 0)
RETURN_FAIL("CloseHandle() failed");
#ifdef _WIN32
DWORD written = 0;
+ BYTE *ptr = (BYTE *) buf;
if (port->nonblocking) {
/* Non-blocking write. */
if (HasOverlappedIoCompleted(&port->write_ovl)) {
DEBUG("Previous write completed");
port->writing = 0;
- free(port->write_buf);
- port->write_buf = NULL;
} else {
DEBUG("Previous write not complete");
/* Can't take a new write until the previous one finishes. */
}
}
- /* Copy user buffer. */
- if (!(port->write_buf = malloc(count)))
- RETURN_ERROR(SP_ERR_MEM, "buffer copy malloc failed");
- memcpy(port->write_buf, buf, count);
-
- /* Start asynchronous write. */
- if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
- if (GetLastError() == ERROR_IO_PENDING) {
- DEBUG("Asynchronous write started");
- port->writing = 1;
- RETURN_VALUE("%d", count);
+ /* Keep writing data until the OS has to actually start an async IO for it.
+ * At that point we know the buffer is full. */
+ while (written < count)
+ {
+ /* Copy first byte of user buffer. */
+ port->pending_byte = *ptr++;
+
+ /* Start asynchronous write. */
+ if (WriteFile(port->hdl, &port->pending_byte, 1, NULL, &port->write_ovl) == 0) {
+ if (GetLastError() == ERROR_IO_PENDING) {
+ DEBUG("Asynchronous write started");
+ port->writing = 1;
+ RETURN_VALUE("%d", ++written);
+ } else {
+ /* Actual failure of some kind. */
+ RETURN_FAIL("WriteFile() failed");
+ }
} else {
- free(port->write_buf);
- port->write_buf = NULL;
- /* Actual failure of some kind. */
- RETURN_FAIL("WriteFile() failed");
+ DEBUG("Single byte written immediately.");
+ written++;
}
- } else {
- DEBUG("Write completed immediately");
- free(port->write_buf);
- port->write_buf = NULL;
- RETURN_VALUE("%d", count);
}
+
+ DEBUG("All bytes written immediately.");
+
} else {
/* Blocking write. */
if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {