自己实现的STL(试图解决多线程的安全问题)

///

作者:  gavin  葛

时间: 2011年

地点:北京

///

 

 

话说STL在多线程下的不安全,解决其方法有二:

1.在使用的时候,给本身容器总体的加锁,

2.在本身实现STL的时候就加锁.

于是满怀信心的想利用第二种思路自己写一套STL出来(用单项list实现了List 和Deque).

想就这个机会去解决线程不安全的问题,虽然没有达到预期的效果,但是,还想继续在这方面努力.把源代码贴出来,请各位高手多多指教.

(全部代码一个文件中,直接拷贝用就可以)

 

#ifndef  MYSTL
#define MYSTL

namespace MYSTL
{
template <class T>
class CNode
{
private:
 T m_value;
 CNode<T>* m_pNext;
 int m_idx;
public: 
 CNode(T v = 0 , CNode<T>* pnext = NULL,int index=0)
 {
  m_value = v;
  m_pNext = pnext;
  m_idx = index;
 }
 ~CNode(){}
 inline bool SetNode(T v)
 {
  m_value = v;
  return true;
 }
 inline T GetNode()
 {
  return m_value;
 }
 inline CNode<T>* GetNext()
 {
  return m_pNext;
 }
 inline void SetNext(CNode<T>* node)
 {
  m_pNext = node;
 }
 inline void SetIndex(int index)
 {
  m_idx = index;
 }
 inline int GetIndex()
 {
  return m_idx;
 }
};

template<class T>
class CDeque
{
private:
 CNode<T>* m_pHead;
 CNode<T>* m_pTail;
 CNode<T>* m_pCurrent;
 volatile long m_isize;
 volatile long m_bResourseInUse;
 CRITICAL_SECTION critical_sec_object;
private:
 void Lock();
 void UnLock();
public:
 CDeque();
 ~CDeque();
public:
 int GetSize();
 bool PushBack(T value);
 bool PushFront(T value);
 T PopBack();
 T PopFront();
 T GetAt(int idx); 
 bool SetAt(int idx,T value);
 bool InsertAt(int idx,T value);
 bool DeleteAt(int idx);
 bool Erase(int idxBegin);
 bool Clear();
};

template<class T>
class CList
{
private:
 CNode<T>* m_pHead;
 CNode<T>* m_pTail;
 CNode<T>* m_pCurrent;
 volatile long m_isize;
 volatile long m_bResourseInUse;
private:
 void Lock();
 void UnLock();
public:
 CList();
 ~CList();
public:
 int GetSize();     
 T GetAt(int idx);
 bool SetAt(int idx,T value);
 bool InsertAt(int idx,T value);
 bool DeleteAt(int idx);
 bool Erase(int idxBegin);
 bool Clear();
};

template<class T>
CDeque<T>::CDeque()
{
 m_pHead = NULL;
 m_pTail =NULL;
 m_pCurrent = NULL;
 m_isize = 0;
 m_bResourseInUse = FALSE;
 ::InitializeCriticalSection(&critical_sec_object);
}

template<class T>
CDeque<T>::~CDeque()
{
 CNode<T>* ptr = NULL;
 CNode<T>* ptrCur = NULL;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  ptr = ptrCur;
  ptrCur = ptrCur->GetNext();
  delete ptr;
 }
 ptr = NULL;
 m_isize = 0;
 ::DeleteCriticalSection(&critical_sec_object); 
}

template<class T>
bool CDeque<T>::Clear()
{
 CNode<T>* ptr = NULL;
 CNode<T>* ptrCur = NULL;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  ptr = ptrCur;
  ptrCur = ptrCur->GetNext();
  delete ptr;
 }
 ptr = NULL;
 m_isize = 0;
 m_pHead = m_pTail = m_pCurrent = NULL;
 return true;
}

template<class T>
void CDeque<T>::Lock()
{
 /*while(InterlockedExchange(&m_bResourseInUse,TRUE)== TRUE)
 {
  Sleep(1);
 }*/
 //::EnterCriticalSection(&critical_sec_object);
}

template<class T>
void CDeque<T>::UnLock()
{
 /*InterlockedExchange(&m_bResourseInUse,FALSE); */
 //::LeaveCriticalSection(&critical_sec_object);
}

template<class T>
int CDeque<T>::GetSize()
{
 return m_isize;
}

template<class T>
bool CDeque<T>::PushBack(T value)
{
 //thread_space::CStackLock lock(m_criticalObj);
 Lock();
 CNode<T>* ptrCur = NULL;
 if(m_isize == 0)
 {
  CNode<T>* newptr=new CNode<T>(value,NULL,0);
  assert(newptr);
  m_pHead = newptr;
  m_pTail = newptr;
  //m_isize ++;
  InterlockedIncrement(&m_isize);
 }
 else
 {
  CNode<T> * newptr = new CNode<T>(value,NULL,m_isize);
  assert(newptr);
  m_pTail->SetNext(newptr);
  m_pTail = newptr;
  //m_isize ++; 
  InterlockedIncrement(&m_isize);
 } 
 UnLock();
 return true;
}

template<class T>
bool CDeque<T>::PushFront(T value)
{
 Lock();
 CNode<T>* ptrCur = NULL;
 //thread_space::CStackLock lock(m_criticalObj);
 if (m_isize == 0)
 {
  CNode<T> * newptr = new CNode<T>(value,NULL,0);
  assert(newptr);
  m_pHead = newptr;
  m_pTail = newptr;  
 }
 else
 {
  ptrCur = m_pHead;
  while(ptrCur)
  {
   ptrCur->SetIndex(ptrCur->GetIndex()+1);
   ptrCur = ptrCur->GetNext();
  }
  CNode<T> * newptr = new CNode<T>(value,NULL,0);
  newptr->SetNext(m_pHead);
  m_pHead = newptr;
 } 
 //m_isize ++;
 InterlockedIncrement(&m_isize);
 UnLock();
 return true;
}

template<class T>
T CDeque<T>::PopBack()
{
 Lock();
 CNode<T> * ptr = NULL;
 CNode<T>* ptrCur = NULL;
 T v;
 //thread_space::CStackLock lock(m_criticalObj);
 if (m_isize == 1)
 {
  ptr = m_pHead;  
  v = m_pHead->GetNode();
  delete ptr;
  ptr = NULL;
  m_pHead = m_pTail = NULL;
  m_isize = 0;
 }
 else
 {
  ptrCur = m_pHead;
  while (ptrCur)
  {
   ptr = ptrCur->GetNext();
   if (ptr->GetIndex() == m_isize -1 )
   {
    v = m_pTail->GetNode();
    m_pTail = ptrCur;
    ptrCur->SetNext(NULL);
    delete ptr;
    ptr = NULL;
    //m_isize --;
    InterlockedDecrement(&m_isize);
    break;
   }
   ptrCur = ptrCur->GetNext();
  }
 }
 UnLock();
 return v;
}

template<class T>
T CDeque<T>::PopFront()
{
 Lock();
 CNode<T> * ptr = NULL;
 CNode<T>* ptrCur = NULL;
 T v;
 //thread_space::CStackLock lock(m_criticalObj);
 if (m_isize == 1)
 {
  ptr = m_pHead;  
  v = m_pHead->GetNode();
  delete ptr;
  ptr = NULL;
  m_pHead = m_pTail = NULL;
  m_isize = 0;
 }
 else
 {
  ptr = m_pHead;
  v = m_pHead->GetNode();
  m_pHead = m_pHead->GetNext();
  delete ptr;
  ptr = NULL;
  ptrCur = m_pHead;
  while (ptrCur)
  {
   ptrCur->SetIndex(ptrCur->GetIndex()-1);
   ptrCur = ptrCur->GetNext();
  }
  //m_isize --;
  InterlockedDecrement(&m_isize);
 }
 UnLock();
 return v;
}

template<class T>
T CDeque<T>::GetAt(int idx)
{
 Lock();
 assert(idx < m_isize && idx >= 0);
 CNode<T>* ptrCur = NULL;
 ptrCur = m_pHead;
 T v;
 while(ptrCur)
 {
  if (ptrCur->GetIndex() == idx)
  {
   v = ptrCur->GetNode();
   break;
  }
  ptrCur = ptrCur->GetNext();
 }
 UnLock();
 return v;
}

template<class T>
bool CDeque<T>::SetAt(int idx,T value)
{
 Lock();
 CNode<T>* ptrCur = NULL;
 bool bRet = false;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  if (ptrCur->GetIndex() == idx)
  {
   ptrCur->SetNode(value);
   bRet = true;
  }
  ptrCur = ptrCur->GetNext();
 }
 UnLock();
 return bRet;
}

template<class T>
bool CDeque<T>::InsertAt(int idx,T value)
{
 Lock();
 CNode<T>* ptrCur = NULL;
 bool bRet = false;
 //thread_space::CStackLock lock(m_criticalObj);
 if(idx == 0)
 {
  if (m_isize == 0)
  {
   CNode<T>* newptr=new CNode<T>(value,NULL,0);
   assert(newptr);
   m_pHead = newptr;
   m_pTail = newptr;
   //m_isize ++;
   InterlockedIncrement(&m_isize);
  }  
  else
  {
   ptrCur = m_pHead;
   while (ptrCur)
   {
    ptrCur->SetIndex(ptrCur->GetIndex()+1);
    ptrCur = ptrCur->GetNext();
   }
   CNode<T>* newptr=new CNode<T>(value,NULL,0);
   assert(newptr);
   newptr->SetNext(m_pHead);
   m_pHead = newptr;
   //m_isize ++;
   InterlockedIncrement(&m_isize);
  }
  bRet = true;
 }
 else if(idx>0 && idx<m_isize)
 {
  CNode<T> * newptr = new CNode<T>(value,NULL,idx);
  CNode<T> * ptr = NULL;
  ptrCur = m_pHead;
  while(ptrCur)
  {
   ptr = ptrCur->GetNext();
   if (ptr->GetIndex() == idx)
   {    
    newptr->SetNext(ptrCur->GetNext());
    ptrCur->SetNext(newptr);
    //m_isize ++;
    InterlockedIncrement(&m_isize);
    break;
   }
   ptrCur = ptr;
  }
  ptrCur = newptr->GetNext();
  while(ptrCur)
  {
   ptrCur->SetIndex(ptrCur->GetIndex()+1);
   ptrCur = ptrCur->GetNext();
  }
  bRet = true;
 }
 else if (idx == m_isize)
 {
  CNode<T> * newptr = new CNode<T>(value,NULL,idx);
  assert(newptr);
  m_pTail->SetNext(newptr);
  m_pTail = newptr;
  //m_isize ++;
  InterlockedIncrement(&m_isize);
  bRet = true;
 }
 UnLock();
 return bRet;
}
template<class T>
bool CDeque<T>::Erase(int idxBegin)
{
 Lock();
 if (idxBegin >= m_isize || idxBegin<0)
 {
  return false;
 }
 
  //thread_space::CStackLock lock(m_criticalObj);
 CNode<T>* pCur = NULL;
 CNode<T>* pTmp = NULL;
 bool bDelFlag = false;
 if (idxBegin == 0)
 {
  return Clear();
 }
 else //if(idxBegin>0 && idxBegin < m_isize -1)
 {
  pCur = m_pHead;
  while(pCur)
  {
   pTmp = pCur->GetNext();
   if (pTmp->GetIndex() == idxBegin)
   {
    bDelFlag = true;
    break;
   }
   pCur = pCur->GetNext();
  }
  if (bDelFlag)
  {
   m_pTail = pCur;
   pTmp = pCur->GetNext();
   pCur->SetNext(NULL);
   CNode<T> *ptr = NULL;
   while(pTmp)
   {    
    ptr = pTmp;
    pTmp = pTmp->GetNext();
    delete ptr;  
    //m_isize --;
    InterlockedDecrement(&m_isize);
   }
  }
 }   
 /*else if (idxBegin == m_isize -1)
 {
  PopBack();
 }*/
 UnLock();
 return true;
}

template<class T>
bool CDeque<T>::DeleteAt(int idx)
{
 Lock();
 if(idx<0 ||idx >= m_isize)return false;
 CNode<T>* ptrCur = NULL;
 //thread_space::CStackLock lock(m_criticalObj);

 CNode<T> * ptr = NULL;
 CNode<T> * ptrTmp = NULL;
 if (idx == 0)
 {
  if (m_isize == 0)
  {
   ptr = m_pHead;
   m_pHead = m_pTail = m_pCurrent = NULL;
   delete ptr;
   ptr = NULL;
  }
  else
  {
   ptr = m_pHead;
   m_pHead  = m_pHead->GetNext();
   delete ptr;
   if (1 == m_isize)
   {
    m_pTail = m_pHead;
   }
   ptr = NULL;
   ptrCur = m_pHead;
   while(ptrCur)
   {
    ptrCur->SetIndex(ptrCur->GetIndex()-1);
    ptrCur = ptrCur->GetNext();
   }
  }  
  //m_isize --;
  InterlockedDecrement(&m_isize);
 }
 else if(idx>0 && idx<m_isize)
 {
  ptrCur = m_pHead;
  while(ptrCur)
  {
   ptr = ptrCur->GetNext();
   if (ptr->GetIndex() == idx)
   {    
    ptrTmp = ptr;
    ptrCur->SetNext(ptrCur->GetNext()->GetNext());   
    delete ptrTmp;
    ptrTmp = NULL;
    //m_isize --;
    InterlockedDecrement(&m_isize);
    break;
   }
   ptrCur = ptrCur->GetNext();
  }
  while(ptrCur->GetNext())
  {
   ptr = ptrCur->GetNext();
   ptr->SetIndex(ptr->GetIndex()-1);
   ptrCur = ptrCur->GetNext();
  }
  m_pTail = ptrCur;
 }
 UnLock();
 return true;
}


template<class T>
CList<T>::CList()
{
 m_pHead = NULL;
 m_pTail =NULL;
 m_pCurrent = NULL;
 m_isize = 0;
 m_bResourseInUse = FALSE;
}

template<class T>
void CList<T>::Lock()
{
 while(InterlockedExchange(&m_bResourseInUse,TRUE)== TRUE)
 {
   Sleep(1);
 }
}

template<class T>
void CList<T>::UnLock()
{
 InterlockedExchange(&m_bResourseInUse,FALSE); 
}

template<class T>
CList<T>::~CList()
{
 CNode<T>* ptr = NULL;
 CNode<T>* ptrCur = NULL;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  ptr = ptrCur;
  ptrCur = ptrCur->GetNext();
  delete ptr;
 }
 ptr = NULL;
 m_isize = 0;
}

template<class T>
int CList<T>::GetSize()
{
 return m_isize;
}

template<class T>
T CList<T>::GetAt(int idx)
{
 Lock();
 assert(idx < m_isize && idx >= 0);
 CNode<T>* ptrCur = NULL;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  if (ptrCur->GetIndex() == idx)
  {
   return ptrCur->GetNode();
  }
  ptrCur = ptrCur->GetNext();
 }
 UnLock();
}     

template<class T>
bool CList<T>::InsertAt(int idx,T value)
{
 Lock();
 CNode<T>* ptrCur = NULL;
 bool bRet = false;
 //thread_space::CStackLock lock(m_criticalObj);
 if(idx == 0)
 {
  if (m_isize == 0)
  {
   CNode<T>* newptr=new CNode<T>(value,NULL,0);
   assert(newptr);
   m_pHead = newptr;
   m_pTail = newptr;
   //m_isize ++;
   InterlockedIncrement(&m_isize);
  }  
  else
  {
   ptrCur = m_pHead;
   while (ptrCur)
   {
    ptrCur->SetIndex(ptrCur->GetIndex()+1);
    ptrCur = ptrCur->GetNext();
   }
   CNode<T>* newptr=new CNode<T>(value,NULL,0);
   assert(newptr);
   newptr->SetNext(m_pHead);
   m_pHead = newptr;
   //m_isize ++;
   InterlockedIncrement(&m_isize);
  }
  bRet = true;
 }
 else if(idx>0 && idx<m_isize)
 {
  CNode<T> * newptr = new CNode<T>(value,NULL,idx);
  CNode<T> * ptr = NULL;
  ptrCur = m_pHead;
  while(ptrCur)
  {
   ptr = ptrCur->GetNext();
   if (ptr->GetIndex() == idx)
   {    
    newptr->SetNext(ptrCur->GetNext());
    ptrCur->SetNext(newptr);
    //m_isize ++;
    InterlockedIncrement(&m_isize);
    break;
   }
   ptrCur = ptr;
  }
  ptrCur = newptr->GetNext();
  while(ptrCur)
  {
   ptrCur->SetIndex(ptrCur->GetIndex()+1);
   ptrCur = ptrCur->GetNext();
  }
  bRet = true;
 }
 else if (idx == m_isize)
 {
  CNode<T> * newptr = new CNode<T>(value,NULL,idx);
  assert(newptr);
  m_pTail->SetNext(newptr);
  m_pTail = newptr;
  //m_isize ++;
  InterlockedIncrement(&m_isize);
  bRet = true;
 }
 UnLock();
 return bRet;
}

template<class T>
bool CList<T>::DeleteAt(int idx)
{
 Lock();
 if(idx<0 ||idx >= m_isize)return false;
 CNode<T>* ptrCur = NULL;
 //thread_space::CStackLock lock(m_criticalObj);
 CNode<T> * ptr = NULL;
 CNode<T> * ptrTmp = NULL;
 if (idx == 0)
 {
  if (m_isize == 0)
  {
   ptr = m_pHead;
   m_pHead = m_pTail = m_pCurrent = NULL;
   delete ptr;
   ptr = NULL;
  }
  else
  {
   ptr = m_pHead;
   m_pHead  = m_pHead->GetNext();
   delete ptr;
   if (1 == m_isize)
   {
    m_pTail = m_pHead;
   }
   ptr = NULL;
   ptrCur = m_pHead;
   while(ptrCur)
   {
    ptrCur->SetIndex(ptrCur->GetIndex()-1);
    ptrCur = ptrCur->GetNext();
   }
  }  
  //m_isize --;
  InterlockedDecrement(&m_isize);
 }
 else if(idx>0 && idx<m_isize)
 {
  ptrCur = m_pHead;
  while(ptrCur)
  {
   ptr = ptrCur->GetNext();
   if (ptr->GetIndex() == idx)
   {    
    ptrTmp = ptr;
    ptrCur->SetNext(ptrCur->GetNext()->GetNext());   
    delete ptrTmp;
    ptrTmp = NULL;
    //m_isize --;
    InterlockedDecrement(&m_isize);
    break;
   }
   ptrCur = ptrCur->GetNext();
  }
  while(ptrCur->GetNext())
  {
   ptr = ptrCur->GetNext();
   ptr->SetIndex(ptr->GetIndex()-1);
   ptrCur = ptrCur->GetNext();
  }
  m_pTail = ptrCur;
 }
 UnLock();
 return true;
}

template<class T>
bool CList<T>::Clear()
{
 Lock();
 //thread_space::CStackLock lock(m_criticalObj);
 CNode<T>* ptr = NULL;
 CNode<T>* ptrCur = NULL;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  ptr = ptrCur;
  ptrCur = ptrCur->GetNext();
  delete ptr;
 }
 ptr = NULL;
 m_isize = 0;
 m_pHead = m_pTail = m_pCurrent = NULL;
 UnLock();
 return true;
}

template<class T>
bool CList<T>::SetAt(int idx,T value)
{
 Lock();
 CNode<T>* ptrCur = NULL;
 bool bRet = false;
 ptrCur = m_pHead;
 while(ptrCur)
 {
  if (ptrCur->GetIndex() == idx)
  {
   ptrCur->SetNode(value);
   bRet = true;
  }
  ptrCur = ptrCur->GetNext();
 }
 UnLock();
 return bRet;
}
template<class T>
bool CList<T>::Erase(int idxBegin)
{
 Lock();
 if (idxBegin >= m_isize || idxBegin<0)
 {
  return false;
 }
 //thread_space::CStackLock lock(m_criticalObj);
 CNode<T>* pCur = NULL;
 CNode<T>* pTmp = NULL;
 bool bDelFlag = false;
 if (idxBegin == 0)
 {
  return Clear();
 }
 else //if(idxBegin>0 && idxBegin < m_isize -1)
 {
  pCur = m_pHead;
  while(pCur)
  {
   pTmp = pCur->GetNext();
   if (pTmp->GetIndex() == idxBegin)
   {
    bDelFlag = true;
    break;
   }
   pCur = pCur->GetNext();
  }
  if (bDelFlag)
  {
   m_pTail = pCur;
   pTmp = pCur->GetNext();
   pCur->SetNext(NULL);
   CNode<T> *ptr = NULL;
   while(pTmp)
   {    
    ptr = pTmp;
    pTmp = pTmp->GetNext();
    delete ptr;  
    //m_isize --;
    InterlockedDecrement(&m_isize);
   }
  }
 }  
 UnLock();
 return true;
}
}
#endif
//

 

由于时间有限,而且侧重点不一样(目的是想解决多线程的安全问题)

所以,没有自己写迭代器.以后有时间会加上去.当然迭代器本身是STL的一个很重要的功能,但是作者认为,

迭代器本身的目的是为了更好的去使用STL容器.而本文解决的目的不一样.

 

作者:gavin  葛            版权所有                          ( 如若转载,请标明原始地址       谢谢.)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值