2014-07-09 37 views
0

我想知道COW是如何工作的,我在wikibooks上找到了下面這個類,但我不明白這段代碼。抄寫正確的用法?

template <class T> 
class CowPtr 
{ 
    public: 
     typedef boost::shared_ptr<T> RefPtr; 

    private: 
     RefPtr m_sp; 

     void detach() 
     { 
      T* tmp = m_sp.get(); 
      if(!(tmp == 0 || m_sp.unique())) { 
       m_sp = RefPtr(new T(*tmp)); 
      } 
     } 

    public: 
     CowPtr(T* t) 
      : m_sp(t) 
     {} 
     CowPtr(const RefPtr& refptr) 
      : m_sp(refptr) 
     {} 
     CowPtr(const CowPtr& cowptr) 
      : m_sp(cowptr.m_sp) 
     {} 
     CowPtr& operator=(const CowPtr& rhs) 
     { 
      m_sp = rhs.m_sp; // no need to check for self-assignment with boost::shared_ptr 
      return *this; 
     } 
     const T& operator*() const 
     { 
      return *m_sp; 
     } 
     T& operator*() 
     { 
      detach(); 
      return *m_sp; 
     } 
     const T* operator->() const 
     { 
      return m_sp.operator->(); 
     } 
     T* operator->() 
     { 
      detach(); 
      return m_sp.operator->(); 
     } 
}; 

而且我會在我的多線程應用程序中將它用於共享地圖對象。

map<unsigned int, LPOBJECT> map; 

所以我賦予它模板,我現在有:

CowPtr<map<unsigned int, LPOBJECT>> map; 

現在我的問題:

  1. 我應該怎樣propertly拿地圖的實例隨機只想讀地圖對象的線程?

  2. 我應該如何從隨機線程修改地圖對象,例如。插入新的對象或擦除它?

回答

4

您發佈的代碼很差,無法使用; 作者似乎並不瞭解const如何在C++中工作。

實際上講:CoW需要一定的知識才能在課上完成 操作。當包裝對象上的操作可能修改 時,CoW包裝必須 觸發副本;在被包裝的對象可以「泄漏」指針 或允許修改的迭代器的情況下,它也必須能夠記住這個,一旦泄漏了任何東西就要求深度複製 。您發佈的代碼會觸發副本,具體取決於 指針是否爲const,這與 的東西並不完全相同。因此,與std::map,呼籲 std::map<>::find地圖應該觸發寫時複製,即使指針 不是常量,並調用std::map<>::insert應該,即使 指針是常量。

至於線程:這是非常困難的一頭牛 類線程安全沒有抓住一個鎖,每一個操作 可能發生變異,因爲它是非常困難的,知道什麼時候 實際對象的線程之間共享。而且,如果對象允許指針或迭代器泄漏到 ,就像標準庫對象一樣,它甚至更難。

你不解釋爲什麼你想要一個線程安全的CoW地圖。 如果您每次添加或刪除元素時都是地圖上的點, 您最終得到的新副本在其他 實例中不可見?如果只是用 啓動一個現有地圖的副本,std::map有一個副本構造函數 ,它可以很好地完成這項工作,而且您不需要任何花式的 包裝。

1

這是如何工作的?

class CowPtr確實持有一個共享指針到基礎對象。它有一個私有方法來複制構造一個新對象並將指針分配給本地共享指針(如果任何其他對象確實持有對其的引用):void detach()

此代碼的相關部分是,它具有每個方法

const return_type& 
method_name() const 

,一次不常量。一個方法之後的const保證該方法不會修改該對象,該方法被稱爲const方法。由於對基礎對象的引用也是const,因此每次需要引用而不修改該方法時都會調用該方法。

然而,如果你選擇修改的對象後面的參考資料,例如:

CowPtr<std::map<unsigned int, LPOBJECT>> map; 
map->clear(); 

非const方法T& operator->()被調用,調用detach()。通過這樣做,一份拷貝,如果任何其他CowPtrshared_ptr被引用相同的底層對象(的<unsigned int, LPOBJECT>在這種情況下,實例)

如何使用它?

您將如何使用std::shared_ptrboost::shared_ptr。關於該實現的很酷的事情是它自動完成所有的事情。

備註

這是沒有COW但是,作爲一份拷貝,即使你不寫,它更是一個副本,如果你不能保證你不寫 - 實施。

+0

除了發佈的代碼不工作,因爲它用來確定是否要複製的常量不是指向對象的指針,而是指針的指針。所以你不能將一個'const Co'傳遞給一個可能會修改該對象的函數,但是如果你在一個非const指針上調用一個const函數,它將執行該複製。 –

+0

@JamesKanze是的,這就是我所說的「複製如果你不能保證你不寫 - 執行」。我贊成你的回答,因爲我沒有問自己「這個實施很好嗎?」而是「我怎麼解釋它做了什麼?」 ;) – Theolodis