2015-12-20 29 views
5

W C++ 11 są obiekty klasy funkcji skrótu zadeklarowane w <functional> bezpieczne wątku? Np. Czy można bezpiecznie wywoływać tę funkcję z wielu wątków?C++ 11 std :: funkcja hash klasa obiektów bezpieczeństwo wątku

size_t hash1(const std::string& s) { 
    std::hash<std::string> str_hash; 
    return str_hash(s); 
} 

lub, jeśli ktoś ma globalny obiekt std::hash<std::string> str_hash_global;, wówczas jest to bezpieczne, aby wywołać tę drugą funkcję z wielu wątków?

size_t hash2(const std::string& s) { 
    return str_hash_global(s); 
} 
+0

Pomijając inne względy, upewnij się, że sam ciąg nie jest modyfikowany jednocześnie, podczas gdy jego wartość jest obliczana. –

Odpowiedz

6

Standardowa biblioteka obiecuje, że jeśli tylko wezwanie const -qualified funkcje członka na standardowej biblioteki obiektów, standardowy kod biblioteki nie powoduje wyścig danych (por [res.on.data.races ]).

Standardowy szablon std::hash, jak również wszelkie ich dopuszczalne specjalności, jak również wszelkie funktor użytkownika, pod warunkiem że spełnia wymogów Hash ([hash.requirements]) musi mieć const -qualified operatora połączeń ze względu na wymagania, a więc z wykorzystaniem biblioteki dostarczonego std::hash specjalizacje nie powinno spowodować wyścig. Co więcej, ze względu na [namespace.std], specjalizacje przewidziane przez program muszą spełniać te same wymagania.

Wreszcie mogę sobie wyobrazić, że można zazwyczaj używać gwarancji rasy chudości przez rekurencyjnie odwołując się do const połączeń: Jeśli wiele wątków jednocześnie wyszukać wartości w mapie, muszą używać const interfejs na mapy na powoływać się na wyżej biblioteki rządzić, ale wtedy mapa dostaje tylko do korzystania stałą wartość Hasher (lub prywatnej kopii), a więc to może tylko sam wykonać wyścigowych wolne obliczeń hash. To, czy istnieje nieskładny operator wywołujący połączenia, jest w tym momencie niemetryczne.

+0

'musi posiadać operator call const wykwalifikowanych powodu requirements' Która część standardu wymaga to? Szukałem czegoś mówiącego i nie mogłem go znaleźć. Istnieje "Zwrócona wartość zależy tylko od argumentu' k' na czas trwania programu ", ale to nie mówi bezpośrednio" operator() 'musi być const-kwalifikowany" –

+0

@IgorTandetnik: Mówi "' h' jest wartością (prawdopodobnie 'const')". –

+1

Ach, tak, więc tak. "' h' jest dokładną wartością typu (ewentualnie const) 'H'". Przypuszczam, że nadal nie ma bezwzględnie wyklucza klasę, która zapewnia dwa przeciążeniem 'operatora()', jeden i jeden const const (choć nie jest jasne, dlaczego ktoś miałby kiedykolwiek chcesz to zrobić). –

2

Stosuje się tu te same zasady "bezpieczeństwa wątków", jak w przypadku wszystkich typów std :: lib.

Gwarantuje się, że pierwsza wersja jest wątkowo bezpieczna, ponieważ między wątkami nie ma żadnych zmiennych.

Drugi z nich nie ma żadnych wyścigów danych, jeśli zostanie wywołany operator(): const. Nie jest sprecyzowane, czy implementacja zapewnia (oprócz potencjalnie nie-wątkowego) przeciążenie niestałe o wartości hash<T>::operator() oprócz (wymaganej) stałej. Jeśli twoja global_str_hash jest stała, lub rzucisz ją na const przed użyciem, to gwarantujesz, że będzie używana const operator().

Nie ma powodu, aby zrobić drugą wersję, jest po prostu głupia, ale w praktyce powinna być bezpieczna, ponieważ żadna standardowa implementacja biblioteki prawdopodobnie nie zapewni nadmiernego przeciążenia w postaci stałej o wartości hash::operator(), zapewnią one tylko przeciążenie stałą , który musi być bezpieczny dla wątków.

Powiązane problemy