///
作者: 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 葛 版权所有 ( 如若转载,请标明原始地址 谢谢.)