2008-12-21 34 views
5

Tôi cần làm việc với mảng từ một số chuỗi, vì vậy tôi sử dụng PHẦN TIÊU CHUẨN để cung cấp cho nó quyền truy cập độc quyền vào dữ liệu.
Đây là mẫu của tôi:
Sự cố khi sử dụng 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); 
} 

Trong khi biên soạn tôi có một vấn đề đối với gọi EnterCriticalSection(&cs)LeaveCriticalSection(&cs):

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

Tôi không biết những gì là sai. Có thể bạn có thể thấy. Chỉ vì tôi luôn luôn sử dụng nó theo cách này và nó đã được alright. windows.h được bao gồm

+0

Đừng viết mẫu , nhưng mẫu pyon

Trả lời

20

Chỉ cần tuyên bố cs như:

mutable CRITICAL_SECTION cs; 

hoặc khác loại bỏ các khoản const trên size()

nhập một phần quan trọng làm thay đổi các CRITICAL_SECTION, và để lại sẽ thay đổi nó một lần nữa. Kể từ khi vào và rời khỏi phần quan trọng không thực hiện cuộc gọi phương thức size() một cách hợp lý non- const, tôi muốn nói rằng hãy để nó tuyên bố const và thực hiện csmutable. Đây là loại tình huống mutable được giới thiệu.

Ngoài ra - hãy xem các đề xuất của Martin YorkJoe Mucchiello - hãy sử dụng RAII bất cứ khi nào có thể để xử lý mọi loại tài nguyên cần được dọn dẹp. Điều này cũng hoạt động tốt cho các phần quan trọng vì nó cho con trỏ và xử lý tệp.

1

EnterCriticalSection không tham số const. Đó là lỗi biên dịch, BTW, không phải lỗi liên kết ...

Ngoài ra, bạn có chắc chắn muốn chuyển một phần quan trọng vào ctor của mình và sau đó yêu cầu cuộc gọi InitializeCriticalSection? Nếu bạn muốn chia sẻ phần quan trọng của mình, tôi cho rằng bạn sẽ khởi tạo phần đầu tiên và sau đó đưa nó ra.

0

vì vậy, điều gì đó sai với quyền truy cập. Tôi đã thực hiện phương thức size() không const và bây giờ nó là ok.

+0

Câu trả lời được chọn (sử dụng có thể thay đổi) chắc chắn là tốt hơn. –

1

Tôi thấy bạn đã tuyên bố một constructor sao chép rỗng:

SharedVector(const SharedVector& rhs) {} 

Như tôi chắc chắn rằng bạn đã biết, chức năng này không có gì, và nó cũng rời cs uninitialised. Bởi vì lớp của bạn chứa một cá thể của một CRITICAL_SECTION, bạn phải chắc chắn không cho phép các hàm tạo bản sao và các cuộc gọi toán tử gán trừ khi bạn sẽ triển khai chúng hoàn toàn. Bạn có thể làm điều này bằng cách đặt các tờ khai sau trong phần private của lớp học của bạn:

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

Điều này ngăn cản các trình biên dịch từ phiên bản tự động tạo ra không chính xác của phương pháp này, và cũng có thể ngăn bạn gọi họ trong mã khác bạn viết (vì đây chỉ là các khai báo, nhưng không phải là các định nghĩa với các khối mã {}).

Ngoài ra, theo số Arnout được đề cập, hàm tạo có tham số CRITICAL_SECTION& có vẻ sai.Việc triển khai của bạn là sao chép phần quan trọng đã được chuyển đến cs (không phải là điều hợp lệ để thực hiện với CRITICAL_SECTION), sau đó gọi InitializeCriticalSection(&cs) để ghi đè bản sao bạn vừa thực hiện và tạo một phần quan trọng mới. Đối với người gọi đã qua một phần quan trọng, điều này dường như làm điều sai trái bằng cách bỏ qua hiệu quả bất cứ điều gì đã được thông qua.

6

Ngoài ra mã ở trên không phải là Ngoại lệ an toàn.
Không có gì đảm bảo rằng push_back() pop_back() sẽ không ném. Nếu họ làm họ sẽ rời khỏi phần quan trọng của bạn vĩnh viễn bị khóa. Bạn nên tạo một lớp locker có tên gọi là EnterCriticalSection() khi xây dựng và LeaveCriticalSection() trên sự hủy diệt.

Điều này cũng giúp phương pháp của bạn dễ đọc hơn rất nhiều. (xem bên dưới)

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(); 
} 

Một điều khác bạn nên lo lắng. Hãy chắc chắn rằng khi bạn phá hủy đối tượng bạn có quyền sở hữu và không ai khác cố gắng nắm quyền sở hữu trong quá trình hủy diệt. Hy vọng rằng DestoryCriticalSection của bạn() sẽ chăm sóc điều này.

2

Tôi thích sử dụng đối tượng Chuyển đổi riêng trên mã của bạn. Mã của bạn nếu mong manh khi một ngoại lệ xảy ra giữa các Nhập và Rời khỏi cuộc gọi:

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

Sau đó, trong phương pháp lớp học của bạn, bạn sẽ mã hóa nó như:

template <typename T> 
void SharedVector::PushBack(const T& value) { 
    CS_Acquire acquire(&cs); 
    vect.push_back(value); 
} 
Các vấn đề liên quan