2012-10-30 4 views
9

Ecco lo scenario:C++ unordered_map STL, la sicurezza thread in cui ogni thread ha accesso solo ad essa la propria tasto assegnato e può modificare tale valore

1) utilizzando un unordered_map<int, vector<MyClass*>*> diciamo aggiungo i tasti 1, 2, ... 8
2) tutti i tasti sono impostati con un vettore all'inizializzazione del programma e nulla viene aggiunto o eliminato
3) Ho 8 thread, dove thread1 accede a chiave [1], thread2 accede a chiave [2], ... thread8 accesses key [8] (ovvero il numero di thread può accedere solo a quel numero di chiave e nessun'altra chiave)

A volte riassegno il valore vecto r * in un'altra raccolta allocata di heap. (cioè thread1 esegue key[1] = new vector<MyClass*>)

Credo che questo sia sicuro, sono corretto? In caso contrario, suppongo che userò concurrent_unordered_map.

grazie.

+0

Ho appena scoperto che '[contenitore.requirements.dataraces]/1' consente che questo venga fatto in un modo molto più bello di quello che avevo suggerito nella mia risposta originale. Per favore dai un'occhiata. – Mankarse

risposta

11

La risposta a questa domanda si può trovare in [res.on.data.races]/3:

Una funzione libreria standard C++ non deve modificare direttamente o indirettamente oggetti (1,10) accessibile da fili diversi thread corrente meno che gli oggetti sono accessibili direttamente o indirettamente tramite gli argomenti non const della funzione, incluso questo.

Inoltre, [container.requirements.dataraces]/1 stati:

A scopo di evitare corse di dati ([res.on.data.races]), implementazioni esaminano le seguenti funzioni di essere const: begin, end, rbegin, rend, front, back, data , find, lower_bound, upper_bound, equal_range, at e, tranne che in associazione o non ordinata a contenitori ssociative, operator[].

Dal unordered_map::operator[] è non-const, è legale per un'implementazione di modificare il unordered_map quando si verifica una chiamata a operator[]. Si dovrebbe invece usare unordered_map::find, che viene esplicitamente richiesto di essere trattati come const, e quindi non modificherà la unordered_map:.

map.find(key)->second = new vector<MyClass*>; 

(Come nota a margine, il vostro disegno suggerito sembra una ricetta per perdite di memoria Perché non renderlo un unordered_map<int, std::unique_ptr<vector<MyClass*>>>, o unordered_map<int,vector<MyClass*>>?)

+1

Voterò per la seconda alternativa (inutile mettere il vettore sull'heap da solo in generale). –

+0

Grazie per le risposte. Userò una concurrent_unordered_map e non metterò il vettore sullo heap (per semplicità, anche se lo sto gestendo correttamente nel codice). – GreekFire