灵巧指针与垃圾回收源代码CPtrArray


http://www.chinaaspx.com/archive/VC/7043.htm

本人将源代码粘贴于此,各位有兴趣的网友可以测试一试。

说明:

       只要将两个文件加入到你的工程中,并在你的CWinApp派生类中加入如下一句即可:

        CPtrManager thePtrManager;

       然后,在使用普通指针的地方,用灵巧指针替换即可,假如有一个类test,并有如下应用:

          test * ptest=new test;

          other  code

          delete ptest;

现在可这样应用:

         auto_ptr<test> ptest= new test;

          other code

再不用人为的delete  ptest 了,垃圾回收将自动清除,即使你有如下应用:

        auto_ptr<test>  ptest;

       test  mytest;

       ptest=&mytest;

你也不用担心,灵巧指针也不会误删你在栈中的内存。

        只要大家认真帮我测试这段代码到没有 BUG,并对部分算法进行优化和改进,那么,我可以相信:“C++中无垃圾回收”将成为历史。

 

// PtrManager.h: interface for the CPtrManager class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PTRMANAGER_H__BB4B38B5_DA34_11D3_9327_000629377185__INCLUDED_)
#define AFX_PTRMANAGER_H__BB4B38B5_DA34_11D3_9327_000629377185__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Afxmt.h"

class CMySingleLock:public CSingleLock
{
public:
 CMySingleLock(CSyncObject* pObject, BOOL bInitialLock = FALSE )
  :CSingleLock(pObject,bInitialLock){}
    void operator delete(void * p)
 {
   free(p);
 }
    void * operator new(size_t size)
 {  
      return malloc(size);
 }
};


class CPtr
{
 friend class CMark;
public:
 int GetPtrSize();
 CMutex * GetCMutex();
 void * GetPtr();
 CPtr();
 virtual ~CPtr();
 int GetCount();
    void AddAutoPtr(void * autoPtr,int AutoMark);
 BOOL DeleteAutoPtr(void * autoPtr);
 void SetPtr(void * thePtr,int Size,
          int mark,int count=0);
 
    void operator delete(void * p)
 {
   free(p);
 }
    void * operator new(size_t size)
 {  
      return malloc(size);
 }

private:
 int m_mark;
 int m_count;
 void * m_ptr;
 int m_size;
 CPtrArray AutoPtrArray;
 CUIntArray m_AutoMark; file://0 in the stack; >0 =mark
 CMutex mutex;
};

class CMark
{
 friend class CMarkTable;
public:
 CMark(){}
 virtual ~CMark(){}


    void operator delete(void * p)
 {
   free(p);
 }
    void * operator new(size_t size)
 {  
      return malloc(size);
 }
 void CopyFromCPtr(CPtr* theCPtr);
 BOOL bIsNoneInStack();
 void Release();
private:
 int m_mark;
 CPtrArray autoptrArray;
 CUIntArray automarkArray;

};
class CMarkTable
{
public:
 CMarkTable(){Init();}
 virtual ~CMarkTable(){}
 
 void AddCMark(CMark * theCMark);
 BOOL FindMark(int mark);
 void Init();
 void DoLockMark();
private:
 CPtrArray CMarkArray;
 CPtrArray CLockMarkArray;
 void GetLockMark();
 BOOL FindLockMark(int mark);
 void RemoveUnlockMark();
 void RemoveGroup(int automark);

};

 


class CPtrManager 
{
public:
 int GetAutoMark(void * ptr);
 CPtrManager();
 virtual ~CPtrManager();
 int GetMarkFromPtr(void * Ptr);
 void *MallocPtr(size_t size);
    BOOL bCanWrite();
 void DeletePtr(int mark,void * Ptr);
 void AddPtr(void *Ptr,int PtrSize);
 static CPtrManager * GetPtrManager();
 CPtr * GetCPtr(void * Ptr,int mark);

private:
    CPtrArray m_ptr;
 void*  pCurrent;
 unsigned int m_mark;
 CUIntArray m_removed;
 BOOL bWrite;
 static CPtrManager * p_this;
 CMutex mutex;
 CMarkTable myMarkTable;
 void RemoveLockRes();
 void CopyAllMark();
 static UINT myThreadProc(LPVOID lparm);
 CWinThread* myThread;
 void BeginThread()
 { myThread=AfxBeginThread(myThreadProc,this);}
};

class parent_autoptr
{
public:
 parent_autoptr()
 {thisAutoMark=0;}
 virtual ~parent_autoptr(){}
 virtual void Release(){}
protected:
 int thisAutoMark;
};

template<class T>
class auto_ptr :public parent_autoptr
{
   public:
    virtual void Release(){Remove();}
    auto_ptr()
    {mark=0;pointee=0;thisAutoMark=GetAutoMark();}
    auto_ptr(auto_ptr<T>&rhs);
    auto_ptr(T*ptr);
    ~auto_ptr(){Remove();}
    T*operator->() const;
    operator T*();
    T&operator*()const;
    auto_ptr<T>&operator=(auto_ptr<T>&rhs);
       auto_ptr<T>&operator=(T*ptr);
   private:
       void Remove();
    int GetAutoMark();
    CMutex *GetCMutex();
    void ReadyWrite();
    T*pointee;
    int mark;
   
};
template<class T> T* auto_ptr< T>::operator ->()const
{
 return pointee;
}
template<class T> void auto_ptr< T>::ReadyWrite()
{
 CPtrManager * pMana=CPtrManager::GetPtrManager();
    if(pMana)
 {
  for(;;)
  {
   if(pMana->bCanWrite())
    break;
  }
 }
}
template<class T> int auto_ptr< T>::GetAutoMark()
{
 CPtrManager * pMana=CPtrManager::GetPtrManager();
    if(pMana)
 {
  return pMana->GetAutoMark(this);
 }
 return 0;
}
template<class T> CMutex* auto_ptr< T>::GetCMutex()
{
   CPtrManager * pMana=CPtrManager::GetPtrManager();
   if(pMana)
   {
   CPtr * theCPtr=pMana->GetCPtr(pointee,mark);
      if(theCPtr)
    return theCPtr->GetCMutex();
   }
   return NULL;
}
template<class T> void auto_ptr< T>::Remove()
{
CMutex * theMutex=GetCMutex();
if(theMutex)
{
 CMySingleLock *pLock=new CMySingleLock(theMutex);
 pLock->Lock();
 BOOL bDeleteLock=FALSE;
 
    CPtrManager * pMana=CPtrManager::GetPtrManager();
 if(pointee&&pMana)
 {
   CPtr * theCPtr=pMana->GetCPtr(pointee,mark);
   if(theCPtr)
   {
    if(theCPtr->DeleteAutoPtr(this))
    {
     if(theCPtr->GetCount()==0)
     {
      pLock->Unlock();
      delete pLock;
      pMana->DeletePtr(mark,pointee);
      bDeleteLock=TRUE;
      delete pointee;

     }
    }

   }     
   else
   {
    file://User decide to do
   }


 }
 pointee=NULL;
 mark=0;
 if(!bDeleteLock)
  delete pLock;
}
}
template<class T> auto_ptr< T>::operator T*()
{
 return pointee;
}
template<class T> T& auto_ptr< T>::operator *()const
{
 return *pointee;
}
template<class T> auto_ptr< T>::auto_ptr(auto_ptr<T>&rhs)
{
thisAutoMark=GetAutoMark();
ReadyWrite();
CMutex * theMutex=GetCMutex();
if(theMutex)
{
 CSingleLock singleLock(theMutex);
 singleLock.Lock();


 pointee=rhs.pointee;
 mark=rhs.mark;
 CPtrManager * pMana=CPtrManager::GetPtrManager();
 if(pMana)
 {
       CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
    if(theCPtr)
    {
     theCPtr->AddAutoPtr(this,thisAutoMark);
    }

 }

}
template<class T> auto_ptr< T>::auto_ptr(T*ptr)
{
    thisAutoMark=GetAutoMark();
    ReadyWrite();

    mark=0;
    pointee=ptr;
       CPtrManager * pMana=CPtrManager::GetPtrManager();
       if(pMana)
    {
       mark=pMana->GetMarkFromPtr(ptr);
    if(mark>0)
    {
   CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
         if(theCPtr)
   {
     CMutex * theMutex=theCPtr->GetCMutex();
           if(theMutex)
     {
          CSingleLock singleLock(theMutex);
          singleLock.Lock();
       theCPtr->AddAutoPtr(this,thisAutoMark);
     }
   }
    }
     
    }
}
template<class T>auto_ptr<T>& auto_ptr< T>::operator=(auto_ptr<T>&rhs)
{
if(pointee!=rhs.pointee)
{
  ReadyWrite();
  Remove();
 
  pointee=rhs.pointee;
  mark=rhs.mark;

  CMutex * theMutex=GetCMutex();
  if(theMutex)
  {
   CSingleLock singleLock(theMutex);
   singleLock.Lock();

    CPtrManager * pMana=CPtrManager::GetPtrManager();
  if(pMana)
  {
            CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
         if(theCPtr)
   {
        theCPtr->AddAutoPtr(this,thisAutoMark);
   }
  }

  }
}
 return *this;

}
template<class T> auto_ptr<T>&auto_ptr< T>::operator = (T* ptr)
{
   if(pointee!=ptr)
   {
    ReadyWrite();

    Remove();
    pointee=ptr;
       CPtrManager * pMana=CPtrManager::GetPtrManager();
       if(pMana)
    {

       mark=pMana->GetMarkFromPtr(ptr);
    if(mark>0)
    {
   CPtr* theCPtr=pMana->GetCPtr(pointee,mark);
         if(theCPtr)
   {
      CMutex * theMutex=theCPtr->GetCMutex();
             if(theMutex)
    {
              CSingleLock singleLock(theMutex);
              singleLock.Lock();
        theCPtr->AddAutoPtr(this,thisAutoMark);
   
    }
   }
    }
  
    }
   }
    return *this;
}


class test
{
public:
 auto_ptr<test> p;
};
#endif // !defined(AFX_PTRMANAGER_H__BB4B38B5_DA34_11D3_9327_000629377185__INCLUDED_)

 

 

// PtrManager.cpp: implementation of the CPtrManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "PtrManager.h"

CPtrManager * CPtrManager::p_this=0;


void operator delete(void * p)
{
 free(p);
}
void * operator new(size_t size)
{
  CPtrManager * pMana=CPtrManager::GetPtrManager();
 
  return pMana->MallocPtr(size);

}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPtr::CPtr()
{
 m_count=0;
 m_mark=0;
 m_ptr=0;
 m_size=0;
 AutoPtrArray.SetSize(0);
 m_AutoMark.SetSize(0);
}
CPtr::~CPtr()
{
}
void * CPtr::GetPtr()
{
  return m_ptr;
}
void CPtr::AddAutoPtr(void * autoPtr,int AutoMark)
{
 int size=AutoPtrArray.GetSize();
 AutoPtrArray.SetAtGrow(size,autoPtr);
 m_AutoMark.SetAtGrow(size,AutoMark);
 m_count++;
}
BOOL CPtr::DeleteAutoPtr(void * autoPtr)
{
 int size=AutoPtrArray.GetSize();
 for(int i=0;i<size;i++)
 {
  if(autoPtr==AutoPtrArray[i])
  {
   AutoPtrArray.RemoveAt(i);
   m_AutoMark.RemoveAt(i);
   m_count--;
   return TRUE;
  }
 }
 return FALSE;
}
int CPtr::GetCount()
{
 return m_count;
}
void CPtr::SetPtr(void * thePtr,int Size,int mark,int count)
{
 m_ptr=thePtr;
 m_mark=mark;
    m_size=Size;
 m_count=count;
}
CMutex * CPtr::GetCMutex()
{
   return &mutex;
}
int CPtr::GetPtrSize()
{
return m_size;
}

 

// class CPtrManager

CPtrManager::CPtrManager()
{
   m_mark=0;
   m_ptr.SetSize(1);
   m_ptr[0]=0;
   m_removed.SetSize(0);
   p_this=this;
   pCurrent=0;
   bWrite=TRUE;
   myThread=0;
   BeginThread();
}

CPtrManager::~CPtrManager()
{
    p_this=0;
 if(myThread)
   myThread->SuspendThread( );
 int size=m_ptr.GetSize();
 for(int i=1;i<size;i++)
 {
  if(m_ptr[i])
  {
   free(m_ptr[i]);
  }
 }

}
void CPtrManager::AddPtr(void *Ptr,int PtrSize)
{
    CSingleLock singleLock(&mutex);
 singleLock.Lock();

 int size=0;
    if(m_removed.GetSize()==0)
 {
    size =m_ptr.GetSize();
 }
    else
 {
     size=m_removed[0];
     m_removed.RemoveAt(0);
 }
  if(size==0)
  size=1;
 CPtr * thePtr=new CPtr;
 thePtr->SetPtr(Ptr,PtrSize,size);
  m_ptr.SetAtGrow(size,thePtr);

 pCurrent=Ptr;
 m_mark=size;
}
void * CPtrManager::MallocPtr(size_t size)
{
   CSingleLock singleLock(&mutex);
   singleLock.Lock();

   void * p=malloc(size);
   if(p)
     AddPtr(p,size);
  
   return p;
}
void CPtrManager::DeletePtr(int mark,void*Ptr)
{

   if(mark<=0||m_ptr.GetSize()<mark+1)
    return ;

    CSingleLock singleLock(&mutex);
 singleLock.Lock();

   if(m_ptr[mark])
   {
    CPtr * thePtr=(CPtr*)m_ptr[mark];
    if(Ptr!=thePtr->GetPtr())
     return ;
    delete thePtr;
    m_ptr[mark]=NULL;
       m_removed.Add(mark);
   }

}
int CPtrManager::GetMarkFromPtr(void * Ptr)
{
    CSingleLock singleLock(&mutex);
 singleLock.Lock();

 if(pCurrent==Ptr)
  return m_mark;

 int size=m_ptr.GetSize();
 for(int i=1;i<size;i++)
 {
  if(m_ptr[i]==Ptr)
   return i;
 }
 return NULL;
}
CPtrManager * CPtrManager::GetPtrManager()
{
 return p_this;
}
BOOL CPtrManager::bCanWrite()
{
 return bWrite;
}
CPtr * CPtrManager::GetCPtr(void * Ptr,int mark)
{

 if(!Ptr||mark<=0 || m_ptr.GetSize()<mark+1)
  return NULL;

 CSingleLock singleLock(&mutex);
 singleLock.Lock();

 if(m_ptr[mark])
 {
  CPtr * thePtr=(CPtr*)m_ptr[mark];
  if(Ptr!=thePtr->GetPtr())
   return NULL;
  else
   return thePtr;
 }
 return NULL;
}

 


int CPtrManager::GetAutoMark(void *ptr)
{
    CSingleLock singleLock(&mutex);
 singleLock.Lock();

  int size =m_ptr.GetSize();
  for(int i=1;i<size;i++)
  {
   CPtr* theCPtr=(CPtr*)m_ptr[i];
   if(theCPtr)
   {
    int ptrFirst=(int)theCPtr->GetPtr();
    int ptrEnd=ptrFirst+theCPtr->GetPtrSize();
    int p=(int)ptr;
    if(p>=ptrFirst&&p<=ptrEnd)
     return  i;
   }
  }
  return 0;
}

void CPtrManager::RemoveLockRes()
{
 CopyAllMark();
 myMarkTable.DoLockMark();
}
void CPtrManager::CopyAllMark()
{
 CSingleLock singleLock(&mutex);
 singleLock.Lock();

 CUIntArray theIntArray;
 theIntArray.SetSize(0);
 int size=m_ptr.GetSize();
 for(int i=0;i<size-1;i++)
 {
  theIntArray.SetAtGrow(i,i+1);
 }

 bWrite=FALSE;

    BOOL bALLCopyed=TRUE;
 int TotalWhile=0;
 do
 {
 TotalWhile++;
 bALLCopyed=TRUE;
 size=theIntArray.GetSize();
 for(i=0;i<size;i++)
 {
  int m=theIntArray[i];
  CPtr * theCPtr=(CPtr*)m_ptr[m];
  if(theCPtr)
  {
   CMutex * theMutex;
   theMutex=theCPtr->GetCMutex();
   if(theMutex)
   {
         CMySingleLock * theLock;
         theLock=new CMySingleLock(theMutex);
      if(!theLock->IsLocked())
      {
       if(theLock->Lock(50))
       {
        CMark * theMark;
        theMark=new CMark();
        theMark->CopyFromCPtr(theCPtr);
        delete theLock;
        myMarkTable.AddCMark(theMark);
        theIntArray.RemoveAt(i);
        i--;
        size--;
       }
       else
       {
        delete theLock;
        bALLCopyed=FALSE;
       }
      }
      else
      {
       delete theLock;
       bALLCopyed=FALSE;
      }
   }
  }
 }
 if(TotalWhile>=50)
  break;
 }while(!bALLCopyed);

    bWrite=TRUE;
}

UINT CPtrManager::myThreadProc(LPVOID lparm)
{
 CPtrManager* pana=(CPtrManager*)lparm;
 if(!pana)
  return 0;
 Sleep(500);
 for(;;)
  pana->RemoveLockRes();
 return 0;

}
file://begin class CMark
void CMark::CopyFromCPtr(CPtr *theCPtr)
{
 if(!theCPtr)
  return;
 
 int size=(theCPtr->AutoPtrArray).GetSize();
 automarkArray.SetSize(size);
 autoptrArray.SetSize(size);
 for(int i=0;i<size;i++)
 {
  automarkArray[i]=(theCPtr->m_AutoMark)[i];
  autoptrArray[i]=(theCPtr->AutoPtrArray)[i];
 }
 m_mark=theCPtr->m_mark;
}

BOOL CMark::bIsNoneInStack()
{
 int size=automarkArray.GetSize();
 if(size==0)
  return FALSE;
 for(int i=0;i<size;i++)
 {
  if(automarkArray[i]<=0)
   return FALSE;
 }
 return TRUE;
}
void CMark::Release()
{
 int size=autoptrArray.GetSize();
 for(int i=0;i<size;i++)
 {
  parent_autoptr * thePtr=
   (parent_autoptr *)autoptrArray[i];
  thePtr->Release();
 }
}

file://end Calss CMark 

file://begin class CMarkTable

void CMarkTable::AddCMark(CMark * theCMark)
{
 if(theCMark)
    CMarkArray.Add(theCMark);
}
BOOL CMarkTable::FindMark(int mark)
{
 int size=CMarkArray.GetSize();
 for(int i=0;i<size;i++)
 {
  CMark * theMark=(CMark *)CMarkArray[i];
  if(theMark)
  {
   if(mark==theMark->m_mark)
    return TRUE;
  }
 }
 return FALSE;
}

void CMarkTable::GetLockMark()
{
 CLockMarkArray.SetSize(0);
 int size=CMarkArray.GetSize();
 for(int i=0;i<size;i++)
 {
  CMark * theMark=(CMark*)CMarkArray[i];
  if(theMark)
  {
   if(theMark->bIsNoneInStack())
    CLockMarkArray.SetAtGrow(i,theMark);
  }
 }
}
void CMarkTable::RemoveUnlockMark()
{
CUIntArray UnlockMarkArray;
BOOL bNoneRemoveed;
do
{
 bNoneRemoveed=TRUE;
 UnlockMarkArray.SetSize(0);
 int size=CLockMarkArray.GetSize();
 for(int i=0;i<size;i++)
 {
  CMark * theMark=(CMark*)CLockMarkArray[i];
  if(theMark)
  {
   int size1=(theMark->automarkArray).GetSize();

   for(int j=0;j<size1;j++)
   {
    int mark=(theMark->automarkArray)[j];
    if(!FindLockMark(mark))
    {
     UnlockMarkArray.InsertAt(0,i); file://record to remove
     bNoneRemoveed=FALSE;
     break;
    }
   }
  }
  else
  {
   UnlockMarkArray.InsertAt(0,i);
   bNoneRemoveed=FALSE;
  }
 }
 int size2=UnlockMarkArray.GetSize();
 for(int k=0;k<size2;k++)
 {
  int m=UnlockMarkArray[k];
  CLockMarkArray.RemoveAt(m);
 }
}while(!bNoneRemoveed);

}
BOOL CMarkTable::FindLockMark(int mark)
{
 int size=CLockMarkArray.GetSize();
 for(int i=0;i<size;i++)
 {
  CMark * theMark=(CMark *)CLockMarkArray[i];
  if(theMark)
  {
   if(mark==theMark->m_mark)
    return TRUE;
  }
 }
 return FALSE;
}
void CMarkTable::RemoveGroup(int automark)
{
 int size=CLockMarkArray.GetSize();
 for(int i=0;i<size;i++)
 {
  CMark * theMark=(CMark *)CLockMarkArray[i];
  if(theMark)
  {
   if(automark==theMark->m_mark)
   {
    CLockMarkArray.RemoveAt(i);
                int size2=
     (theMark->automarkArray).GetSize();
    for(int j=0;j<size2;j++)
    {
     int auto_mark=
      (theMark->automarkArray)[j];
     RemoveGroup(auto_mark);
    }
    break;
   }
    
  }
 }
}
void CMarkTable::DoLockMark()
{
GetLockMark();
RemoveUnlockMark();
int size=CLockMarkArray.GetSize();

while(size)
{
 CMark* theMark=(CMark*)CLockMarkArray[0];
 CLockMarkArray.RemoveAt(0);
 if(theMark)
 {
  int size2=
   (theMark->automarkArray).GetSize();
  for(int i=0;i<size2;i++)
  {
   int automark=
    (theMark->automarkArray)[i];
   RemoveGroup(automark);
  }
  theMark->Release();
 }
 size=CLockMarkArray.GetSize();
}

Init();
}
void CMarkTable::Init()
{
  int size=CMarkArray.GetSize();
  for(int i=0;i<size;i++)
  {
   CMark* theMark=(CMark*)CMarkArray[i];
   if(theMark)
    delete theMark;
  }
  CMarkArray.SetSize(0);
     CLockMarkArray.SetSize(0);

}
file://end class CMarkTable

posted on 2005-12-30 19:13  cy163  阅读(2175)  评论(0编辑  收藏  举报

导航