2013-04-24 15 views
8

Mam ConcurrentQueue klasę, która opiera się na dostarczonych przez użytkownika pojemnik z konstruktora tak ...Jak mogę zablokować muteks na liście inicjalizatora?

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue) {} 

Ale muszę zablokować other „s mutex gdy jest on jednocześnie kopiowane.

Wariant 1:

Więc nie mogłem użyć konstruktora kopii w ogóle, a nie ...

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.m_Queue) 
{ 
    std::lock_guard<std::mutex> lock(other.m_Mutex); 
    m_Queue = other.m_Queue; 
} 

Ale nie mogę zagwarantować, że zadanie kopiowania i skopiuj budowę są równoważne funkcjonalność.

Opcja 2:

mogę mieć prywatną metodę ...

std::queue<T, Container> GetQueue() const 
{ 
    std::lock_guard<std::mutex> lock(other.m_Mutex); 
    return m_Queue; 
} 

A potem w konstruktorze to zrobić ...

ConcurrentQueue(const ConcurrentQueue& other) : m_Queue(other.GetQueue()) {} 

Ale to potencjalnie (w zależności od optymalizacji) używa konstruktora kopiowania m_Queue raz i konstruktora ruchu raz. Nie mogę też zagwarantować, że kopia i ruch są odpowiednikami tylko kopii. Dodatkowo dostarczony przez użytkownika pojemnik może być dziwaczny i podlegać kopiowaniu, ale niemożliwy do zrealizowania, co również powoduje problemy z tym podejściem.

Co mam zrobić?

Odpowiedz

9
ConcurrrentQueue::ConcurrrentQueue(
     ConcurrrentQueue const& other) 
    : m_Queue((std::lock_guard<std::mutex>(other.m_Mutex), 
       other.m_Queue)) 
{ 
} 

powinien działać.

+0

Czy uważasz, że powinno to zawsze być zrobione w ten sposób? – 0x499602D2

+0

@ 0x499602D2 W rzeczywistości uważam, że należy unikać tej sytuacji. Nie wiem wystarczająco dużo o twoim aktualnym kontekście lub problemie, który próbujesz rozwiązać, by zaproponować alternatywne rozwiązania, ale wiem, że nigdy nie musiałam używać czegoś takiego. W rzeczywistości nie mogę myśleć o przypadku, w którym skopiowałem kontener między wątkami. –

1

Zablokuj, utwórz kopię zawartości, a następnie zamień ją z członkiem. Przynajmniej to jest najłatwiejszy i najczystszy sposób IMHO. Innym, mniej czystym sposobem jest użycie operatora przecinka: (a, b), który daje b, ale jeśli a jest blokiem o zakresie, tymczasowy będzie działać do następnego punktu sekwencji, tj. Dopóki nie użyjesz b do zainicjowania lokalnej kopii.

Powiedział, że są dwie rzeczy do rozważenia:

  • Może kopiowanie nie jest taki sprytny pomysł i tak swoją prace projektowe, a także jeśli po prostu wyłączyć kopiowanie.
  • Jeśli masz dostęp do kolejki i możesz ją odczytać do skopiowania, czy to nie oznacza, że ​​muteks musi być już zablokowany? Jeśli nie, to w jaki sposób na pewno chcesz skopiować kolejkę? Nie kwestionuję, że istnieją odpowiedzi uzasadniające projekt, ale jest to niezwykłe.
Powiązane problemy