mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 08:31:43 +02:00
poll() support (tested on Solaris and Linux)
array delete policy for SharedPtr
This commit is contained in:
@@ -39,7 +39,13 @@
|
||||
#include "Poco/Timestamp.h"
|
||||
#include <algorithm>
|
||||
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring>
|
||||
|
||||
#if defined(POCO_HAVE_FD_POLL)
|
||||
#include "Poco/SharedPtr.h"
|
||||
#include <poll.h>
|
||||
typedef Poco::SharedPtr<pollfd,
|
||||
Poco::ReferenceCounter,
|
||||
Poco::ReleaseArrayPolicy<pollfd> > SharedPollArray;
|
||||
#endif
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
@@ -85,6 +91,96 @@ Socket::~Socket()
|
||||
}
|
||||
|
||||
|
||||
int Socket::poll(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout)
|
||||
{
|
||||
#if !defined(POCO_HAVE_FD_POLL)
|
||||
throw NotImplementedException("poll() is only available on POSIX platforms");
|
||||
#else
|
||||
nfds_t nfd = readList.size() + writeList.size() + exceptList.size();
|
||||
if (0 == nfd) return 0;
|
||||
|
||||
SharedPollArray pPollArr = new pollfd[nfd];
|
||||
|
||||
int idx = 0;
|
||||
for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it)
|
||||
{
|
||||
pPollArr[idx].fd = int(it->sockfd());
|
||||
pPollArr[idx++].events |= POLLIN;
|
||||
}
|
||||
|
||||
SocketList::iterator begR = readList.begin();
|
||||
SocketList::iterator endR = readList.end();
|
||||
for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it)
|
||||
{
|
||||
SocketList::iterator pos = std::find(begR, endR, *it);
|
||||
if (pos != endR)
|
||||
{
|
||||
pPollArr[pos-begR].events |= POLLOUT;
|
||||
--nfd;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPollArr[idx].fd = int(it->sockfd());
|
||||
pPollArr[idx++].events |= POLLOUT;
|
||||
}
|
||||
}
|
||||
|
||||
SocketList::iterator begW = writeList.begin();
|
||||
SocketList::iterator endW = writeList.end();
|
||||
for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it)
|
||||
{
|
||||
SocketList::iterator pos = std::find(begR, endR, *it);
|
||||
if (pos != endR) --nfd;
|
||||
else
|
||||
{
|
||||
SocketList::iterator pos = std::find(begW, endW, *it);
|
||||
if (pos != endW) --nfd;
|
||||
else pPollArr[idx++].fd = int(it->sockfd());
|
||||
}
|
||||
}
|
||||
|
||||
Poco::Timespan remainingTime(timeout);
|
||||
int rc;
|
||||
do
|
||||
{
|
||||
Poco::Timestamp start;
|
||||
rc = ::poll(pPollArr, nfd, timeout.totalMilliseconds());
|
||||
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
|
||||
{
|
||||
Poco::Timestamp end;
|
||||
Poco::Timespan waited = end - start;
|
||||
if (waited < remainingTime) remainingTime -= waited;
|
||||
else remainingTime = 0;
|
||||
}
|
||||
}
|
||||
while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
|
||||
if (rc < 0) SocketImpl::error();
|
||||
|
||||
SocketList readyReadList;
|
||||
SocketList readyWriteList;
|
||||
SocketList readyExceptList;
|
||||
|
||||
int count = 0;
|
||||
SocketList::iterator begE = exceptList.begin();
|
||||
SocketList::iterator endE = exceptList.end();
|
||||
for (int idx = 0; idx < nfd; ++idx)
|
||||
{
|
||||
SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd));
|
||||
if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt);
|
||||
slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd));
|
||||
if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt);
|
||||
slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd));
|
||||
if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt);
|
||||
}
|
||||
std::swap(readList, readyReadList);
|
||||
std::swap(writeList, readyWriteList);
|
||||
std::swap(exceptList, readyExceptList);
|
||||
|
||||
return readList.size() + writeList.size() + exceptList.size();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout)
|
||||
{
|
||||
fd_set fdRead;
|
||||
|
@@ -40,6 +40,9 @@
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring>
|
||||
#if defined(POCO_HAVE_FD_POLL)
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
|
||||
using Poco::IOException;
|
||||
@@ -335,9 +338,37 @@ int SocketImpl::available()
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
|
||||
{
|
||||
#if defined(POCO_HAVE_FD_POLL)
|
||||
|
||||
pollfd pollBuf;
|
||||
|
||||
std::memset(&pollBuf, 0, sizeof(pollfd));
|
||||
pollBuf.fd = _sockfd;
|
||||
if (mode & SELECT_READ) pollBuf.events |= POLLIN;
|
||||
if (mode & SELECT_WRITE) pollBuf.events |= POLLOUT;
|
||||
|
||||
Poco::Timespan remainingTime(timeout);
|
||||
int rc;
|
||||
do
|
||||
{
|
||||
Poco::Timestamp start;
|
||||
rc = ::poll(&pollBuf, 1, remainingTime.totalMilliseconds());
|
||||
|
||||
if (rc < 0 && lastError() == POCO_EINTR)
|
||||
{
|
||||
Poco::Timestamp end;
|
||||
Poco::Timespan waited = end - start;
|
||||
if (waited < remainingTime)
|
||||
remainingTime -= waited;
|
||||
else
|
||||
remainingTime = 0;
|
||||
}
|
||||
} while (rc < 0 && lastError() == POCO_EINTR);
|
||||
|
||||
#else
|
||||
|
||||
fd_set fdRead;
|
||||
fd_set fdWrite;
|
||||
fd_set fdExcept;
|
||||
@@ -376,6 +407,9 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
|
||||
}
|
||||
}
|
||||
while (rc < 0 && lastError() == POCO_EINTR);
|
||||
|
||||
#endif
|
||||
|
||||
if (rc < 0) error();
|
||||
return rc > 0;
|
||||
}
|
||||
|
@@ -121,7 +121,11 @@ void SocketReactor::run()
|
||||
{
|
||||
onIdle();
|
||||
}
|
||||
#if defined(POCO_HAVE_FD_POLL)
|
||||
else if (Socket::poll(readable, writable, except, _timeout))
|
||||
#else
|
||||
else if (Socket::select(readable, writable, except, _timeout))
|
||||
#endif
|
||||
{
|
||||
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
|
||||
dispatch(*it, _pReadableNotification);
|
||||
|
Reference in New Issue
Block a user