2012-10-08 2 views
2

내 질문 : 데이터 무결성에 대한 걱정없이 더 나은 방법으로 설명 된 클래스를 어떻게 디자인 할 수 있습니까?데이터 컨테이너 디자인 C++

나는 Player-Container와 Player 클래스가 있습니다. 플레이어 컨테이너는 많은 스레드를위한 중앙 집중식 플레이어 "데이터 컨테이너"입니다.이 플레이어는 모두이 클래스에 대한 포인터를 가지고 있습니다. TBB 라이브러리는 읽기 전용 및 쓰기 용 잠금 메커니즘을 제공합니다. 나는 "최상위 - 컨테이너"에 그 기능을 가지고 잘못된 것 같습니다하지만이 때문에 주위에 오지 보인다 개발 더 나를 위해 지금

Class: Player-Container 
Method: CreatePlayer, RemovePlayer , LoginUser, VerifyUser 

Class: Player 
Method: None its a pure data container 

: 나는 어떤 의사 코드 내 현재의 디자인을 반영해야 컨테이너는 병렬 액세스로 인해 사용자를 수정할 수 없도록 객체를 잠글 수 있습니다 (예 : 사용자가 무언가를 작성하고이 요청을 두 번 보내고 리소스가 한 번이 아닌 두 번 줄어 듭니다).

내가하고 싶은 것 : 난 그냥 "인덱스"로 hash_map을 사용하고 "플레이어"수준을 구축해야

Class: Player-Container 
Method: CreatePlayer, RemovePlayer 

Class: Player 
Method: LoginUser, VerifyUser,.... 

내 문제는, 어떻게 그것을 달성하고 여전히 데이터 무결성이 저장 될 않습니다 잠금? 몇 가지 의견과 제안이있는 것이 좋습니다. 플레이어 클래스에 대해 PlayerContainer가 실제로 알아야 할 버그가 가장 많이 들었습니다. 컨테이너에서 많이 코딩해야하는 속성을 변경하면 버그가 발생합니다.

분명하지 않은 것으로 여겨지면 문의하십시오.

답변

2

실제로 여기에 두 가지 질문이있는 것 같습니다. & 잠그고 캡슐화와 응집력 주위에 약간의 디자인 긴장감이 꽤 있습니다.

api 사용자의 경우 플레이어를 추가/제거하기 위해 'Player-Container'클래스 만 처리하면 좋을 것 같습니다.

플레이어 컨테이너에서 앞면을 유지하는 방법을 사용하여 작업을 단순하게 유지하는 방법을 고려해 보겠습니다. 그러나 Player-Container 클래스 내에 아주 작은 코드가 있음을 보장하기 위해 도우미 클래스 나 도우미 함수를 구현할 수도 있습니다. 당신이 그것을 원한다면 플레이어 클래스에 메소드로 추가 할 수도 있습니다.

Scott Meyer 's의 this article을 어디에서 읽을 지 모르겠다면 시간 가치가있을 것입니다.

두 번째 질문은 잠금에 관한 것입니다. 즉, 자물쇠가 컨테이너 또는 플레이어 클래스에서 어디에 있어야하는지입니다.

여기에는 선택 항목이 있지만 개별 클래스의 컨테이너와 데이터를 모두 동기화해야한다는 점을 기억하십시오. 따라서 플레이어를 보관하기 위해 동시 컨테이너를 사용하고 플레이어 컨테이너 클래스의 헤비급 잠금을 피하는 경우 플레이어 클래스가 동기화되도록해야합니다. 특히 여러 스레드가 동일한 플레이어에서 작동하도록 허용하는 경우 특히 그렇습니다.

이렇게하면 플레이어의 개별 메소드가 아니라 플레이어 전체가 호환되지 않는 기능을 인터리브하지 않도록하는 것이 더 중요합니다. LoginUser가 동일한 사용자의 RemoveUser와 동시에 실행되는 것을 원하지 않는 경우, 사용자가 일련 번호를 지정하고 차례대로 실행하기를 원할 것입니다.

+0

감사합니다 레코드를 검색하여 잠금을 설정 한 후 플레이어에서 실제로 암호를 확인하는 메서드를 호출 한 후 (실제로 이상하게 보였던 이유는 플레이어 -화물을 사용하여 개체를 잠그고 함수를 실행 한 후 제대로 해제 할 수 있음) 어쩌면 할 수있는 일입니다. –

1

TBB 라이브러리의 특정 기능에 대해서는 알지 못하지만 일반적으로 Player 인스턴스를 노출시키기위한 클래스 SharedObject<Player>과 같은 것을 만들 수 있습니다 (예 : 읽기/쓰기 뮤텍스). 잠금을 올바르게 적용하는 SharedObjectAccessor 객체를 사용하여 액세스합니다.

template<typename T> 
class SharedObjectAccessor; 

template<typename T> 
class SharedObject 
{ 
public: 
    SharedObject(const T& initial = T()) 
    : managedObject(initial) 
    {} 

private: 
    friend class SharedObjectAccessor<T>; 

    const T& read() const { return managedObject; } 
    T& write() { return managedObject; } 
    ReadWriteMutex lock; 
    T managedObject; 
}; 

template<typename T> 
class SharedObjectAccessor 
{ 
public: 
    SharedObjectAccessor(SharedObject<T>& ref) 
    : sharedObject(ref) 
    {} 

    ~SharedObjectAccessor() { sharedObject.lock.unlock(); } 

    const T& get() const 
    { 
     sharedObject.lock.lock_read(); 
     return sharedObject.read(); 
    } 

    T& set() 
    { 
     sharedObject.lock.lock_write(); 
     return sharedObject.write(); 
    } 

private: 
    mutable SharedObject<T>& sharedObject; 
}; 
의 TBB 라이브러리 읽거나 플레이어 - 컨테이너는 예를 들어, "LoginUser"가 만 취득 할 순간에 읽기/쓰기하려는 경우에 따라 "플레이어"기록을 잠급니다 솔루션 릭에 대한
+0

이것은 실제로 이미 구현되어 있습니다. tbb 데이터 구조는 실제로 데이터 구조의 객체를 수정하기위한 읽기/쓰기 접근자를 제공합니다. 내가 tbb가 없을 때마다 유용 할 수있는 예제를 제공해 주셔서 감사합니다. –