|
From: <gb...@us...> - 2008-10-15 07:03:53
|
Revision: 322
http://gearbox.svn.sourceforge.net/gearbox/?rev=322&view=rev
Author: gbiggs
Date: 2008-10-15 07:03:32 +0000 (Wed, 15 Oct 2008)
Log Message:
-----------
Performance improvements
Modified Paths:
--------------
gearbox/trunk/src/flexiport/tcpport.cpp
gearbox/trunk/src/flexiport/test/tcp_example.cpp
gearbox/trunk/src/flexiport/test/udp_example.cpp
gearbox/trunk/src/flexiport/udpport.cpp
gearbox/trunk/src/flexiport/udpport.h
Modified: gearbox/trunk/src/flexiport/tcpport.cpp
===================================================================
--- gearbox/trunk/src/flexiport/tcpport.cpp 2008-10-15 05:54:06 UTC (rev 321)
+++ gearbox/trunk/src/flexiport/tcpport.cpp 2008-10-15 07:03:32 UTC (rev 322)
@@ -832,7 +832,13 @@
TCPPort::WaitStatus TCPPort::WaitForDataOrTimeout (void)
{
if (IsDataAvailable ())
+ {
+ if (_debug >= 2)
+ cerr << "TCPPort::" << __func__ << "() Found data available immediately." << endl;
return DATA_AVAILABLE;
+ }
+ if (_debug >= 2)
+ cerr << "TCPPort::" << __func__ << "() No data available immediately, will wait." << endl;
fd_set fdSet;
struct timeval tv, *tvPtr = NULL;
@@ -868,7 +874,11 @@
// Checks if data is available right now
bool TCPPort::IsDataAvailable (void)
{
- // First peek at the buffer to see if there is anything waiting
+ if (_debug >= 3)
+ cerr << "TCPPort::" << __func__ << "() Checking if data is available immediately." << endl;
+
+ // First peek at the buffer to see if there is anything waiting. For an infinite timeout,
+ // this will block indefinitely until we get data.
char buffer;
ssize_t receivedBytes = 0;
#if defined (WIN32)
@@ -880,7 +890,7 @@
{
if (_debug >= 3)
cerr << "TCPPort::" << __func__ << "() Found data waiting." << endl;
- return DATA_AVAILABLE;
+ return true;
}
else if (receivedBytes < 0)
{
Modified: gearbox/trunk/src/flexiport/test/tcp_example.cpp
===================================================================
--- gearbox/trunk/src/flexiport/test/tcp_example.cpp 2008-10-15 05:54:06 UTC (rev 321)
+++ gearbox/trunk/src/flexiport/test/tcp_example.cpp 2008-10-15 07:03:32 UTC (rev 322)
@@ -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
@@ -94,7 +94,7 @@
port->Write (charMessage3, strlen (charMessage3) + 1);
cout << "Client waiting for parting message." << endl;
port->ReadString (stringMessage);
- cout << "Client got parting message: \"" << stringMessage << '"' << endl;
+ cout << "Client got parting message: \"" << stringMessage << '"' << endl;
cout << "Client done." << endl;
return 0;
Modified: gearbox/trunk/src/flexiport/test/udp_example.cpp
===================================================================
--- gearbox/trunk/src/flexiport/test/udp_example.cpp 2008-10-15 05:54:06 UTC (rev 321)
+++ gearbox/trunk/src/flexiport/test/udp_example.cpp 2008-10-15 07:03:32 UTC (rev 322)
@@ -112,17 +112,6 @@
cout << "Test failed." << endl;
return -1;
}
-// cout << "Server testing ReadStringUntil()" << endl;
-// port->ReadStringUntil (stringBuffer, '\n');
-// cout << "Server received \"" << stringBuffer << '"' << endl;
-// if (stringBuffer != "Message #2\n")
-// {
-// cout << "Test failed." << endl;
-// return -1;
-// }
-// cout << "Server has " << port->BytesAvailable () << " bytes available immediatly." << endl;
-// cout << "Server clearing the trailing null byte from that last message." << endl;
-// port->Read (charBuffer, 1);
int bytesWaiting = port->BytesAvailableWait ();
cout << "Server has " << bytesWaiting << " bytes available after waiting." << endl;
cout << "Server testing ReadFull()" << endl;
@@ -133,16 +122,6 @@
cout << "Test failed." << endl;
return -1;
}
-// cout << "Server testing ReadUntil()" << endl;
-// port->ReadUntil (charBuffer, 32, '\n');
-// cout << "Server received \"" << charBuffer << '"' << endl;
-// if (strncmp (charBuffer, "Probably message #4\n", 20) != 0)
-// {
-// cout << "Test failed." << endl;
-// return -1;
-// }
-// cout << "Server clearing the trailing null byte from that last message." << endl;
-// port->Read (charBuffer, 1);
cout << "Server testing Read()" << endl;
memset (charBuffer, 0, sizeof (char) * 32);
port->Read (charBuffer, 32);
@@ -152,14 +131,6 @@
cout << "Test failed." << endl;
return -1;
}
-// cout << "Server testing ReadLine()" << endl;
-// port->ReadLine (stringBuffer);
-// cout << "Server received \"" << stringBuffer << '"' << endl;
-// if (stringBuffer != "Finally, message #6\n")
-// {
-// cout << "Test failed." << endl;
-// return -1;
-// }
cout << "Server sending back to client" << endl;
port->WriteString ("So long, and thanks for all the text.");
SLEEP (5);
Modified: gearbox/trunk/src/flexiport/udpport.cpp
===================================================================
--- gearbox/trunk/src/flexiport/udpport.cpp 2008-10-15 05:54:06 UTC (rev 321)
+++ gearbox/trunk/src/flexiport/udpport.cpp 2008-10-15 07:03:32 UTC (rev 322)
@@ -145,7 +145,7 @@
OpenSender ();
OpenReceiver ();
- SetPortBlockingFlag ();
+ SetSocketBlockingFlag ();
_open = true;
if (_debug >= 2)
@@ -178,16 +178,38 @@
if (_debug >= 2)
cerr << "UDPPort::" << __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 (_recvSock, reinterpret_cast<char*> (buffer), count, 0);
+#else
+ receivedBytes = recv (_recvSock, 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 (_recvSock, reinterpret_cast<char*> (buffer), count, 0);
+ receivedBytes = recv (_recvSock, reinterpret_cast<char*> (buffer), count, 0);
#else
- receivedBytes = recv (_recvSock, buffer, count, 0);
+ receivedBytes = recv (_recvSock, 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 (_recvSock, reinterpret_cast<char*> (buffer), count, 0);
+#else
+ receivedBytes = recv (_recvSock, buffer, count, 0);
+#endif
+ }
+ // If first call doesn't return a timeout, fall through to the result/error checking below
+ }
if (_debug >= 2)
cerr << "UDPPort::" << __func__ << "() Read " << receivedBytes << " bytes" << endl;
@@ -333,9 +355,6 @@
CheckPort (true);
- if (!IsDataAvailable ())
- return 0;
-
#if defined (WIN32)
unsigned long bytesAvailable = 0;
if (ioctlsocket (_recvSock, FIONREAD, &bytesAvailable) < 0)
@@ -513,7 +532,7 @@
void UDPPort::SetTimeout (Timeout timeout)
{
_timeout = timeout;
- SetPortBlockingFlag ();
+ SetSocketBlockingFlag ();
}
void UDPPort::SetCanRead (bool canRead)
@@ -847,6 +866,15 @@
// Checks if data is available, waiting for the timeout if none is available immediatly
UDPPort::WaitStatus UDPPort::WaitForDataOrTimeout (void)
{
+ if (IsDataAvailable ())
+ {
+ if (_debug >= 2)
+ cerr << "UDPPort::" << __func__ << "() Found data available immediately." << endl;
+ return DATA_AVAILABLE;
+ }
+ if (_debug >= 2)
+ cerr << "UDPPort::" << __func__ << "() No data available immediately, will wait." << endl;
+
fd_set fdSet;
struct timeval tv, *tvPtr = NULL;
@@ -868,46 +896,65 @@
}
else if (result == 0)
{
- if (_debug >= 3)
+ if (_debug >= 2)
cerr << "UDPPort::" << __func__ << "() Timed out" << endl;
// Time out
return TIMED_OUT;
}
if (_debug >= 2)
- cerr << "UDPPort::" << __func__ << "() Found data waiting" << endl;
+ cerr << "UDPPort::" << __func__ << "() Found data after waiting" << endl;
return DATA_AVAILABLE;
}
// Checks if data is available right now
bool UDPPort::IsDataAvailable (void)
{
- fd_set fdSet;
- struct timeval tv;
+ if (_debug >= 3)
+ cerr << "UDPPort::" << __func__ << "() Checking if data is available immediately." << endl;
- FD_ZERO (&fdSet);
- FD_SET (_recvSock, &fdSet);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- int result = select (_recvSock + 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 (_recvSock, &buffer, 1, MSG_PEEK);
+#else
+ receivedBytes = recv (_recvSock, reinterpret_cast<void*> (&buffer), 1, MSG_PEEK);
+#endif
+ if (receivedBytes > 0)
{
- stringstream ss;
- ss << "UDPPort::" << __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 << "UDPPort::" << __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 << "UDPPort::" << __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
@@ -957,7 +1004,7 @@
throw PortException ("Cannot write to read-only port.");
}
-void UDPPort::SetPortBlockingFlag (void)
+void UDPPort::SetSocketBlockingFlag (void)
{
if (_timeout._sec == -1)
{
@@ -985,35 +1032,35 @@
int flags;
// Receive socket
- if ((flags = fcntl (_recvSock, F_GETFD)) < 0)
+ if ((flags = fcntl (_recvSock, F_GETFL)) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(_recvSock, F_GETFD) error: (" << ErrNo () <<
+ ss << "UDPPort::" << __func__ << "() fcntl(_recvSock, F_GETFL) error: (" << ErrNo () <<
") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
flags &= ~O_NONBLOCK;
- if (fcntl (_recvSock, F_SETFD, flags) < 0)
+ if (fcntl (_recvSock, F_SETFL, flags) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(_recvSock, F_SETFD) error: (" << ErrNo () <<
+ ss << "UDPPort::" << __func__ << "() fcntl(_recvSock, F_SETFL) error: (" << ErrNo () <<
") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
// Send socket
- if ((flags = fcntl (_sendSock, F_GETFD)) < 0)
+ if ((flags = fcntl (_sendSock, F_GETFL)) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_GETFD) error: (" << ErrNo () <<
+ ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_GETFL) error: (" << ErrNo () <<
") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
flags &= ~O_NONBLOCK;
- if (fcntl (_sendSock, F_SETFD, flags) < 0)
+ if (fcntl (_sendSock, F_SETFL, flags) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_SETFD) error: (" << ErrNo () <<
+ ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_SETFL) error: (" << ErrNo () <<
") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
@@ -1045,35 +1092,35 @@
int flags;
// Receive socket
- if ((flags = fcntl (_recvSock, F_GETFD)) < 0)
+ if ((flags = fcntl (_recvSock, F_GETFL)) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(F_GETFD) error: (" << ErrNo () << ") " <<
+ ss << "UDPPort::" << __func__ << "() fcntl(F_GETFL) error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
flags |= O_NONBLOCK;
- if (fcntl (_recvSock, F_SETFD, flags) < 0)
+ if (fcntl (_recvSock, F_SETFL, flags) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(F_SETFD) error: (" << ErrNo () << ") " <<
+ ss << "UDPPort::" << __func__ << "() fcntl(F_SETFL) error: (" << ErrNo () << ") " <<
StrError (ErrNo ());
throw PortException (ss.str ());
}
// Send socket
- if ((flags = fcntl (_sendSock, F_GETFD)) < 0)
+ if ((flags = fcntl (_sendSock, F_GETFL)) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_GETFD) error: (" << ErrNo () <<
+ ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_GETFL) error: (" << ErrNo () <<
") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
flags |= O_NONBLOCK;
- if (fcntl (_sendSock, F_SETFD, flags) < 0)
+ if (fcntl (_sendSock, F_SETFL, flags) < 0)
{
stringstream ss;
- ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_SETFD) error: (" << ErrNo () <<
+ ss << "UDPPort::" << __func__ << "() fcntl(_sendSock, F_SETFL) error: (" << ErrNo () <<
") " << StrError (ErrNo ());
throw PortException (ss.str ());
}
Modified: gearbox/trunk/src/flexiport/udpport.h
===================================================================
--- gearbox/trunk/src/flexiport/udpport.h 2008-10-15 05:54:06 UTC (rev 321)
+++ gearbox/trunk/src/flexiport/udpport.h 2008-10-15 07:03:32 UTC (rev 322)
@@ -140,7 +140,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.
|