mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-13 02:22:57 +01:00
Socket::select and SocketReactor improvements
This commit is contained in:
parent
9b636a3fbd
commit
8e58146848
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Socket.h
|
||||
//
|
||||
// $Id: //poco/svn/Net/include/Poco/Net/Socket.h#3 $
|
||||
// $Id: //poco/1.3/Net/include/Poco/Net/Socket.h#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Sockets
|
||||
@ -129,6 +129,10 @@ public:
|
||||
/// * readList contains those sockets ready for reading,
|
||||
/// * writeList contains those sockets ready for writing,
|
||||
/// * exceptList contains those sockets with a pending error.
|
||||
///
|
||||
/// If the total number of sockets passed in readList, writeList and
|
||||
/// exceptList is zero, select() will return immediately and the
|
||||
/// return value will be 0.
|
||||
|
||||
bool poll(const Poco::Timespan& timeout, int mode) const;
|
||||
/// Determines the status of the socket, using a
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketNotification.h
|
||||
//
|
||||
// $Id: //poco/svn/Net/include/Poco/Net/SocketNotification.h#2 $
|
||||
// $Id: //poco/1.3/Net/include/Poco/Net/SocketNotification.h#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Reactor
|
||||
@ -128,6 +128,19 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Net_API IdleNotification: public SocketNotification
|
||||
/// This notification is sent when the SocketReactor does
|
||||
/// not have any sockets to react to.
|
||||
{
|
||||
public:
|
||||
IdleNotification(SocketReactor* pReactor);
|
||||
/// Creates the IdleNotification for the given SocketReactor.
|
||||
|
||||
~IdleNotification();
|
||||
/// Destroys the IdleNotification.
|
||||
};
|
||||
|
||||
|
||||
class Net_API ShutdownNotification: public SocketNotification
|
||||
/// This notification is sent when the SocketReactor is
|
||||
/// about to shut down.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketReactor.h
|
||||
//
|
||||
// $Id: //poco/svn/Net/include/Poco/Net/SocketReactor.h#2 $
|
||||
// $Id: //poco/1.3/Net/include/Poco/Net/SocketReactor.h#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Reactor
|
||||
@ -90,7 +90,8 @@ class Net_API SocketReactor: public Poco::Runnable
|
||||
/// If an event is detected, the corresponding event handler
|
||||
/// is invoked. There are five event types (and corresponding
|
||||
/// notification classes) defined: ReadableNotification, WritableNotification,
|
||||
/// ErrorNotification, TimeoutNotification and ShutdownNotification.
|
||||
/// ErrorNotification, TimeoutNotification, IdleNotification and
|
||||
/// ShutdownNotification.
|
||||
///
|
||||
/// The ReadableNotification will be dispatched if a socket becomes
|
||||
/// readable. The WritableNotification will be dispatched if a socket
|
||||
@ -100,9 +101,17 @@ class Net_API SocketReactor: public Poco::Runnable
|
||||
/// If the timeout expires and no event has occured, a
|
||||
/// TimeoutNotification will be dispatched to all event handlers
|
||||
/// registered for it. This is done in the onTimeout() method
|
||||
/// which can be overridded by subclasses to perform custom
|
||||
/// which can be overridden by subclasses to perform custom
|
||||
/// timeout processing.
|
||||
///
|
||||
/// If there are no sockets for the SocketReactor to pass to
|
||||
/// Socket::select(), an IdleNotification will be dispatched to
|
||||
/// all event handlers registered for it. This is done in the
|
||||
/// onIdle() method which can be overridden by subclasses
|
||||
/// to perform custom idle processing. Since onIdle() will be
|
||||
/// called repeatedly in a loop, it is recommended to do a
|
||||
/// short sleep or yield in the event handler.
|
||||
///
|
||||
/// Finally, when the SocketReactor is about to shut down (as a result
|
||||
/// of stop() being called), it dispatches a ShutdownNotification
|
||||
/// to all event handlers. This is done in the onShutdown() method
|
||||
@ -174,6 +183,13 @@ protected:
|
||||
/// Can be overridden by subclasses. The default implementation
|
||||
/// dispatches the TimeoutNotification and thus should be called by overriding
|
||||
/// implementations.
|
||||
|
||||
virtual void onIdle();
|
||||
/// Called if no sockets are available to call select() on.
|
||||
///
|
||||
/// Can be overridden by subclasses. The default implementation
|
||||
/// dispatches the IdleNotification and thus should be called by overriding
|
||||
/// implementations.
|
||||
|
||||
virtual void onShutdown();
|
||||
/// Called when the SocketReactor is about to terminate.
|
||||
@ -208,6 +224,7 @@ private:
|
||||
NotificationPtr _pWritableNotification;
|
||||
NotificationPtr _pErrorNotification;
|
||||
NotificationPtr _pTimeoutNotification;
|
||||
NotificationPtr _pIdleNotification;
|
||||
NotificationPtr _pShutdownNotification;
|
||||
Poco::FastMutex _mutex;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Socket.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/src/Socket.cpp#2 $
|
||||
// $Id: //poco/1.3/Net/src/Socket.cpp#4 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Sockets
|
||||
@ -112,6 +112,7 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce
|
||||
nfd = int(it->sockfd());
|
||||
FD_SET(it->sockfd(), &fdExcept);
|
||||
}
|
||||
if (nfd == 0) return 0;
|
||||
Poco::Timespan remainingTime(timeout);
|
||||
int rc;
|
||||
do
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketNotification.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/src/SocketNotification.cpp#2 $
|
||||
// $Id: //poco/1.3/Net/src/SocketNotification.cpp#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Reactor
|
||||
@ -102,6 +102,17 @@ TimeoutNotification::~TimeoutNotification()
|
||||
}
|
||||
|
||||
|
||||
IdleNotification::IdleNotification(SocketReactor* pReactor):
|
||||
SocketNotification(pReactor)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IdleNotification::~IdleNotification()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
|
||||
SocketNotification(pReactor)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketReactor.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/src/SocketReactor.cpp#2 $
|
||||
// $Id: //poco/1.3/Net/src/SocketReactor.cpp#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Reactor
|
||||
@ -38,6 +38,7 @@
|
||||
#include "Poco/Net/SocketNotification.h"
|
||||
#include "Poco/Net/SocketNotifier.h"
|
||||
#include "Poco/ErrorHandler.h"
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
@ -57,6 +58,7 @@ SocketReactor::SocketReactor():
|
||||
_pWritableNotification(new WritableNotification(this)),
|
||||
_pErrorNotification(new ErrorNotification(this)),
|
||||
_pTimeoutNotification(new TimeoutNotification(this)),
|
||||
_pIdleNotification(new IdleNotification(this)),
|
||||
_pShutdownNotification(new ShutdownNotification(this))
|
||||
{
|
||||
}
|
||||
@ -69,6 +71,7 @@ SocketReactor::SocketReactor(const Poco::Timespan& timeout):
|
||||
_pWritableNotification(new WritableNotification(this)),
|
||||
_pErrorNotification(new ErrorNotification(this)),
|
||||
_pTimeoutNotification(new TimeoutNotification(this)),
|
||||
_pIdleNotification(new IdleNotification(this)),
|
||||
_pShutdownNotification(new ShutdownNotification(this))
|
||||
{
|
||||
}
|
||||
@ -87,31 +90,60 @@ void SocketReactor::run()
|
||||
|
||||
while (!_stop)
|
||||
{
|
||||
readable.clear();
|
||||
writable.clear();
|
||||
except.clear();
|
||||
try
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
|
||||
readable.clear();
|
||||
writable.clear();
|
||||
except.clear();
|
||||
int nSockets = 0;
|
||||
{
|
||||
if (it->second->accepts(_pReadableNotification))
|
||||
readable.push_back(it->first);
|
||||
if (it->second->accepts(_pWritableNotification))
|
||||
writable.push_back(it->first);
|
||||
if (it->second->accepts(_pErrorNotification))
|
||||
except.push_back(it->first);
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
|
||||
{
|
||||
if (it->second->accepts(_pReadableNotification))
|
||||
{
|
||||
readable.push_back(it->first);
|
||||
nSockets++;
|
||||
}
|
||||
if (it->second->accepts(_pWritableNotification))
|
||||
{
|
||||
writable.push_back(it->first);
|
||||
nSockets++;
|
||||
}
|
||||
if (it->second->accepts(_pErrorNotification))
|
||||
{
|
||||
except.push_back(it->first);
|
||||
nSockets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nSockets == 0)
|
||||
{
|
||||
onIdle();
|
||||
}
|
||||
else if (Socket::select(readable, writable, except, _timeout))
|
||||
{
|
||||
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
|
||||
dispatch(*it, _pReadableNotification);
|
||||
for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it)
|
||||
dispatch(*it, _pWritableNotification);
|
||||
for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it)
|
||||
dispatch(*it, _pErrorNotification);
|
||||
}
|
||||
else onTimeout();
|
||||
}
|
||||
if (Socket::select(readable, writable, except, _timeout))
|
||||
catch (Exception& exc)
|
||||
{
|
||||
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
|
||||
dispatch(*it, _pReadableNotification);
|
||||
for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it)
|
||||
dispatch(*it, _pWritableNotification);
|
||||
for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it)
|
||||
dispatch(*it, _pErrorNotification);
|
||||
ErrorHandler::handle(exc);
|
||||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
ErrorHandler::handle(exc);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ErrorHandler::handle();
|
||||
}
|
||||
else onTimeout();
|
||||
}
|
||||
onShutdown();
|
||||
}
|
||||
@ -172,6 +204,12 @@ void SocketReactor::onTimeout()
|
||||
}
|
||||
|
||||
|
||||
void SocketReactor::onIdle()
|
||||
{
|
||||
dispatch(_pIdleNotification);
|
||||
}
|
||||
|
||||
|
||||
void SocketReactor::onShutdown()
|
||||
{
|
||||
dispatch(_pShutdownNotification);
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketTest.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/testsuite/src/SocketTest.cpp#2 $
|
||||
// $Id: //poco/1.3/Net/testsuite/src/SocketTest.cpp#2 $
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
@ -425,6 +425,18 @@ void SocketTest::testSelect2()
|
||||
}
|
||||
|
||||
|
||||
void SocketTest::testSelect3()
|
||||
{
|
||||
Socket::SocketList readList;
|
||||
Socket::SocketList writeList;
|
||||
Socket::SocketList exceptList;
|
||||
Timespan timeout(1000);
|
||||
|
||||
int rc = Socket::select(readList, writeList, exceptList, timeout);
|
||||
assert (rc == 0);
|
||||
}
|
||||
|
||||
|
||||
void SocketTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -452,6 +464,7 @@ CppUnit::Test* SocketTest::suite()
|
||||
CppUnit_addTest(pSuite, SocketTest, testOptions);
|
||||
CppUnit_addTest(pSuite, SocketTest, testSelect);
|
||||
CppUnit_addTest(pSuite, SocketTest, testSelect2);
|
||||
CppUnit_addTest(pSuite, SocketTest, testSelect3);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// SocketTest.h
|
||||
//
|
||||
// $Id: //poco/svn/Net/testsuite/src/SocketTest.h#2 $
|
||||
// $Id: //poco/1.3/Net/testsuite/src/SocketTest.h#2 $
|
||||
//
|
||||
// Definition of the SocketTest class.
|
||||
//
|
||||
@ -59,6 +59,7 @@ public:
|
||||
void testOptions();
|
||||
void testSelect();
|
||||
void testSelect2();
|
||||
void testSelect3();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
Loading…
Reference in New Issue
Block a user