Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Sync with upstream.

  • Loading branch information...
commit 28cb253453340c7db1d1466b8e76a932b83bf66d 2 parents a2697a5 + 73a3a5e
Philip Prindeville authored
Showing with 662 additions and 40 deletions.
  1. +130 −18 Foundation/include/Poco/FIFOBuffer.h
  2. +9 −9 Foundation/include/Poco/FPEnvironment_DUMMY.h
  3. +107 −0 Foundation/testsuite/src/CoreTest.cpp
  4. +1 −0  Foundation/testsuite/src/CoreTest.h
  5. +4 −0 Net/Net_CE_vs90.vcproj
  6. +2 −0  Net/Net_vs100.vcxproj
  7. +6 −0 Net/Net_vs100.vcxproj.filters
  8. +2 −0  Net/Net_vs110.vcxproj
  9. +6 −0 Net/Net_vs110.vcxproj.filters
  10. +4 −0 Net/Net_vs71.vcproj
  11. +4 −0 Net/Net_vs80.vcproj
  12. +4 −0 Net/Net_vs90.vcproj
  13. +2 −0  Net/Net_x64_vs100.vcxproj
  14. +6 −0 Net/Net_x64_vs100.vcxproj.filters
  15. +2 −0  Net/Net_x64_vs110.vcxproj
  16. +6 −0 Net/Net_x64_vs110.vcxproj.filters
  17. +4 −0 Net/Net_x64_vs90.vcproj
  18. +201 −0 Net/include/Poco/Net/ParallelSocketAcceptor.h
  19. +105 −0 Net/include/Poco/Net/ParallelSocketReactor.h
  20. +3 −2 Net/include/Poco/Net/SocketAcceptor.h
  21. +3 −0  Net/include/Poco/Net/SocketDefs.h
  22. +7 −7 Net/src/SocketImpl.cpp
  23. +41 −2 Net/testsuite/src/SocketReactorTest.cpp
  24. +1 −0  Net/testsuite/src/SocketReactorTest.h
  25. +1 −1  PageCompiler/File2Page/Makefile
  26. +1 −1  PageCompiler/Makefile
148 Foundation/include/Poco/FIFOBuffer.h
View
@@ -56,8 +56,11 @@ class BasicFIFOBuffer
/// A simple buffer class with support for re-entrant,
/// FIFO-style read/write operations, as well as (optional)
/// empty/non-empty/full (i.e. writable/readable) transition
- /// notifications. Buffer size, as well as amount of unread data
- /// and available space introspections are supported as well.
+ /// notifications. Buffer can be flagged with end-of-file and
+ /// error flags, which renders it un-readable/writable.
+ ///
+ /// Buffer size, as well as amount of unread data and
+ /// available space introspections are supported as well.
///
/// This class is useful anywhere where a FIFO functionality
/// is needed.
@@ -93,7 +96,9 @@ class BasicFIFOBuffer
_buffer(size),
_begin(0),
_used(0),
- _notify(notify)
+ _notify(notify),
+ _eof(false),
+ _error(false)
/// Creates the FIFOBuffer.
{
}
@@ -102,7 +107,9 @@ class BasicFIFOBuffer
_buffer(pBuffer, size),
_begin(0),
_used(0),
- _notify(notify)
+ _notify(notify),
+ _eof(false),
+ _error(false)
/// Creates the FIFOBuffer.
{
}
@@ -111,7 +118,9 @@ class BasicFIFOBuffer
_buffer(pBuffer, size),
_begin(0),
_used(size),
- _notify(notify)
+ _notify(notify),
+ _eof(false),
+ _error(false)
/// Creates the FIFOBuffer.
{
}
@@ -154,6 +163,7 @@ class BasicFIFOBuffer
{
if (0 == length) return 0;
Mutex::ScopedLock lock(_mutex);
+ if (!isReadable()) return 0;
if (length > _used) length = _used;
std::memcpy(pBuffer, _buffer.begin() + _begin, length * sizeof(T));
return length;
@@ -172,6 +182,7 @@ class BasicFIFOBuffer
/// supplied buffer.
{
Mutex::ScopedLock lock(_mutex);
+ if (!isReadable()) return 0;
if (0 == length || length > _used) length = _used;
buffer.resize(length);
return peek(buffer.begin(), length);
@@ -185,10 +196,9 @@ class BasicFIFOBuffer
///
/// Returns the reference to the buffer.
{
+ if (0 == length) return 0;
Mutex::ScopedLock lock(_mutex);
-
- if (0 == _used) return 0;
-
+ if (!isReadable()) return 0;
std::size_t usedBefore = _used;
std::size_t readLen = peek(pBuffer, length);
poco_assert (_used >= readLen);
@@ -210,9 +220,7 @@ class BasicFIFOBuffer
/// Returns the reference to the buffer.
{
Mutex::ScopedLock lock(_mutex);
-
- if (0 == _used) return 0;
-
+ if (!isReadable()) return 0;
std::size_t usedBefore = _used;
std::size_t readLen = peek(buffer, length);
poco_assert (_used >= readLen);
@@ -236,10 +244,12 @@ class BasicFIFOBuffer
///
/// Returns the length of data written.
{
- if (0 == length || isFull()) return 0;
+ if (0 == length) return 0;
Mutex::ScopedLock lock(_mutex);
-
+
+ if (!isWritable()) return 0;
+
if (_buffer.size() - (_begin + _used) < length)
{
std::memmove(_buffer.begin(), _buffer.begin() + _begin, _used);
@@ -268,11 +278,14 @@ class BasicFIFOBuffer
///
/// Returns the length of data written.
{
- if (isFull()) return 0;
+ std::size_t len = length;
- if (0 == length || length > buffer.size()) length = buffer.size();
+ if (len == 0)
+ len = buffer.size();
+ else if (len > buffer.size())
+ len = buffer.size();
- return write(buffer.begin(), length);
+ return write(buffer.begin(), len);
}
std::size_t size() const
@@ -298,6 +311,8 @@ class BasicFIFOBuffer
/// If length is zero or greater than buffer current
/// content length, buffer is emptied.
{
+ Mutex::ScopedLock lock(_mutex);
+
std::size_t usedBefore = _used;
if (0 == length || length >= _used)
@@ -317,11 +332,19 @@ class BasicFIFOBuffer
{
poco_check_ptr(ptr);
if (0 == length) return;
+
+ Mutex::ScopedLock lock(_mutex);
+
if (length > available())
throw Poco::InvalidAccessException("Cannot extend buffer.");
+
+ if (!isWritable())
+ throw Poco::InvalidAccessException("Buffer not writable.");
std::memcpy(&_buffer[_used], ptr, length);
- advance(length);
+ std::size_t usedBefore = _used;
+ _used += length;
+ if (_notify) notify(usedBefore);
}
void advance(std::size_t length)
@@ -329,8 +352,13 @@ class BasicFIFOBuffer
/// Should be called AFTER the data
/// was copied into the buffer.
{
+ Mutex::ScopedLock lock(_mutex);
+
if (length > available())
throw Poco::InvalidAccessException("Cannot extend buffer.");
+
+ if (!isWritable())
+ throw Poco::InvalidAccessException("Buffer not writable.");
std::size_t usedBefore = _used;
_used += length;
@@ -357,6 +385,7 @@ class BasicFIFOBuffer
/// Throws InvalidAccessException if index is larger than
/// the last valid (used) buffer position.
{
+ Mutex::ScopedLock lock(_mutex);
if (index >= _used)
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
@@ -368,6 +397,7 @@ class BasicFIFOBuffer
/// Throws InvalidAccessException if index is larger than
/// the last valid (used) buffer position.
{
+ Mutex::ScopedLock lock(_mutex);
if (index >= _used)
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
@@ -379,9 +409,75 @@ class BasicFIFOBuffer
{
return _buffer;
}
+
+ void setError(bool error = true)
+ /// Sets the error flag on the buffer and empties it.
+ /// If notifications are enabled, they will be triggered
+ /// if appropriate.
+ ///
+ /// Setting error flag to true prevents reading and writing
+ /// to the buffer; to re-enable FIFOBuffer for reading/writing,
+ /// the error flag must be set to false.
+ {
+ if (error)
+ {
+ bool f = false;
+ Mutex::ScopedLock lock(_mutex);
+ if (error && isReadable() && _notify) readable.notify(this, f);
+ if (error && isWritable() && _notify) writable.notify(this, f);
+ _error = error;
+ _used = 0;
+ }
+ else
+ {
+ bool t = true;
+ Mutex::ScopedLock lock(_mutex);
+ _error = false;
+ if (_notify && !_eof) writable.notify(this, t);
+ }
+ }
+
+ bool isValid() const
+ /// Returns true if error flag is not set on the buffer,
+ /// otherwise returns false.
+ {
+ return !_error;
+ }
+
+ void setEOF(bool eof = true)
+ /// Sets end-of-file flag on the buffer.
+ ///
+ /// Setting EOF flag to true prevents writing to the
+ /// buffer; reading from the buffer will still be
+ /// allowed until all data present in the buffer at the
+ /// EOF set time is drained. After that, to re-enable
+ /// FIFOBuffer for reading/writing, EOF must be
+ /// set to false.
+ ///
+ /// Setting EOF flag to false clears EOF state if it
+ /// was previously set. If EOF was not set, it has no
+ /// effect.
+ {
+ Mutex::ScopedLock lock(_mutex);
+ bool flag = !eof;
+ if (_notify) writable.notify(this, flag);
+ _eof = eof;
+ }
+
+ bool hasEOF() const
+ /// Returns true if EOF flag has been set.
+ {
+ return _eof;
+ }
+
+ bool isEOF() const
+ /// Returns true if EOF flag has been set and buffer is empty.
+ {
+ return isEmpty() && _eof;
+ }
bool isEmpty() const
- /// Returns true is buffer is empty, flase otherwise.
+ /// Returns true is buffer is empty, false otherwise.
{
return 0 == _used;
}
@@ -392,6 +488,20 @@ class BasicFIFOBuffer
return size() == _used;
}
+ bool isReadable() const
+ /// Returns true if buffer contains data and is not
+ /// in error state.
+ {
+ return !isEmpty() && isValid();
+ }
+
+ bool isWritable() const
+ /// Returns true if buffer is not full and is not
+ /// in error state.
+ {
+ return !isFull() && isValid() && !_eof;
+ }
+
void setNotify(bool notify = true)
/// Enables/disables notifications.
{
@@ -428,6 +538,8 @@ class BasicFIFOBuffer
std::size_t _used;
bool _notify;
mutable Mutex _mutex;
+ bool _eof;
+ bool _error;
};
18 Foundation/include/Poco/FPEnvironment_DUMMY.h
View
@@ -42,7 +42,7 @@
#include "Poco/Foundation.h"
-#include <math.h>
+#include <cmath>
namespace Poco {
@@ -95,49 +95,49 @@ class Foundation_API FPEnvironmentImpl
//
inline bool FPEnvironmentImpl::isInfiniteImpl(float value)
{
- return isinf(value) != 0;
+ return std::isinf(value) != 0;
}
inline bool FPEnvironmentImpl::isInfiniteImpl(double value)
{
- return isinf(value) != 0;
+ return std::isinf(value) != 0;
}
inline bool FPEnvironmentImpl::isInfiniteImpl(long double value)
{
- return isinf((double) value) != 0;
+ return std::isinf((double) value) != 0;
}
inline bool FPEnvironmentImpl::isNaNImpl(float value)
{
- return isnan(value) != 0;
+ return std::isnan(value) != 0;
}
inline bool FPEnvironmentImpl::isNaNImpl(double value)
{
- return isnan(value) != 0;
+ return std::isnan(value) != 0;
}
inline bool FPEnvironmentImpl::isNaNImpl(long double value)
{
- return isnan((double) value) != 0;
+ return std::isnan((double) value) != 0;
}
inline float FPEnvironmentImpl::copySignImpl(float target, float source)
{
- return copysignf(target, source);
+ return std::copysignf(target, source);
}
inline double FPEnvironmentImpl::copySignImpl(double target, double source)
{
- return copysign(target, source);
+ return std::copysign(target, source);
}
107 Foundation/testsuite/src/CoreTest.cpp
View
@@ -284,6 +284,112 @@ void CoreTest::testBuffer()
}
+void CoreTest::testFIFOBufferEOFAndError()
+{
+ typedef FIFOBuffer::Type T;
+
+ FIFOBuffer f(20, true);
+
+ assert (f.isEmpty());
+ assert (!f.isFull());
+
+ Buffer<T> b(10);
+ std::vector<T> v;
+
+ f.readable += delegate(this, &CoreTest::onReadable);
+ f.writable += delegate(this, &CoreTest::onWritable);
+
+ for (T c = '0'; c < '0' + 10; ++c)
+ v.push_back(c);
+
+ std::memcpy(b.begin(), &v[0], sizeof(T) * v.size());
+ assert(0 == _notToReadable);
+ assert(0 == _readableToNot);
+ assert (10 == f.write(b));
+ assert(1 == _notToReadable);
+ assert(0 == _readableToNot);
+ assert (20 == f.size());
+ assert (10 == f.used());
+ assert (!f.isEmpty());
+ f.setEOF();
+ assert(0 == _notToWritable);
+ assert(1 == _writableToNot);
+ assert (f.hasEOF());
+ assert (!f.isEOF());
+ assert(1 == _notToReadable);
+ assert(0 == _readableToNot);
+ assert (20 == f.size());
+ assert (10 == f.used());
+ assert (0 == f.write(b));
+ assert (!f.isEmpty());
+ assert (5 == f.read(b, 5));
+ assert(1 == _notToReadable);
+ assert(0 == _readableToNot);
+ assert (f.hasEOF());
+ assert (!f.isEOF());
+ assert (5 == f.read(b, 5));
+ assert(1 == _notToReadable);
+ assert(1 == _readableToNot);
+ assert (f.hasEOF());
+ assert (f.isEOF());
+ assert(0 == _notToWritable);
+ assert(1 == _writableToNot);
+
+ f.setEOF(false);
+ assert (!f.hasEOF());
+ assert (!f.isEOF());
+ assert(1 == _notToWritable);
+ assert(1 == _writableToNot);
+ assert(1 == _notToReadable);
+ assert(1 == _readableToNot);
+
+ assert (5 == f.write(b));
+ assert(1 == _notToWritable);
+ assert(1 == _writableToNot);
+ assert(2 == _notToReadable);
+ assert(1 == _readableToNot);
+ assert (20 == f.size());
+ assert (5 == f.used());
+ f.setError();
+ assert (0 == f.write(b));
+
+ try
+ {
+ f.copy(b.begin(), 5);
+ fail ("must throw InvalidAccessException");
+ }
+ catch (InvalidAccessException&) { }
+
+ try
+ {
+ f.advance(5);
+ fail ("must throw InvalidAccessException");
+ }
+ catch (InvalidAccessException&) { }
+
+ assert(1 == _notToWritable);
+ assert(2 == _writableToNot);
+ assert(2 == _notToReadable);
+ assert(2 == _readableToNot);
+ assert (20 == f.size());
+ assert (0 == f.used());
+ f.setError(false);
+ assert(2 == _notToWritable);
+ assert(2 == _writableToNot);
+ assert(2 == _notToReadable);
+ assert(2 == _readableToNot);
+ assert (20 == f.size());
+ assert (0 == f.used());
+ assert (5 == f.write(b));
+ assert(2 == _notToWritable);
+ assert(2 == _writableToNot);
+ assert(3 == _notToReadable);
+ assert(2 == _readableToNot);
+ assert (20 == f.size());
+ assert (5 == f.used());
+}
+
+
void CoreTest::testFIFOBufferChar()
{
typedef FIFOBuffer::Type T;
@@ -964,6 +1070,7 @@ CppUnit::Test* CoreTest::suite()
CppUnit_addTest(pSuite, CoreTest, testBuffer);
CppUnit_addTest(pSuite, CoreTest, testFIFOBufferChar);
CppUnit_addTest(pSuite, CoreTest, testFIFOBufferInt);
+ CppUnit_addTest(pSuite, CoreTest, testFIFOBufferEOFAndError);
CppUnit_addTest(pSuite, CoreTest, testAtomicCounter);
CppUnit_addTest(pSuite, CoreTest, testNullable);
CppUnit_addTest(pSuite, CoreTest, testAscii);
1  Foundation/testsuite/src/CoreTest.h
View
@@ -54,6 +54,7 @@ class CoreTest: public CppUnit::TestCase
void testBuffer();
void testFIFOBufferChar();
void testFIFOBufferInt();
+ void testFIFOBufferEOFAndError();
void testAtomicCounter();
void testNullable();
void testAscii();
4 Net/Net_CE_vs90.vcproj
View
@@ -804,6 +804,8 @@
<File
RelativePath=".\include\Poco\Net\SocketAcceptor.h"/>
<File
+ RelativePath=".\include\Poco\Net\ParallelSocketAcceptor.h"/>
+ <File
RelativePath=".\include\Poco\Net\SocketConnector.h"/>
<File
RelativePath=".\include\Poco\Net\SocketNotification.h"/>
@@ -811,6 +813,8 @@
RelativePath=".\include\Poco\Net\SocketNotifier.h"/>
<File
RelativePath=".\include\Poco\Net\SocketReactor.h"/>
+ <File
+ RelativePath=".\include\Poco\Net\ParallelSocketReactor.h"/>
</Filter>
<Filter
Name="Source Files">
2  Net/Net_vs100.vcxproj
View
@@ -273,6 +273,8 @@
<ClInclude Include="include\Poco\Net\Net.h" />
<ClInclude Include="include\Poco\Net\NetException.h" />
<ClInclude Include="include\Poco\Net\NetworkInterface.h" />
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h" />
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h" />
<ClInclude Include="include\Poco\Net\SocketAddress.h" />
<ClInclude Include="include\Poco\Net\SocketDefs.h" />
<ClInclude Include="include\Poco\Net\DatagramSocket.h" />
6 Net/Net_vs100.vcxproj.filters
View
@@ -414,6 +414,12 @@
<ClInclude Include="include\Poco\Net\WebSocketImpl.h">
<Filter>WebSocket\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\DNS.cpp">
2  Net/Net_vs110.vcxproj
View
@@ -347,10 +347,12 @@
<ClInclude Include="include\Poco\Net\FTPClientSession.h"/>
<ClInclude Include="include\Poco\Net\FTPStreamFactory.h"/>
<ClInclude Include="include\Poco\Net\SocketAcceptor.h"/>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h"/>
<ClInclude Include="include\Poco\Net\SocketConnector.h"/>
<ClInclude Include="include\Poco\Net\SocketNotification.h"/>
<ClInclude Include="include\Poco\Net\SocketNotifier.h"/>
<ClInclude Include="include\Poco\Net\SocketReactor.h"/>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h"/>
<ClInclude Include="include\Poco\Net\MailMessage.h"/>
<ClInclude Include="include\Poco\Net\MailRecipient.h"/>
<ClInclude Include="include\Poco\Net\MailStream.h"/>
6 Net/Net_vs110.vcxproj.filters
View
@@ -351,6 +351,9 @@
<ClInclude Include="include\Poco\Net\SocketAcceptor.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
<ClInclude Include="include\Poco\Net\SocketConnector.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
@@ -363,6 +366,9 @@
<ClInclude Include="include\Poco\Net\SocketReactor.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
<ClInclude Include="include\Poco\Net\MailMessage.h">
<Filter>Mail\Header Files</Filter>
</ClInclude>
4 Net/Net_vs71.vcproj
View
@@ -736,6 +736,8 @@
<File
RelativePath=".\include\Poco\Net\SocketAcceptor.h"/>
<File
+ RelativePath=".\include\Poco\Net\ParallelSocketAcceptor.h"/>
+ <File
RelativePath=".\include\Poco\Net\SocketConnector.h"/>
<File
RelativePath=".\include\Poco\Net\SocketNotification.h"/>
@@ -743,6 +745,8 @@
RelativePath=".\include\Poco\Net\SocketNotifier.h"/>
<File
RelativePath=".\include\Poco\Net\SocketReactor.h"/>
+ <File
+ RelativePath=".\include\Poco\Net\ParallelSocketReactor.h"/>
</Filter>
<Filter
Name="Source Files">
4 Net/Net_vs80.vcproj
View
@@ -757,6 +757,8 @@
<File
RelativePath=".\include\Poco\Net\SocketAcceptor.h"/>
<File
+ RelativePath=".\include\Poco\Net\ParallelSocketAcceptor.h"/>
+ <File
RelativePath=".\include\Poco\Net\SocketConnector.h"/>
<File
RelativePath=".\include\Poco\Net\SocketNotification.h"/>
@@ -764,6 +766,8 @@
RelativePath=".\include\Poco\Net\SocketNotifier.h"/>
<File
RelativePath=".\include\Poco\Net\SocketReactor.h"/>
+ <File
+ RelativePath=".\include\Poco\Net\ParallelSocketReactor.h"/>
</Filter>
<Filter
Name="Source Files">
4 Net/Net_vs90.vcproj
View
@@ -756,6 +756,8 @@
<File
RelativePath=".\include\Poco\Net\SocketAcceptor.h"/>
<File
+ RelativePath=".\include\Poco\Net\ParallelSocketAcceptor.h"/>
+ <File
RelativePath=".\include\Poco\Net\SocketConnector.h"/>
<File
RelativePath=".\include\Poco\Net\SocketNotification.h"/>
@@ -763,6 +765,8 @@
RelativePath=".\include\Poco\Net\SocketNotifier.h"/>
<File
RelativePath=".\include\Poco\Net\SocketReactor.h"/>
+ <File
+ RelativePath=".\include\Poco\Net\ParallelSocketReactor.h"/>
</Filter>
<Filter
Name="Source Files">
2  Net/Net_x64_vs100.vcxproj
View
@@ -339,10 +339,12 @@
<ClInclude Include="include\Poco\Net\FTPClientSession.h"/>
<ClInclude Include="include\Poco\Net\FTPStreamFactory.h"/>
<ClInclude Include="include\Poco\Net\SocketAcceptor.h"/>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h"/>
<ClInclude Include="include\Poco\Net\SocketConnector.h"/>
<ClInclude Include="include\Poco\Net\SocketNotification.h"/>
<ClInclude Include="include\Poco\Net\SocketNotifier.h"/>
<ClInclude Include="include\Poco\Net\SocketReactor.h"/>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h"/>
<ClInclude Include="include\Poco\Net\MailMessage.h"/>
<ClInclude Include="include\Poco\Net\MailRecipient.h"/>
<ClInclude Include="include\Poco\Net\MailStream.h"/>
6 Net/Net_x64_vs100.vcxproj.filters
View
@@ -351,6 +351,9 @@
<ClInclude Include="include\Poco\Net\SocketAcceptor.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
<ClInclude Include="include\Poco\Net\SocketConnector.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
@@ -363,6 +366,9 @@
<ClInclude Include="include\Poco\Net\SocketReactor.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
<ClInclude Include="include\Poco\Net\MailMessage.h">
<Filter>Mail\Header Files</Filter>
</ClInclude>
2  Net/Net_x64_vs110.vcxproj
View
@@ -345,10 +345,12 @@
<ClInclude Include="include\Poco\Net\FTPClientSession.h"/>
<ClInclude Include="include\Poco\Net\FTPStreamFactory.h"/>
<ClInclude Include="include\Poco\Net\SocketAcceptor.h"/>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h"/>
<ClInclude Include="include\Poco\Net\SocketConnector.h"/>
<ClInclude Include="include\Poco\Net\SocketNotification.h"/>
<ClInclude Include="include\Poco\Net\SocketNotifier.h"/>
<ClInclude Include="include\Poco\Net\SocketReactor.h"/>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h"/>
<ClInclude Include="include\Poco\Net\MailMessage.h"/>
<ClInclude Include="include\Poco\Net\MailRecipient.h"/>
<ClInclude Include="include\Poco\Net\MailStream.h"/>
6 Net/Net_x64_vs110.vcxproj.filters
View
@@ -351,6 +351,9 @@
<ClInclude Include="include\Poco\Net\SocketAcceptor.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketAcceptor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
<ClInclude Include="include\Poco\Net\SocketConnector.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
@@ -363,6 +366,9 @@
<ClInclude Include="include\Poco\Net\SocketReactor.h">
<Filter>Reactor\Header Files</Filter>
</ClInclude>
+ <ClInclude Include="include\Poco\Net\ParallelSocketReactor.h">
+ <Filter>Reactor\Header Files</Filter>
+ </ClInclude>
<ClInclude Include="include\Poco\Net\MailMessage.h">
<Filter>Mail\Header Files</Filter>
</ClInclude>
4 Net/Net_x64_vs90.vcproj
View
@@ -761,6 +761,8 @@
<File
RelativePath=".\include\Poco\Net\SocketAcceptor.h"/>
<File
+ RelativePath=".\include\Poco\Net\ParallelSocketAcceptor.h"/>
+ <File
RelativePath=".\include\Poco\Net\SocketConnector.h"/>
<File
RelativePath=".\include\Poco\Net\SocketNotification.h"/>
@@ -768,6 +770,8 @@
RelativePath=".\include\Poco\Net\SocketNotifier.h"/>
<File
RelativePath=".\include\Poco\Net\SocketReactor.h"/>
+ <File
+ RelativePath=".\include\Poco\Net\ParallelSocketReactor.h"/>
</Filter>
<Filter
Name="Source Files">
201 Net/include/Poco/Net/ParallelSocketAcceptor.h
View
@@ -0,0 +1,201 @@
+//
+// ParallelSocketAcceptor.h
+//
+// $Id: //poco/1.4/Net/include/Poco/Net/ParallelSocketAcceptor.h#1 $
+//
+// Library: Net
+// Package: Reactor
+// Module: ParallelSocketAcceptor
+//
+// Definition of the ParallelSocketAcceptor class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Net_ParallelSocketAcceptor_INCLUDED
+#define Net_ParallelSocketAcceptor_INCLUDED
+
+
+#include "Poco/Net/ParallelSocketReactor.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/Environment.h"
+#include "Poco/NObserver.h"
+#include "Poco/SharedPtr.h"
+#include <vector>
+
+
+using Poco::Net::Socket;
+using Poco::Net::SocketReactor;
+using Poco::Net::ServerSocket;
+using Poco::Net::StreamSocket;
+using Poco::NObserver;
+using Poco::AutoPtr;
+
+
+namespace Poco {
+namespace Net {
+
+
+template <class ServiceHandler, class SR>
+class ParallelSocketAcceptor
+ /// This class implements the Acceptor part of the Acceptor-Connector design pattern.
+ /// Only the difference from single-threaded version is documented here, For full
+ /// description see Poco::Net::SocketAcceptor documentation.
+ ///
+ /// This is a multi-threaded version of SocketAcceptor, it differs from the
+ /// single-threaded version in number of reactors (defaulting to number of processors)
+ /// that can be specified at construction time and is rotated in a round-robin fashion
+ /// by event handler. See ParallelSocketAcceptor::onAccept and
+ /// ParallelSocketAcceptor::createServiceHandler documentation and implementation for
+ /// details.
+{
+public:
+ typedef Poco::Net::ParallelSocketReactor<SR> ParallelReactor;
+
+ explicit ParallelSocketAcceptor(ServerSocket& socket,
+ unsigned threads = Poco::Environment::processorCount()):
+ _socket(socket),
+ _pReactor(0),
+ _threads(threads),
+ _next(0)
+ /// Creates a ParallelSocketAcceptor using the given ServerSocket,
+ /// sets number of threads and populates the reactors vector.
+ {
+ init();
+ }
+
+ ParallelSocketAcceptor(ServerSocket& socket,
+ SocketReactor& reactor,
+ unsigned threads = Poco::Environment::processorCount()):
+ _socket(socket),
+ _pReactor(0),
+ _threads(threads),
+ _next(0)
+ /// Creates a ParallelSocketAcceptor using the given ServerSocket, sets the
+ /// number of threads, populates the reactors vector and registers itself
+ /// with the given SocketReactor.
+ {
+ init();
+ registerAcceptor(reactor);
+ }
+
+ ~ParallelSocketAcceptor()
+ /// Destroys the ParallelSocketAcceptor.
+ {
+ unregisterAcceptor();
+ }
+
+ void registerAcceptor(SocketReactor& reactor)
+ /// Registers the ParallelSocketAcceptor with a SocketReactor.
+ ///
+ /// A subclass can override this and, for example, also register
+ /// an event handler for a timeout event.
+ ///
+ /// The overriding method must call the baseclass implementation first.
+ {
+ _pReactor = &reactor;
+ _pReactor->addEventHandler(_socket,
+ Poco::Observer<ParallelSocketAcceptor,
+ ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept));
+ }
+
+ void unregisterAcceptor()
+ /// Unregisters the ParallelSocketAcceptor.
+ ///
+ /// A subclass can override this and, for example, also unregister
+ /// its event handler for a timeout event.
+ ///
+ /// The overriding method must call the baseclass implementation first.
+ {
+ _pReactor->removeEventHandler(_socket,
+ Poco::Observer<ParallelSocketAcceptor,
+ ReadableNotification>(*this, &ParallelSocketAcceptor::onAccept));
+ }
+
+ void onAccept(ReadableNotification* pNotification)
+ /// Accepts connection and creates event handler.
+ {
+ pNotification->release();
+ StreamSocket sock = _socket.acceptConnection();
+ createServiceHandler(sock);
+ }
+
+protected:
+ ServiceHandler* createServiceHandler(StreamSocket& socket)
+ /// Create and initialize a new ServiceHandler instance.
+ ///
+ /// Subclasses can override this method.
+ {
+ std::size_t next = _next++;
+ if (_next == _reactors.size()) _next = 0;
+ return new ServiceHandler(socket, *_reactors[next]);
+ }
+
+ SocketReactor* reactor()
+ /// Returns a pointer to the SocketReactor where
+ /// this SocketAcceptor is registered.
+ ///
+ /// The pointer may be null.
+ {
+ return _pReactor;
+ }
+
+ Socket& socket()
+ /// Returns a reference to the SocketAcceptor's socket.
+ {
+ return _socket;
+ }
+
+ void init()
+ /// Populates the reactors vector.
+ {
+ poco_assert (_threads > 0);
+
+ for (unsigned i = 0; i < _threads; ++i)
+ _reactors.push_back(new ParallelReactor);
+ }
+
+private:
+ typedef std::vector<typename ParallelReactor::Ptr> ReactorVec;
+
+ ParallelSocketAcceptor();
+ ParallelSocketAcceptor(const ParallelSocketAcceptor&);
+ ParallelSocketAcceptor& operator = (const ParallelSocketAcceptor&);
+
+ ServerSocket _socket;
+ SocketReactor* _pReactor;
+ unsigned _threads;
+ ReactorVec _reactors;
+ std::size_t _next;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ParallelSocketAcceptor_INCLUDED
105 Net/include/Poco/Net/ParallelSocketReactor.h
View
@@ -0,0 +1,105 @@
+//
+// ParallelSocketReactor.h
+//
+// $Id: //poco/1.4/Net/include/Poco/Net/ParallelSocketReactor.h#1 $
+//
+// Library: Net
+// Package: Reactor
+// Module: ParallelSocketReactor
+//
+// Definition of the ParallelSocketReactor class.
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+#ifndef Net_ParallelSocketReactor_INCLUDED
+#define Net_ParallelSocketReactor_INCLUDED
+
+
+#include "Poco/Net/SocketReactor.h"
+#include "Poco/Net/SocketNotification.h"
+#include "Poco/Net/StreamSocket.h"
+#include "Poco/Net/ServerSocket.h"
+#include "Poco/NObserver.h"
+#include "Poco/Thread.h"
+#include "Poco/SharedPtr.h"
+
+
+using Poco::Net::Socket;
+using Poco::Net::SocketReactor;
+using Poco::Net::ReadableNotification;
+using Poco::Net::ShutdownNotification;
+using Poco::Net::ServerSocket;
+using Poco::Net::StreamSocket;
+using Poco::NObserver;
+using Poco::AutoPtr;
+using Poco::Thread;
+
+
+namespace Poco {
+namespace Net {
+
+
+template <class SR>
+class ParallelSocketReactor: public SR
+{
+public:
+ typedef Poco::SharedPtr<ParallelSocketReactor> Ptr;
+
+ ParallelSocketReactor()
+ {
+ _thread.start(*this);
+ }
+
+ ParallelSocketReactor(const Poco::Timespan& timeout):
+ SR(timeout)
+ {
+ _thread.start(*this);
+ }
+
+ ~ParallelSocketReactor()
+ {
+ this->stop();
+ _thread.join();
+ }
+
+protected:
+ void onIdle()
+ {
+ SR::onIdle();
+ Poco::Thread::yield();
+ }
+
+private:
+ Poco::Thread _thread;
+};
+
+
+} } // namespace Poco::Net
+
+
+#endif // Net_ParallelSocketReactor_INCLUDED
5 Net/include/Poco/Net/SocketAcceptor.h
View
@@ -92,14 +92,14 @@ class SocketAcceptor
explicit SocketAcceptor(ServerSocket& socket):
_socket(socket),
_pReactor(0)
- /// Creates an SocketAcceptor, using the given ServerSocket.
+ /// Creates a SocketAcceptor, using the given ServerSocket.
{
}
SocketAcceptor(ServerSocket& socket, SocketReactor& reactor):
_socket(socket),
_pReactor(0)
- /// Creates an SocketAcceptor, using the given ServerSocket.
+ /// Creates a SocketAcceptor, using the given ServerSocket.
/// The SocketAcceptor registers itself with the given SocketReactor.
{
registerAcceptor(reactor);
@@ -138,6 +138,7 @@ class SocketAcceptor
}
void onAccept(ReadableNotification* pNotification)
+ /// Accepts connection and creates event handler.
{
pNotification->release();
StreamSocket sock = _socket.acceptConnection();
3  Net/include/Poco/Net/SocketDefs.h
View
@@ -40,6 +40,9 @@
#define Net_SocketDefs_INCLUDED
+#define POCO_ENOERR 0
+
+
#if defined(POCO_OS_FAMILY_WINDOWS)
#include "Poco/UnWindows.h"
#include <winsock2.h>
14 Net/src/SocketImpl.cpp
View
@@ -518,7 +518,7 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode)
FD_SET(sockfd, &fdExcept);
}
Poco::Timespan remainingTime(timeout);
- int errorCode;
+ int errorCode = POCO_ENOERR;
int rc;
do
{
@@ -890,13 +890,12 @@ void SocketImpl::setBlocking(bool flag)
int arg = flag ? 0 : 1;
ioctl(FIONBIO, arg);
#else
- int arg = fcntl(F_GETFL);
- long flags = arg & ~O_NONBLOCK;
- if (!flag)
- flags |= O_NONBLOCK;
- (void) fcntl(F_SETFL, flags);
+ int arg = fcntl(F_GETFL);
+ long flags = arg & ~O_NONBLOCK;
+ if (!flag) flags |= O_NONBLOCK;
+ (void) fcntl(F_SETFL, flags);
#endif
- _blocking = flag;
+ _blocking = flag;
}
@@ -999,6 +998,7 @@ void SocketImpl::error(int code, const std::string& arg)
{
switch (code)
{
+ case POCO_ENOERR: return;
case POCO_ESYSNOTREADY:
throw NetException("Net subsystem not ready", code);
case POCO_ENOTINIT:
43 Net/testsuite/src/SocketReactorTest.cpp
View
@@ -37,6 +37,7 @@
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketConnector.h"
#include "Poco/Net/SocketAcceptor.h"
+#include "Poco/Net/ParallelSocketAcceptor.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/SocketAddress.h"
@@ -48,6 +49,7 @@
using Poco::Net::SocketReactor;
using Poco::Net::SocketConnector;
using Poco::Net::SocketAcceptor;
+using Poco::Net::ParallelSocketAcceptor;
using Poco::Net::StreamSocket;
using Poco::Net::ServerSocket;
using Poco::Net::SocketAddress;
@@ -142,8 +144,8 @@ namespace
checkReadableObserverCount(1);
_reactor.removeEventHandler(_socket, Observer<ClientServiceHandler, ReadableNotification>(*this, &ClientServiceHandler::onReadable));
checkReadableObserverCount(0);
- _reactor.stop();
- _data = _str.str();
+ if (_once || _data.size() >= 3072) _reactor.stop();
+ _data += _str.str();
delete this;
}
}
@@ -175,6 +177,11 @@ namespace
return _data;
}
+ static void resetData()
+ {
+ _data.clear();
+ }
+
static bool timeout()
{
return _timeout;
@@ -205,6 +212,11 @@ namespace
return _timeoutError;
}
+ static void setOnce(bool once = true)
+ {
+ _once = once;
+ }
+
private:
void checkReadableObserverCount(std::size_t oro)
{
@@ -245,6 +257,7 @@ namespace
static bool _timeoutError;
static bool _timeout;
static bool _closeOnTimeout;
+ static bool _once;
};
@@ -254,6 +267,7 @@ namespace
bool ClientServiceHandler::_timeoutError = false;
bool ClientServiceHandler::_timeout = false;
bool ClientServiceHandler::_closeOnTimeout = false;
+ bool ClientServiceHandler::_once = false;
class FailConnector: public SocketConnector<ClientServiceHandler>
@@ -322,6 +336,8 @@ void SocketReactorTest::testSocketReactor()
SocketAcceptor<EchoServiceHandler> acceptor(ss, reactor);
SocketAddress sa("localhost", ss.address().port());
SocketConnector<ClientServiceHandler> connector(sa, reactor);
+ ClientServiceHandler::setOnce(true);
+ ClientServiceHandler::resetData();
reactor.run();
std::string data(ClientServiceHandler::data());
assert (data.size() == 1024);
@@ -331,6 +347,28 @@ void SocketReactorTest::testSocketReactor()
}
+void SocketReactorTest::testParallelSocketReactor()
+{
+ SocketAddress ssa;
+ ServerSocket ss(ssa);
+ SocketReactor reactor;
+ ParallelSocketAcceptor<EchoServiceHandler, SocketReactor> acceptor(ss, reactor);
+ SocketAddress sa("localhost", ss.address().port());
+ SocketConnector<ClientServiceHandler> connector1(sa, reactor);
+ SocketConnector<ClientServiceHandler> connector2(sa, reactor);
+ SocketConnector<ClientServiceHandler> connector3(sa, reactor);
+ SocketConnector<ClientServiceHandler> connector4(sa, reactor);
+ ClientServiceHandler::setOnce(false);
+ ClientServiceHandler::resetData();
+ reactor.run();
+ std::string data(ClientServiceHandler::data());
+ assert (data.size() == 4096);
+ assert (!ClientServiceHandler::readableError());
+ assert (!ClientServiceHandler::writableError());
+ assert (!ClientServiceHandler::timeoutError());
+}
+
+
void SocketReactorTest::testSocketConnectorFail()
{
SocketReactor reactor;
@@ -375,6 +413,7 @@ CppUnit::Test* SocketReactorTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("SocketReactorTest");
CppUnit_addTest(pSuite, SocketReactorTest, testSocketReactor);
+ CppUnit_addTest(pSuite, SocketReactorTest, testParallelSocketReactor);
CppUnit_addTest(pSuite, SocketReactorTest, testSocketConnectorFail);
CppUnit_addTest(pSuite, SocketReactorTest, testSocketConnectorTimeout);
1  Net/testsuite/src/SocketReactorTest.h
View
@@ -47,6 +47,7 @@ class SocketReactorTest: public CppUnit::TestCase
~SocketReactorTest();
void testSocketReactor();
+ void testParallelSocketReactor();
void testSocketConnectorFail();
void testSocketConnectorTimeout();
2  PageCompiler/File2Page/Makefile
View
@@ -16,6 +16,6 @@ endif
target = f2cpsp
target_version = 1
-target_libs = PocoUtil PocoJSON PocoXML PocoFoundation
+target_libs = PocoUtil PocoXML PocoJSON PocoFoundation
include $(POCO_BASE)/build/rules/exec
2  PageCompiler/Makefile
View
@@ -18,6 +18,6 @@ endif
target = cpspc
target_version = 1
-target_libs = PocoNet PocoUtil PocoJSON PocoXML PocoFoundation
+target_libs = PocoNet PocoUtil PocoXML PocoJSON PocoFoundation
include $(POCO_BASE)/build/rules/exec
Please sign in to comment.
Something went wrong with that request. Please try again.