VirtualAllocBuffer.h
// VirtualAllocBuffer.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2011
#ifndef Ceda_cxMessage_VirtualAllocBuffer_H
#define Ceda_cxMessage_VirtualAllocBuffer_H
#include "cxMessage.h"
#include "Ceda/cxUtils/xvector.h"
#include <string.h>
/*
We use a single buffer allocated with VirtualAlloc to ensure it is a whole number of
4kB pages. This seems appropriate given that async reads/writes will lock whole pages.
VirtualAlloc allows for a distinction between reserving and commiting memory. This is
particularly beneficial on x64 platforms where we typically have much more virtual memory
(8TB) than physical memory (maybe 8GB).
Under "normal circumstances" we reserve NormalReserveBufferSize, and of that only
commit NormalCommitBufferSize. We would expect most messages to be smaller than
NormalCommitBufferSize.
Buffer management policy
------------------------
Parameters:
// The following are all a multiple of the page size
// We require NormalCommitBufferSize <= NormalReserveBufferSize <= MaxMsgSize
ssize_t NormalCommitBufferSize;
ssize_t NormalReserveBufferSize;
ssize_t MaxMsgSize;
ssize_t NumMsgsUntilBackToNormalBufferSize;
- If a message is received with size in (NormalCommitBufferSize,NormalReserveBufferSize]
we can easily commit additional pages if necessary without needing to reallocate memory
from scratch.
- If a message is received with size in (NormalReserveBufferSize,MaxMsgSize] we can reallocate
an entirely new buffer for that message. In such cases we reserve and commit to a size
rounded up to a multiple of the page size.
- In general we keep track of what has been currently committed/reserved and where possible
try to read the next message without any reallocations.
- After NumMsgsUntilBackToNormalBufferSize messages have been received in a row that
don't exceed NormalCommitBufferSize the commit/reserve sizes are returned back to the
normal conditions. [or is a timeout more appropriate?]
IDEA: This policy can be implemented in a class VirtualAllocBuffer that represents the buffer
for us. It may also be possible for this class to make use of pooled memory buffers if that
is appropriate.
*/
namespace ceda
{
/*
VirtualAllocBuffer is assumed to have the following functions:
resize()
size()
data()
ReallocAndMove()
*/
// for now...
typedef xvector<octet_t> VirtualAllocBuffer;
/*
Reallocate b to have size equal to newSize.
Copy the bytes in the range [offset, offset+count) back to position 0.
Used by both the MsgReader and MsgWriter
*/
inline void ReallocAndMove(VirtualAllocBuffer& b, ssize_t newSize, ssize_t offset, ssize_t count)
{
cxAssert(0 <= newSize);
cxAssert(0 <= offset);
cxAssert(0 <= count);
cxAssert(offset + count <= b.size());
cxAssert(count <= newSize);
VirtualAllocBuffer copy(newSize);
memcpy(copy.data(), b.data()+offset, count);
b.swap(copy);
}
} // namespace ceda
#endif // include guard