Fast ring buffer implementation based on mapping of two continuous
virtual ranges on one physical range
static const int PAGE_SIZE = 4096;
class RingBuffer
{
public:
RingBuffer(int bytesCapacity) :
m_bytesCapacity(bytesCapacity),
m_bufferPtr(NULL),
m_head(0),
m_tail(0)
{
assert(bytesCapacity > 0);
assert((bytesCapacity & (PAGE_SIZE - 1)) == 0);
ULONG_PTR toAllocate = bytesCapacity / PAGE_SIZE;
BOOL needContinue = FALSE;
m_hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, m_bytesCapacity, NULL);
while (1) {
m_bufferPtr = VirtualAlloc(NULL, m_bytesCapacity * 2, MEM_RESERVE, PAGE_READWRITE);
VirtualFree(m_bufferPtr, 0, MEM_RELEASE);
if (!MapViewOfFileEx(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, m_bytesCapacity, m_bufferPtr))
continue;
if (!MapViewOfFileEx(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, m_bytesCapacity, (BYTE*)m_bufferPtr + m_bytesCapacity))
continue;
break;
}
}
~RingBuffer()
{
if (m_bufferPtr) {
UnmapViewOfFile(m_bufferPtr);
UnmapViewOfFile((BYTE*)m_bufferPtr + m_bytesCapacity);
}
}
void Push(BYTE *b, DWORD sz)
{
memcpy((BYTE*)m_bufferPtr + m_tail, b, sz);
m_tail += sz;
m_tail %= m_bytesCapacity;
}
void Pop(BYTE *b, DWORD sz)
{
memcpy(b, (BYTE*)m_bufferPtr + m_head, sz);
m_head += sz;
m_head %= m_bytesCapacity;
}
int GetSize(void) const
{
return m_tail > m_head ? (m_tail - m_head) : (m_tail + m_bytesCapacity - m_head);
}
private:
HANDLE m_hMap;
LPVOID m_bufferPtr;
DWORD m_bytesCapacity;
DWORD m_head;
DWORD m_tail;
};
virtual ranges on one physical range
static const int PAGE_SIZE = 4096;
class RingBuffer
{
public:
RingBuffer(int bytesCapacity) :
m_bytesCapacity(bytesCapacity),
m_bufferPtr(NULL),
m_head(0),
m_tail(0)
{
assert(bytesCapacity > 0);
assert((bytesCapacity & (PAGE_SIZE - 1)) == 0);
ULONG_PTR toAllocate = bytesCapacity / PAGE_SIZE;
BOOL needContinue = FALSE;
m_hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0, m_bytesCapacity, NULL);
while (1) {
m_bufferPtr = VirtualAlloc(NULL, m_bytesCapacity * 2, MEM_RESERVE, PAGE_READWRITE);
VirtualFree(m_bufferPtr, 0, MEM_RELEASE);
if (!MapViewOfFileEx(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, m_bytesCapacity, m_bufferPtr))
continue;
if (!MapViewOfFileEx(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, m_bytesCapacity, (BYTE*)m_bufferPtr + m_bytesCapacity))
continue;
break;
}
}
~RingBuffer()
{
if (m_bufferPtr) {
UnmapViewOfFile(m_bufferPtr);
UnmapViewOfFile((BYTE*)m_bufferPtr + m_bytesCapacity);
}
}
void Push(BYTE *b, DWORD sz)
{
memcpy((BYTE*)m_bufferPtr + m_tail, b, sz);
m_tail += sz;
m_tail %= m_bytesCapacity;
}
void Pop(BYTE *b, DWORD sz)
{
memcpy(b, (BYTE*)m_bufferPtr + m_head, sz);
m_head += sz;
m_head %= m_bytesCapacity;
}
int GetSize(void) const
{
return m_tail > m_head ? (m_tail - m_head) : (m_tail + m_bytesCapacity - m_head);
}
private:
HANDLE m_hMap;
LPVOID m_bufferPtr;
DWORD m_bytesCapacity;
DWORD m_head;
DWORD m_tail;
};
No comments:
Post a Comment