mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 00:07:59 +02:00
Buffer and FIFOBuffer performance optimizations
This commit is contained in:
@@ -60,6 +60,7 @@ class Buffer
|
|||||||
public:
|
public:
|
||||||
Buffer(std::size_t size):
|
Buffer(std::size_t size):
|
||||||
_size(size),
|
_size(size),
|
||||||
|
_used(size),
|
||||||
_ptr(new T[size])
|
_ptr(new T[size])
|
||||||
/// Creates and allocates the Buffer.
|
/// Creates and allocates the Buffer.
|
||||||
{
|
{
|
||||||
@@ -79,21 +80,30 @@ public:
|
|||||||
{
|
{
|
||||||
poco_assert(newSize);
|
poco_assert(newSize);
|
||||||
|
|
||||||
T* ptr = new T[newSize];
|
if (newSize > _size)
|
||||||
if (preserveContent)
|
|
||||||
{
|
{
|
||||||
std::size_t n = newSize > _size ? _size : newSize;
|
T* ptr = new T[newSize];
|
||||||
std::memcpy(ptr, _ptr, n);
|
if (preserveContent)
|
||||||
|
std::memcpy(ptr, _ptr, newSize);
|
||||||
|
|
||||||
|
delete [] _ptr;
|
||||||
|
_ptr = ptr;
|
||||||
|
_size = newSize;
|
||||||
}
|
}
|
||||||
delete [] _ptr;
|
|
||||||
_ptr = ptr;
|
_used = newSize;
|
||||||
_size = newSize;
|
}
|
||||||
|
|
||||||
|
std::size_t allocated() const
|
||||||
|
/// Returns the allocated memory size.
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t size() const
|
std::size_t size() const
|
||||||
/// Returns the size of the buffer.
|
/// Returns the used size of the buffer.
|
||||||
{
|
{
|
||||||
return _size;
|
return _used;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* begin()
|
T* begin()
|
||||||
@@ -111,25 +121,25 @@ public:
|
|||||||
T* end()
|
T* end()
|
||||||
/// Returns a pointer to end of the buffer.
|
/// Returns a pointer to end of the buffer.
|
||||||
{
|
{
|
||||||
return _ptr + _size;
|
return _ptr + _used;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* end() const
|
const T* end() const
|
||||||
/// Returns a pointer to the end of the buffer.
|
/// Returns a pointer to the end of the buffer.
|
||||||
{
|
{
|
||||||
return _ptr + _size;
|
return _ptr + _used;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator [] (std::size_t index)
|
T& operator [] (std::size_t index)
|
||||||
{
|
{
|
||||||
poco_assert (index < _size);
|
poco_assert (index < _used);
|
||||||
|
|
||||||
return _ptr[index];
|
return _ptr[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator [] (std::size_t index) const
|
const T& operator [] (std::size_t index) const
|
||||||
{
|
{
|
||||||
poco_assert (index < _size);
|
poco_assert (index < _used);
|
||||||
|
|
||||||
return _ptr[index];
|
return _ptr[index];
|
||||||
}
|
}
|
||||||
@@ -140,6 +150,7 @@ private:
|
|||||||
Buffer& operator = (const Buffer&);
|
Buffer& operator = (const Buffer&);
|
||||||
|
|
||||||
std::size_t _size;
|
std::size_t _size;
|
||||||
|
std::size_t _used;
|
||||||
T* _ptr;
|
T* _ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -89,6 +89,7 @@ public:
|
|||||||
|
|
||||||
FIFOBuffer(std::size_t size, bool notify = false):
|
FIFOBuffer(std::size_t size, bool notify = false):
|
||||||
_buffer(size),
|
_buffer(size),
|
||||||
|
_begin(0),
|
||||||
_used(0),
|
_used(0),
|
||||||
_notify(notify)
|
_notify(notify)
|
||||||
/// Creates and allocates the FIFOBuffer.
|
/// Creates and allocates the FIFOBuffer.
|
||||||
@@ -124,7 +125,7 @@ public:
|
|||||||
/// Peeks into the data currently in the FIFO
|
/// Peeks into the data currently in the FIFO
|
||||||
/// without actually extracting it.
|
/// without actually extracting it.
|
||||||
/// Resizes the supplied buffer to the size of
|
/// Resizes the supplied buffer to the size of
|
||||||
///.data written to it. If length is not
|
/// data written to it. If length is not
|
||||||
/// supplied by the caller, the current FIFO used length
|
/// supplied by the caller, the current FIFO used length
|
||||||
/// is substituted for it.
|
/// is substituted for it.
|
||||||
///
|
///
|
||||||
@@ -135,7 +136,7 @@ public:
|
|||||||
if (0 == length || length > _used) length = _used;
|
if (0 == length || length > _used) length = _used;
|
||||||
poco_assert (length <= _buffer.size());
|
poco_assert (length <= _buffer.size());
|
||||||
buffer.resize(length);
|
buffer.resize(length);
|
||||||
std::memcpy(buffer.begin(), _buffer.begin(), length * sizeof(T));
|
std::memcpy(buffer.begin(), _buffer.begin() + _begin, length * sizeof(T));
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@@ -144,7 +145,7 @@ public:
|
|||||||
/// Copies the data currently in the FIFO
|
/// Copies the data currently in the FIFO
|
||||||
/// into the supplied buffer.
|
/// into the supplied buffer.
|
||||||
/// Resizes the supplied buffer to the size of
|
/// Resizes the supplied buffer to the size of
|
||||||
///.data written to it.
|
/// data written to it.
|
||||||
///
|
///
|
||||||
/// Returns the reference to the buffer.
|
/// Returns the reference to the buffer.
|
||||||
{
|
{
|
||||||
@@ -156,9 +157,9 @@ public:
|
|||||||
std::size_t readLen = peek(buffer, length);
|
std::size_t readLen = peek(buffer, length);
|
||||||
poco_assert (_used >= readLen);
|
poco_assert (_used >= readLen);
|
||||||
_used -= readLen;
|
_used -= readLen;
|
||||||
if (_used > 0)
|
if (0 == _used) _begin = 0;
|
||||||
std::memmove(_buffer.begin(), _buffer.begin() + usedBefore - _used, _used);
|
else _begin += length;
|
||||||
|
|
||||||
if (_notify) notify(usedBefore);
|
if (_notify) notify(usedBefore);
|
||||||
|
|
||||||
return readLen;
|
return readLen;
|
||||||
@@ -174,11 +175,16 @@ public:
|
|||||||
{
|
{
|
||||||
Mutex::ScopedLock lock(_mutex);
|
Mutex::ScopedLock lock(_mutex);
|
||||||
|
|
||||||
poco_assert (_used <= _buffer.size());
|
if (_buffer.size() - (_begin + _used) < buffer.size())
|
||||||
|
{
|
||||||
|
std::memmove(_buffer.begin(), _buffer.begin() + _begin, _used);
|
||||||
|
_begin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t usedBefore = _used;
|
std::size_t usedBefore = _used;
|
||||||
std::size_t available = _buffer.size() - _used;
|
std::size_t available = _buffer.size() - _used - _begin;
|
||||||
std::size_t len = buffer.size() > available ? available : buffer.size();
|
std::size_t len = buffer.size() > available ? available : buffer.size();
|
||||||
std::memcpy(_buffer.begin() + _used, buffer.begin(), len * sizeof(T));
|
std::memcpy(_buffer.begin() + _begin + _used, buffer.begin(), len * sizeof(T));
|
||||||
_used += len;
|
_used += len;
|
||||||
poco_assert (_used <= _buffer.size());
|
poco_assert (_used <= _buffer.size());
|
||||||
if (_notify) notify(usedBefore);
|
if (_notify) notify(usedBefore);
|
||||||
@@ -212,7 +218,7 @@ public:
|
|||||||
if (index >= _used)
|
if (index >= _used)
|
||||||
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
|
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
|
||||||
|
|
||||||
return _buffer[index];
|
return _buffer[_begin + index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator [] (std::size_t index) const
|
const T& operator [] (std::size_t index) const
|
||||||
@@ -223,7 +229,7 @@ public:
|
|||||||
if (index >= _used)
|
if (index >= _used)
|
||||||
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
|
throw InvalidAccessException(format("Index out of bounds: %z (max index allowed: %z)", index, _used - 1));
|
||||||
|
|
||||||
return _buffer[index];
|
return _buffer[_begin + index];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEmpty() const
|
bool isEmpty() const
|
||||||
@@ -251,6 +257,7 @@ private:
|
|||||||
FIFOBuffer& operator = (const FIFOBuffer&);
|
FIFOBuffer& operator = (const FIFOBuffer&);
|
||||||
|
|
||||||
Buffer<T> _buffer;
|
Buffer<T> _buffer;
|
||||||
|
std::size_t _begin;
|
||||||
std::size_t _used;
|
std::size_t _used;
|
||||||
bool _notify;
|
bool _notify;
|
||||||
mutable Mutex _mutex;
|
mutable Mutex _mutex;
|
||||||
|
@@ -197,6 +197,8 @@ void CoreTest::testBuffer()
|
|||||||
{
|
{
|
||||||
std::size_t s = 10;
|
std::size_t s = 10;
|
||||||
Buffer<int> b(s);
|
Buffer<int> b(s);
|
||||||
|
assert (b.size() == s);
|
||||||
|
assert (b.allocated() == s);
|
||||||
std::vector<int> v;
|
std::vector<int> v;
|
||||||
for (int i = 0; i < s; ++i)
|
for (int i = 0; i < s; ++i)
|
||||||
v.push_back(i);
|
v.push_back(i);
|
||||||
@@ -207,6 +209,26 @@ void CoreTest::testBuffer()
|
|||||||
for (int i = 0; i < s; ++i)
|
for (int i = 0; i < s; ++i)
|
||||||
assert (b[i] == i);
|
assert (b[i] == i);
|
||||||
|
|
||||||
|
b.resize(s/2);
|
||||||
|
for (int i = 0; i < s/2; ++i)
|
||||||
|
assert (b[i] == i);
|
||||||
|
|
||||||
|
assert (b.size() == s/2);
|
||||||
|
assert (b.allocated() == s);
|
||||||
|
|
||||||
|
b.resize(s*2);
|
||||||
|
v.clear();
|
||||||
|
for (int i = 0; i < s*2; ++i)
|
||||||
|
v.push_back(i);
|
||||||
|
|
||||||
|
std::memcpy(b.begin(), &v[0], sizeof(int) * v.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < s*2; ++i)
|
||||||
|
assert (b[i] == i);
|
||||||
|
|
||||||
|
assert (b.size() == s*2);
|
||||||
|
assert (b.allocated() == s*2);
|
||||||
|
|
||||||
#if ENABLE_BUGCHECK_TEST
|
#if ENABLE_BUGCHECK_TEST
|
||||||
try { int i = b[s]; fail ("must fail"); }
|
try { int i = b[s]; fail ("must fail"); }
|
||||||
catch (Exception&) { }
|
catch (Exception&) { }
|
||||||
|
Reference in New Issue
Block a user