循环无锁队列

inline void YieldThread(UINT k)
{
 if ((k & 63) == 63)
  ::YieldProcessor();
 else if ((k & 4095) == 4095)
  ::SwitchToThread();
}
template<class T>
class NLockQueue
{
 typedef T*         PTR;
 typedef volatile T*       VPTR;
public:
 NLockQueue(DWORD dwsize) :m_dwSize(dwsize)
 {
  ASSERT(dwsize > 0);
  m_pdata = new PTR[m_dwSize];
  ZeroMemory(m_pdata, m_dwSize*sizeof(PTR));
 }
 ~NLockQueue()
 {
  Clear();
 }
 void GetAllElements(PTR* ppelems)
 {
  memcpy(ppelems, m_pdata, m_dwSize*sizeof(PTR));
 }
 void PushBack(PTR val)
 {
  for (int i = 0; !TryPushBack(val); i++)
   YieldThread(i);
 }
 bool TryPushBack(PTR val)
 {
  DWORD seqPut = m_seqPut;
  if (!HasSpace()) return false;
  PTR* pelem = m_pdata + seqPut%m_dwSize;
  if (::InterlockedCompareExchangePointer((volatile LPVOID*)pelem, val, nullptr) == nullptr)
  {
   ::InterlockedCompareExchange(&m_seqPut, seqPut + 1, seqPut);
   return true;
  }
  ::InterlockedCompareExchange(&m_seqPut, seqPut + 1, seqPut);
  return false;
 }
 void PopFront(PTR* ppelem)
 {
  for (int i = 0; !TryPopFront(ppelem); i++)
   YieldThread();
 }
 bool TryPopFront(PTR* ppelem)
 {
  DWORD seqGet = m_seqGet;
  if (isEMPTY()) return false;
  PTR elem = *(m_pdata + seqGet%m_dwSize);
  if (elem)
  {
   PTR* pelem = m_pdata + seqGet%m_dwSize;
   if (::InterlockedCompareExchangePointer((volatile LPVOID*)pelem, nullptr, elem) == elem)
   {
    ::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet);
    *ppelem = elem;
    return true;
   }
  }
  ::InterlockedCompareExchange(&m_seqGet, seqGet + 1, seqGet);
  return false;
 }
 void Clear()
 {
  for (int i=(m_seqGet-1)%m_dwSize;i<(m_seqPut-1)%m_dwSize;i++)
  {
   delete *(m_pdata+i);
  }
  delete []m_pdata;
  m_pdata = nullptr;
  m_dwSize = 0;
  m_seqPut = 0;
  m_seqGet = 0;
 }
 private:
 bool HasSpace()
 {
  ASSERT((m_seqPut - m_seqGet) >= 0);
  return m_seqPut - m_seqGet < m_dwSize;
 }
 bool isEMPTY()
 {
  ASSERT((m_seqPut - m_seqGet) >= 0);
  return !(m_seqPut - m_seqGet);
 }
private:
 PTR* m_pdata;
 DWORD m_dwSize;
 _declspec(align(CACHE_LINE))
 volatile DWORD m_seqGet = 0;
 volatile DWORD m_seqPut = 0;
};

你可能感兴趣的:(C++,#,线程同步,C++,无锁队列)