2008-12-21 22 views
5

我需要使用來自多個線程的數組,因此我使用CRITICAL SECTION賦予它對數據的獨佔訪問權限。
這裏是我的模板:
使用EnterCriticalSection的問題

#include "stdafx.h" 
#ifndef SHAREDVECTOR_H 
#define SHAREDVECTOR_H 

#include <vector> 
#include <windows.h> 

template<class T> 
class SharedVector { 
    std::vector<T> vect; 
    CRITICAL_SECTION cs; 
    SharedVector(const SharedVector<T>& rhs) {} 
public: 
    SharedVector(); 
    explicit SharedVector(const CRITICAL_SECTION& CS); 
    void PushBack(const T& value); 
    void PopBack(); 
    unsigned int size() const; 
    T& operator[](int index); 
    virtual ~SharedVector(); 
}; 

template<class T> 
SharedVector<T>::SharedVector() { 
    InitializeCriticalSection(&cs); 
} 

template<class T> 
SharedVector<T>::SharedVector(const CRITICAL_SECTION& r): cs(r) { 
    InitializeCriticalSection(&cs); 
} 

template<class T> 
void SharedVector<T>::PushBack(const T& value) { 
    EnterCriticalSection(&cs); 
    vect.push_back(value); 
    LeaveCriticalSection(&cs); 
} 

template<class T> 
void SharedVector<T>::PopBack() { 
    EnterCriticalSection(&cs); 
    vect.pop_back(); 
    LeaveCriticalSection(&cs); 
} 

template<class T> 
unsigned int SharedVector<T>::size() const { 
    EnterCriticalSection(&cs); 
    unsigned int result = vect.size(); 
    LeaveCriticalSection(&cs); 
    return result; 
} 

template<class T> 
T& SharedVector<T>::operator[](int index) { 
    EnterCriticalSection(&cs); 
    T result = vect[index]; 
    LeaveCriticalSection(&cs); 
    return result; 
} 

template<class T> 
SharedVector<T>::~SharedVector() { 
    DeleteCriticalSection(&cs); 
} 

在編譯時我調用EnterCriticalSection(&cs)LeaveCriticalSection(&cs)這樣一個問題:

 
'EnterCriticalSection' : cannot convert parameter 1 from 
'const CRITICAL_SECTION *' to 'LPCRITICAL_SECTION' 

我不知道什麼是錯。可能是你可以看到。只是因爲我總是以這種方式使用它,並沒有問題。包含windows.h

+0

不寫模板,但模板 pyon 2008-12-21 22:28:09

回答

20

只是聲明cs爲:

mutable CRITICAL_SECTION cs; 

否則取消對size()

const的條款進入一個關鍵部分修改CRITICAL_SECTION,並留下再次修改它。由於進入和離開關鍵部分不會使size()方法在邏輯上調用非const,所以我會說它保留const,並使csmutable。這是mutable被引入的情況的類型。

另外 - 看看Martin YorkJoe Mucchiello的建議 - 儘可能使用RAII來處理任何需要清理的資源。對於指針和文件句柄而言,這同樣適用於關鍵部分。

1

EnterCriticalSection不包含const參數。這是一個編譯錯誤,順便說一句,不是一個鏈接錯誤...

此外,你確定你想通過關鍵部分到你的ctor,然後讓ctor執行InitializeCriticalSection調用?如果你想分享你的關鍵部分,我想你會先初始化它,然後把它交出來。

0

因此,訪問權限有問題。 我使size()方法非const,現在可以。

+0

選定的答案(使用可變)肯定更好。 – 2008-12-21 21:49:14

1

我看你宣佈一個空的拷貝構造函數:

SharedVector(const SharedVector& rhs) {} 

正如我相信大家都知道,這個函數什麼也不做,而且還留下cs未初始化。因爲你的類包含一個CRITICAL_SECTION的實例,所以你必須確保不允許複製構造函數和賦值操作符調用,除非你要完全實現它們。您可以通過將以下聲明在類的private部分做到這一點:

SharedVector(const SharedVector &); 
SharedVector &operator=(const SharedVector &); 

這可以防止這些方法自動生成不正確版本的編譯器,同時也防止你叫他們在你寫的其他代碼(因爲這些只是聲明,而不是用{}代碼塊的定義)。

另外,正如Arnout提到的那樣,採用CRITICAL_SECTION&參數的構造函數似乎是錯誤的。你的實現是將傳入的關鍵部分複製到cs(這不是與CRITICAL_SECTION有效的關係),然後調用InitializeCriticalSection(&cs),它會覆蓋剛剛完成的副本並創建新的關鍵部分。對於在關鍵部分中通過的調用者,這似乎是通過有效地忽略所通過的內容來做錯誤的事情。

6

此外,上面的代碼不是異常安全的。
無法保證push_back()pop_back()不會拋出。如果他們這樣做,他們將永久鎖定您的關鍵部分。您應該創建一個在構造時調用EnterCriticalSection()並在銷燬時調用LeaveCriticalSection()的locker類。

此外,這使得你的方法更容易閱讀。 (見下)

class CriticalSectionLock 
{ 
    public: 
     CriticalSectionLock(CRITICAL_SECTION& cs) 
      : criticalSection(cs) 
     { 
      EnterCriticalSection(&criticalSection); 
     } 
     ~CriticalSectionLock() 
     { 
      LeaveCriticalSection(&criticalSection); 
     } 
    private: 
     CRITICAL_SECTION& criticalSection; 
}; 


// Usage 
template 
unsigned int SharedVector::size() const 
{ 
    CriticalSectionLock lock(cs); 
    return vect.size(); 
} 

你應該擔心的另一件事。確保當你銷燬擁有所有權的對象時,並且在銷燬期間沒有其他人試圖獲得所有權。希望你的DestoryCriticalSection()照顧這個。

2

我更喜歡在代碼中使用單獨的Acquisition對象。如果脆弱的,當輸入和Leave調用之間發生你的代碼的異常:

class CS_Acquire { 
    CRITICAL_SECTION &cs; 
public: 
    CS_Acquire(CRITICAL_SECTION& _cs) : cs(_cs) { EnterCriticalSection(cs); } 
    ~CS_Acquire() { LeaveCriticalSection(cs); } 
}; 

然後在您的類的方法你會它的代碼爲:

template <typename T> 
void SharedVector::PushBack(const T& value) { 
    CS_Acquire acquire(&cs); 
    vect.push_back(value); 
}