Block+timeout CanRead/CanWrite/DataAvailable EzSockets methods.

A minor change to the code exposes the timeout parameter of `select()`, which was already in use for CanRead()/CanWrite(). The timeout parameter is used to block the current thread until data (for read) or space (for write) is available on the underlying socket.

A timeout of 0 suppresses any blocking (the original methods fix the timeout to 0).

The timeout value is supplied in milliseconds as an `unsigned int`; this is converted internally to the equivalent `timeval`.

An in-progress addition to my SextetStream input driver is implemented with non-blocking reads on a TCP socket. Without the block+timeout functionality, it must busy-wait for new input. Changing the reads to blocking works during a game but can cause the program to hang when exiting. The changes in this commit provide a solution to both issues without disrupting any existing code.
This commit is contained in:
Peter S. May
2015-04-23 12:50:28 -04:00
parent 55d58659c4
commit 79ee8c1c81
2 changed files with 43 additions and 6 deletions
+40 -6
View File
@@ -33,6 +33,16 @@
#define INVALID_SOCKET -1
#endif
// Returns a timeval set to the given number of milliseconds.
inline timeval timevalFromMs(unsigned int ms)
{
timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = (ms % 1000) * 1000;
return tv;
}
EzSockets::EzSockets()
{
MAXCON = 5;
@@ -185,12 +195,24 @@ bool EzSockets::connect(const std::string& host, unsigned short port)
return true;
}
inline bool checkCanRead(int sock, timeval& timeout)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET((unsigned)sock, &fds);
return select(sock+1, &fds, NULL, NULL, &timeout) > 0;
}
bool EzSockets::CanRead()
{
FD_ZERO(scks);
FD_SET((unsigned)sock, scks);
return checkCanRead(sock, *times);
}
return select(sock+1,scks,NULL,NULL,times) > 0;
bool EzSockets::CanRead(unsigned int msTimeout)
{
timeval tv = timevalFromMs(msTimeout);
return checkCanRead(sock, tv);
}
bool EzSockets::IsError()
@@ -208,12 +230,24 @@ bool EzSockets::IsError()
return true;
}
inline bool checkCanWrite(int sock, timeval& timeout)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET((unsigned)sock, &fds);
return select(sock+1, NULL, &fds, NULL, &timeout) > 0;
}
bool EzSockets::CanWrite()
{
FD_ZERO(scks);
FD_SET((unsigned)sock, scks);
return checkCanWrite(sock, *times);
}
return select(sock+1, NULL, scks, NULL, times) > 0;
bool EzSockets::CanWrite(unsigned int msTimeout)
{
timeval tv = timevalFromMs(msTimeout);
return checkCanWrite(sock, tv);
}
void EzSockets::update()