I have implemented my own lock-free ringbuffer for multiple producers multiple consumers using vector. Can you guys help me review to see if there are any problems and ways to improve?
Explanation:
Each producer runs on its own thread and will use Push() to enter its item into the RingBuffer.
Each consumer runs on its own thread and has its own unique number. When consumer TryRead(), it will enter its unique number.
RingBuffer will keep track of the last position each consumer read in std::vector<long> mReadIdxVec
If mReadIdxVec[consumer unique number] >= mMaxReadIdx, TryRead() will return a nullptr.
Question:
Within Push() method, will it be a problem if multiple producers on different threads call this line mVector[index] = pMsg; at the same time?
Can this code be improved further? Any comments are welcomed!
RingBuffer.h
#ifndef __RING_BUFFER_H_
#define __RING_BUFFER_H_
#include <atomic>
class RingBuffer
{
private:
std::vector<Foo *> mVector;
std::atomic<long> mWriteIdx{0}; //mWriteIdx will not exceed 2,000,000,000
std::atomic<long> mMaxReadIdx{0}; //mMaxReadIdx will not exceed 2,000,000,000
std::vector<long> mReadIdxVec;
public:
RingBuffer(int pNumOfConsumers);
void Push(Foo *);
Foo * TryRead(const int&);
};
#endif
RingBuffer.cc
#include "RingBuffer.h"
#define MAX_SIZE 1000
RingBuffer::RingBuffer(int pNumOfConsumers)
{
mVector.reserve(MAX_SIZE);
mVector.assign(MAX_SIZE, nullptr);
mReadIdxVec.assign(pNumOfConsumers, 0);
}
void RingBuffer::Push(Foo * pMsg)
{
if(!pMsg) return;
long writeIdx = mWriteIdx++;
long index = writeIdx % MAX_SIZE;
if(writeIdx >= MAX_SIZE) delete mVector[index];
mVector[index] = pMsg;
mMaxReadIdx++;
}
Foo * RingBuffer::TryRead(const int& pConsumer)
{
if(mReadIdxVec[pConsumer] >= mMaxReadIdx) return nullptr;
long index = mReadIdxVec[pConsumer] % MAX_SIZE;
mReadIdxVec[pConsumer]++;
return mVector[index];
}
Fooin your code. Who's that and where did he come from? For future reference, please take a look at the How to get the best value out of Code Review - Asking Questions. \$\endgroup\$