|
From: <gb...@us...> - 2008-10-15 05:54:18
|
Revision: 321
http://gearbox.svn.sourceforge.net/gearbox/?rev=321&view=rev
Author: gbiggs
Date: 2008-10-15 05:54:06 +0000 (Wed, 15 Oct 2008)
Log Message:
-----------
Performance improvements
Modified Paths:
--------------
gearbox/trunk/src/flexiport/port.cpp
gearbox/trunk/src/flexiport/serialport.cpp
gearbox/trunk/src/flexiport/serialport.h
gearbox/trunk/src/flexiport/tcpport.cpp
gearbox/trunk/src/flexiport/tcpport.h
Modified: gearbox/trunk/src/flexiport/port.cpp
===================================================================
--- gearbox/trunk/src/flexiport/port.cpp 2008-10-14 05:29:27 UTC (rev 320)
+++ gearbox/trunk/src/flexiport/port.cpp 2008-10-15 05:54:06 UTC (rev 321)
@@ -82,7 +82,7 @@
if (bytesAvailable < 0)
return -1; // Timeout
else if (bytesAvailable == 0)
- return 0; // Nothing available
+ return -1; // Nothing available
if (_debug >= 2)
{
@@ -90,7 +90,7 @@
" bytes waiting to be read into a string" << endl;
}
- // Read this many characters into a string - include space for a NULL incase one doesn't
+ // Read this many characters into a string - include space for a NULL in case one doesn't
// come in the transmitted data.
charBuffer = new char[bytesAvailable + 1];
if ((numRead = Read (charBuffer, bytesAvailable)) < 0)
Modified: gearbox/trunk/src/flexiport/serialport.cpp
===================================================================
--- gearbox/trunk/src/flexiport/serialport.cpp 2008-10-14 05:29:27 UTC (rev 320)
+++ gearbox/trunk/src/flexiport/serialport.cpp 2008-10-15 05:54:06 UTC (rev 321)
@@ -4,17 +4,17 @@
* Copyright (c) 2008 Geoffrey Biggs
*
* flexiport flexible hardware data communications library.
- *
- * This distribution is licensed to you under the terms described in the LICENSE file included in
+ *
+ * This distribution is licensed to you under the terms described in the LICENSE file included in
* this distribution.
*
* This work is a product of the National Institute of Advanced Industrial Science and Technology,
* Japan. Registration number: H20PRO-881
- *
+ *
* This file is part of flexiport.
*
* flexiport is free software: you can redistribute it and/or modify it under the terms of the GNU
- * Lesser General Public License as published by the Free Software Foundation, either version 3 of
+ * Lesser General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* flexiport is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
@@ -293,7 +293,7 @@
StrError (ErrNo ());
throw PortException (ss.str ());
}
-
+
SetPortTimeout ();
#else
int flags = 0;
@@ -306,14 +306,14 @@
flags |= O_NOCTTY;
- // For simplicity set the port to non-blocking and use select() to wait for data based on the
+ // For simplicity set the port to non-blocking and use select() to wait for data based on the
// timeout.
flags |= O_NONBLOCK;
if ((_fd = open (_device.c_str (), flags)) < 0)
{
stringstream ss;
- ss << "Failed to open device " << _device << " with error: (" << ErrNo () << ") " <<
+ ss << "Failed to open device " << _device << " with error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -378,10 +378,28 @@
}
#else
ssize_t receivedBytes = 0;
- if (WaitForDataOrTimeout () == TIMED_OUT)
- return -1;
- receivedBytes = read (_fd, buffer, count);
+ if (_timeout._sec == -1)
+ {
+ // Port is blocking, so just read
+ receivedBytes = read (_fd, buffer, count);
+ }
+ else
+ {
+ // Port is non-blocking, so try to read, see if we get any data (if there is none, this will
+ // return immediately, and is much faster than ioctl() and select() calls)
+ receivedBytes = read (_fd, buffer, count);
+ // Check if that call "timed out"
+ if (receivedBytes < 0 && ErrNo () == EAGAIN)
+ {
+ // No data was available, so wait for data or timeout, then read if data is available
+ if (WaitForDataOrTimeout () == TIMED_OUT)
+ return -1;
+ receivedBytes = read (_fd, buffer, count);
+ }
+ // If first call doesn't return a timeout, fall through to the result/error checking below
+ }
+
if (_debug >= 2)
cerr << "SerialPort::" << __func__ << "() Read " << receivedBytes << " bytes" << endl;
@@ -389,11 +407,11 @@
{
if (ErrNo () == EAGAIN)
return -1; // Timed out
- else
+ else
{
// General error
stringstream ss;
- ss << "SerialPort::" << __func__ << "() recv() error: (" <<
+ ss << "SerialPort::" << __func__ << "() read() error: (" <<
ErrNo () << ") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -427,11 +445,11 @@
if (_debug >= 2)
{
- cerr << "SerialPort::" << __func__ << "() Going to read until have " << count <<
+ cerr << "SerialPort::" << __func__ << "() Going to read until have " << count <<
" bytes" << endl;
}
- // Set the timeout to infinite blocking
+ // Set the port to infinite blocking
SetTimeout (Timeout (-1, 0));
// Keep calling Read() until count bytes have been received or a timeout
while (receivedBytes < count)
@@ -455,15 +473,15 @@
// Restore the timeout
SetTimeout (oldTimeout);
stringstream ss;
- ss << "SerialPort::" << __func__ << "() Port closed while trying to read " <<
+ ss << "SerialPort::" << __func__ << "() Port closed while trying to read " <<
count << " bytes";
throw PortException (ss.str ());
}
// If it is open we can keep going, but with a warning
if (_debug >= 1)
{
- cerr << "WARNING: SerialPort::" << __func__ <<
- " Port closed during ReadFull operation; data may be missing/corrupted." <<
+ cerr << "WARNING: SerialPort::" << __func__ <<
+ " Port closed during ReadFull operation; data may be missing/corrupted." <<
endl;
}
}
@@ -488,19 +506,16 @@
if (!ClearCommError (_fd, &errorType, &comStat))
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() ClearCommError() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() ClearCommError() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
bytesAvailable = comStat.cbInQue;
#else
- if (!IsDataAvailable ())
- return 0;
-
if (ioctl (_fd, FIONREAD, &bytesAvailable) < 0)
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() ioctl() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() ioctl() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -537,11 +552,13 @@
bytesAvailable = BytesAvailable ();
}
#else
+ // WaitForDataOrTimeout() will do an initial check to see if there is data available immediately
+ // and only select() if there isn't
if (WaitForDataOrTimeout () == TIMED_OUT)
{
if (_debug >= 2)
{
- cerr << "SerialPort::" << __func__ <<
+ cerr << "SerialPort::" << __func__ <<
" Timed out waiting for data to check bytes available" << endl;
}
if (IsBlocking ())
@@ -553,7 +570,7 @@
if (ioctl (_fd, FIONREAD, &bytesAvailable) < 0)
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() ioctl() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() ioctl() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -616,7 +633,7 @@
{
// General error
stringstream ss;
- ss << "SerialPort::" << __func__ << "() write() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() write() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -635,7 +652,7 @@
if (!PurgeComm (_fd, PURGE_RXCLEAR | PURGE_TXCLEAR))
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() PurgeComm() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() PurgeComm() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -643,7 +660,7 @@
if (tcflush (_fd, TCIOFLUSH) < 0)
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() tcflush() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() tcflush() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -656,7 +673,7 @@
if (!FlushFileBuffers (_fd))
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() FlushFileBuffers() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() FlushFileBuffers() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -664,7 +681,7 @@
if (tcdrain (_fd) < 0)
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() tcdrain() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() tcdrain() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -695,7 +712,7 @@
status << "Odd" << endl;
break;
default:
- throw PortException (string ("SerialPort::") + __func__ +
+ throw PortException (string ("SerialPort::") + __func__ +
string (" Unknown parity setting."));
break;
}
@@ -708,16 +725,14 @@
void SerialPort::SetTimeout (Timeout timeout)
{
_timeout = timeout;
-#if defined (WIN32)
SetPortTimeout ();
-#endif
}
void SerialPort::SetCanRead (bool canRead)
{
if (IsOpen ())
{
- throw PortException (string ("SerialPort::") + __func__ +
+ throw PortException (string ("SerialPort::") + __func__ +
string (" Cannot change read capability of an open port."));
}
_canRead = canRead;
@@ -727,7 +742,7 @@
{
if (IsOpen ())
{
- throw PortException (string ("SerialPort::") + __func__ +
+ throw PortException (string ("SerialPort::") + __func__ +
string (" Cannot change write capability of an open port."));
}
_canWrite = canWrite;
@@ -742,7 +757,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() GetCommState() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() GetCommState() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -753,7 +768,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() SetCommState() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() SetCommState() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -764,7 +779,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() tcgetattr() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() tcgetattr() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -772,7 +787,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() cfsetispeed() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() cfsetispeed() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -781,7 +796,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() cfsetospeed() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() cfsetospeed() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -789,7 +804,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() tcsetattr() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() tcsetattr() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -857,52 +872,14 @@
return false;
}
-// Checks if data is available right now
-bool SerialPort::IsDataAvailable (void)
-{
-#if defined (WIN32)
- if (BytesAvailable () <= 0)
- {
- // No data
- if (_debug >= 3)
- cerr << "SerialPort::" << __func__ << "() Found no data waiting" << endl;
- return false;
- }
-#else
- fd_set fdSet;
- struct timeval tv;
-
- FD_ZERO (&fdSet);
- FD_SET (_fd, &fdSet);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- int result = select (_fd + 1, &fdSet, NULL, NULL, &tv);
-
- if (result < 0)
- {
- stringstream ss;
- ss << "SerialPort::" << __func__ << "() select() error: (" << ErrNo () << ") " <<
- StrError (ErrNo ());
- throw PortException (ss.str ());
- }
- else if (result == 0)
- {
- if (_debug >= 3)
- cerr << "SerialPort::" << __func__ << "() Found no data waiting" << endl;
- // No data
- return false;
- }
-#endif
- if (_debug >= 3)
- cerr << "SerialPort::" << __func__ << "() Found data waiting" << endl;
- return true;
-}
-
#if !defined (WIN32)
-// Checks if data is available, waiting for the timeout if none is available immediatly
+// Checks if data is available, waiting for the timeout if none is available immediately
SerialPort::WaitStatus SerialPort::WaitForDataOrTimeout (void)
{
+ // Check if there is data available immediately before spending time on a select() call
+ if (BytesAvailable () > 0)
+ return DATA_AVAILABLE;
+
fd_set fdSet;
struct timeval tv, *tvPtr = NULL;
@@ -918,7 +895,7 @@
if (result < 0)
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() select() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() select() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -934,7 +911,7 @@
return DATA_AVAILABLE;
}
-// Checks it he port can be written to, waiting for the timeout if it can't be written immediatly
+// Checks if the port can be written to, waiting for the timeout if it can't be written immediately
SerialPort::WaitStatus SerialPort::WaitForWritableOrTimeout (void)
{
fd_set fdSet;
@@ -952,7 +929,7 @@
if (result < 0)
{
stringstream ss;
- ss << "SerialPort::" << __func__ << "() select() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() select() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -991,7 +968,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() GetCommState() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() GetCommState() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -1044,7 +1021,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() SetCommState() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() SetCommState() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -1055,7 +1032,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() tcgetattr() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() tcgetattr() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -1125,7 +1102,7 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() tcsetattr() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() tcsetattr() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -1134,9 +1111,9 @@
SetBaudRate (_baud);
}
-#if defined (WIN32)
void SerialPort::SetPortTimeout (void)
{
+#if defined (WIN32)
COMMTIMEOUTS timeouts;
if (_timeout._sec == -1)
@@ -1171,11 +1148,37 @@
{
Close ();
stringstream ss;
- ss << "SerialPort::" << __func__ << "() SetCommTimeouts() error: (" << ErrNo () << ") " <<
+ ss << "SerialPort::" << __func__ << "() SetCommTimeouts() error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
+#else
+ int flags;
+ if ((flags = fcntl (_fd, F_GETFL)) < 0)
+ {
+ stringstream ss;
+ ss << "SerialPort::" << __func__ << "() fcntl(F_GETFL) error: (" << ErrNo () << ") " <<
+ StrError (ErrNo ());
+ throw PortException (ss.str ());
+ }
+ if (_timeout._sec == -1)
+ {
+ // Block forever
+ flags &= ~O_NONBLOCK;
+ }
+ else
+ {
+ // Non-blocking operation
+ flags |= O_NONBLOCK;
+ }
+ if (fcntl (_fd, F_SETFL, flags) < 0)
+ {
+ stringstream ss;
+ ss << "SerialPort::" << __func__ << "() fcntl(F_SETFL) error: (" << ErrNo () << ") " <<
+ StrError (ErrNo ());
+ throw PortException (ss.str ());
+ }
+#endif
}
-#endif
} // namespace flexiport
Modified: gearbox/trunk/src/flexiport/serialport.h
===================================================================
--- gearbox/trunk/src/flexiport/serialport.h 2008-10-14 05:29:27 UTC (rev 320)
+++ gearbox/trunk/src/flexiport/serialport.h 2008-10-15 05:54:06 UTC (rev 321)
@@ -4,17 +4,17 @@
* Copyright (c) 2008 Geoffrey Biggs
*
* flexiport flexible hardware data communications library.
- *
- * This distribution is licensed to you under the terms described in the LICENSE file included in
+ *
+ * This distribution is licensed to you under the terms described in the LICENSE file included in
* this distribution.
*
* This work is a product of the National Institute of Advanced Industrial Science and Technology,
* Japan. Registration number: H20PRO-881
- *
+ *
* This file is part of flexiport.
*
* flexiport is free software: you can redistribute it and/or modify it under the terms of the GNU
- * Lesser General Public License as published by the Free Software Foundation, either version 3 of
+ * Lesser General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* flexiport is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
@@ -139,9 +139,7 @@
WaitStatus WaitForWritableOrTimeout (void);
#endif
void SetPortSettings (void);
-#if defined (WIN32)
void SetPortTimeout (void);
-#endif
};
} // namespace flexiport
Modified: gearbox/trunk/src/flexiport/tcpport.cpp
===================================================================
--- gearbox/trunk/src/flexiport/tcpport.cpp 2008-10-14 05:29:27 UTC (rev 320)
+++ gearbox/trunk/src/flexiport/tcpport.cpp 2008-10-15 05:54:06 UTC (rev 321)
@@ -159,7 +159,7 @@
Connect ();
}
- SetPortBlockingFlag ();
+ SetSocketBlockingFlag ();
_open = true;
if (_debug >= 2)
cerr << "TCPPort::" << __func__ << "() Port is open" << endl;
@@ -212,16 +212,38 @@
if (_debug >= 2)
cerr << "TCPPort::" << __func__ << "() Going to read " << count << " bytes" << endl;
- if (_timeout._sec != -1)
+ if (_timeout._sec == -1)
{
- if (WaitForDataOrTimeout () == TIMED_OUT)
- return -1;
+ // Socket is blocking, so just read
+#if defined (WIN32)
+ receivedBytes = recv (_sock, reinterpret_cast<char*> (buffer), count, 0);
+#else
+ receivedBytes = recv (_sock, buffer, count, 0);
+#endif
}
+ else
+ {
+ // Socket is non-blocking, so try to read, see if we get any data (if there is none, this
+ // will return immediately, and is much faster than ioctl() and select() calls)
#if defined (WIN32)
- receivedBytes = recv (_sock, reinterpret_cast<char*> (buffer), count, 0);
+ receivedBytes = recv (_sock, reinterpret_cast<char*> (buffer), count, 0);
#else
- receivedBytes = recv (_sock, buffer, count, 0);
+ receivedBytes = recv (_sock, buffer, count, 0);
#endif
+ // Check if that call "timed out"
+ if (receivedBytes < 0 && ErrNo () == ERRNO_EAGAIN)
+ {
+ // No data was available, so wait for data or timeout, then read if data is available
+ if (WaitForDataOrTimeout () == TIMED_OUT)
+ return -1;
+#if defined (WIN32)
+ receivedBytes = recv (_sock, reinterpret_cast<char*> (buffer), count, 0);
+#else
+ receivedBytes = recv (_sock, buffer, count, 0);
+#endif
+ }
+ // If first call doesn't return a timeout, fall through to the result/error checking below
+ }
if (_debug >= 2)
cerr << "TCPPort::" << __func__ << "() Read " << receivedBytes << " bytes" << endl;
@@ -328,13 +350,11 @@
{
// TODO:
// MSG_PEEK is apparently bad on Windows so we should drain what we can into a local buffer
- // instead, then use that first during read calls. See http://support.microsoft.com/kb/192599
+ // instead, then use that first during read calls. See http://support.microsoft.com/kb/192599.
+ // Unless the buffer is static in size this will affect performance and make real-time not work.
CheckPort (true);
- if (!IsDataAvailable ())
- return 0;
-
#if defined (WIN32)
unsigned long bytesAvailable = 0;
if (ioctlsocket (_sock, FIONREAD, &bytesAvailable) < 0)
@@ -376,7 +396,8 @@
// TODO:
// MSG_PEEK is apparently bad on Windows so we should drain what we can into a local buffer
- // instead, then use that first during read calls. See http://support.microsoft.com/kb/192599
+ // instead, then use that first during read calls. See http://support.microsoft.com/kb/192599.
+ // Unless the buffer is static in size this will affect performance and make real-time not work.
#if defined (WIN32)
unsigned long bytesAvailable = 0;
if (ioctlsocket (_sock, FIONREAD, &bytesAvailable) < 0)
@@ -505,7 +526,7 @@
void TCPPort::SetTimeout (Timeout timeout)
{
_timeout = timeout;
- SetPortBlockingFlag ();
+ SetSocketBlockingFlag ();
}
void TCPPort::SetCanRead (bool canRead)
@@ -810,6 +831,9 @@
// Checks if data is available, waiting for the timeout if none is available immediatly
TCPPort::WaitStatus TCPPort::WaitForDataOrTimeout (void)
{
+ if (IsDataAvailable ())
+ return DATA_AVAILABLE;
+
fd_set fdSet;
struct timeval tv, *tvPtr = NULL;
@@ -831,46 +855,62 @@
}
else if (result == 0)
{
- if (_debug >= 3)
- cerr << "TCPPort::" << __func__ << "() Timed out" << endl;
+ if (_debug >= 2)
+ cerr << "TCPPort::" << __func__ << "() Timed out." << endl;
// Time out
return TIMED_OUT;
}
if (_debug >= 2)
- cerr << "TCPPort::" << __func__ << "() Found data waiting" << endl;
+ cerr << "TCPPort::" << __func__ << "() Found data waiting." << endl;
return DATA_AVAILABLE;
}
// Checks if data is available right now
bool TCPPort::IsDataAvailable (void)
{
- fd_set fdSet;
- struct timeval tv;
-
- FD_ZERO (&fdSet);
- FD_SET (_sock, &fdSet);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- int result = select (_sock + 1, &fdSet, NULL, NULL, &tv);
-
- if (result < 0)
+ // First peek at the buffer to see if there is anything waiting
+ char buffer;
+ ssize_t receivedBytes = 0;
+#if defined (WIN32)
+ receivedBytes = recv (_sock, &buffer, 1, MSG_PEEK);
+#else
+ receivedBytes = recv (_sock, reinterpret_cast<void*> (&buffer), 1, MSG_PEEK);
+#endif
+ if (receivedBytes > 0)
{
- stringstream ss;
- ss << "TCPPort::" << __func__ << "() select() error: (" << ErrNo () << ") " <<
- StrError (ErrNo ());
- throw PortException (ss.str ());
+ if (_debug >= 3)
+ cerr << "TCPPort::" << __func__ << "() Found data waiting." << endl;
+ return DATA_AVAILABLE;
}
- else if (result == 0)
+ else if (receivedBytes < 0)
{
- if (_debug >= 3)
- cerr << "TCPPort::" << __func__ << "() Found no data waiting" << endl;
- // No data
- return false;
+ if (ErrNo () != ERRNO_EAGAIN)
+ {
+ // General error
+ stringstream ss;
+ ss << "TCPPort::" << __func__ << "() recv() error: (" << ErrNo () << ") " <<
+ StrError (ErrNo ());
+ throw PortException (ss.str ());
+ }
+ // Else no data available yet
}
+ else // receivedBytes == 0
+ {
+ // Peer disconnected cleanly, do the same at this end
+ if (_debug >= 1)
+ cerr << "TCPPort::" << __func__ << "() Peer disconnected cleanly." << endl;
+ Close ();
+ if (_alwaysOpen)
+ {
+ if (_debug >= 1)
+ cerr << "TCPPort::" << __func__ << "() Trying to reconnect." << endl;
+ Open ();
+ }
+ // Fall through to return no data
+ }
if (_debug >= 3)
- cerr << "TCPPort::" << __func__ << "() Found data waiting" << endl;
- return true;
+ cerr << "TCPPort::" << __func__ << "() Found no data waiting." << endl;
+ return false;
}
// Checks it he port can be written to, waiting for the timeout if it can't be written immediatly
@@ -920,7 +960,7 @@
throw PortException ("Cannot write to read-only port.");
}
-void TCPPort::SetPortBlockingFlag (void)
+void TCPPort::SetSocketBlockingFlag (void)
{
if (_timeout._sec == -1)
{
@@ -936,18 +976,18 @@
}
#else
int flags;
- if ((flags = fcntl (_sock, F_GETFD)) < 0)
+ if ((flags = fcntl (_sock, F_GETFL)) < 0)
{
stringstream ss;
- ss << "TCPPort::" << __func__ << "() fcntl(F_GETFD) error: (" << ErrNo () << ") " <<
+ ss << "TCPPort::" << __func__ << "() fcntl(F_GETFL) error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
flags &= ~O_NONBLOCK;
- if (fcntl (_sock, F_SETFD, flags) < 0)
+ if (fcntl (_sock, F_SETFL, flags) < 0)
{
stringstream ss;
- ss << "TCPPort::" << __func__ << "() fcntl(F_SETFD) error: (" << ErrNo () << ") " <<
+ ss << "TCPPort::" << __func__ << "() fcntl(F_SETFL) error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -967,18 +1007,18 @@
}
#else
int flags;
- if ((flags = fcntl (_sock, F_GETFD)) < 0)
+ if ((flags = fcntl (_sock, F_GETFL)) < 0)
{
stringstream ss;
- ss << "TCPPort::" << __func__ << "() fcntl(F_GETFD) error: (" << ErrNo () << ") " <<
+ ss << "TCPPort::" << __func__ << "() fcntl(F_GETFL) error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
flags |= O_NONBLOCK;
- if (fcntl (_sock, F_SETFD, flags) < 0)
+ if (fcntl (_sock, F_SETFL, flags) < 0)
{
stringstream ss;
- ss << "TCPPort::" << __func__ << "() fcntl(F_SETFD) error: (" << ErrNo () << ") " <<
+ ss << "TCPPort::" << __func__ << "() fcntl(F_SETFL) error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
Modified: gearbox/trunk/src/flexiport/tcpport.h
===================================================================
--- gearbox/trunk/src/flexiport/tcpport.h 2008-10-14 05:29:27 UTC (rev 320)
+++ gearbox/trunk/src/flexiport/tcpport.h 2008-10-15 05:54:06 UTC (rev 321)
@@ -112,7 +112,7 @@
WaitStatus WaitForDataOrTimeout (void);
bool IsDataAvailable (void);
WaitStatus WaitForWritableOrTimeout (void);
- void SetPortBlockingFlag (void);
+ void SetSocketBlockingFlag (void);
};
} // namespace flexiport
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|