zoukankan      html  css  js  c++  java
  • 灵巧指针与垃圾回收源代码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

  • 相关阅读:
    P1456 Monkey King
    P3377 【模板】左偏树(可并堆)
    P1074 靶形数独
    P1120 小木棍
    P5490 【模板】扫描线
    糖糖别胡说,我真的不是签到题目
    最长公共子序列
    最长上升子序列
    数的三次方根
    地、颜色、魔法(dfs)
  • 原文地址:https://www.cnblogs.com/cy163/p/308438.html
Copyright © 2011-2022 走看看