2013-01-18 7 views
5

Sono nuovo a D e sto scrivendo un semplice server multithreading per esercitarsi. Un paradigma comune per avviare i thread del gestore client in C è passare il descrittore di file del socket appena accettato() in pthread_create(), ma D's st.c.current.savewn() non mi permetterà di passare il Socket perché è mutabile e accessibile da due thread.Alias ​​di dati locali del thread mutabili non consentiti

Ovviamente, in realtà non voglio un socket immutabile (è per questo che non voglio scriverlo nel thread principale a meno che non sia necessario) - Voglio passare uno mutabile e averlo uscire dal campo di applicazione nella discussione principale. Come andrei su questo? Dovrei (/ posso) usare tid.send(s) per permettere al thread di usare il socket? Per qualche ragione mi sembra molto schifoso.

Il mio codice ora:

void main() { 
    Socket listener = new TcpSocket; 
    ... 
    for (;;) { 
     Socket s = listener.accept(); 
     scope(exit) s.close(); 

     auto tid = spawn(&clientHandler, s); 
    } 
} 

void clientHandler(Socket s) { 
    ... 
} 

che produce: Errore: statici assert "alias ai dati thread-local mutevoli non consentita". ... istanziato da qui: spawn! (Socket)

risposta

6

è necessario lanciare la presa di comune e di nuovo nel ClientHandler

auto tid = spawn(&clientHandler, cast(shared) s); 

void clientHandler(shared Socket s) { 
    Socket sock = cast(Socket)s; 
    scope(exit)sock.close(); 
} 

la ragione di questo è che tutte le variabili locali sono implicitamente filetto locale se non specificato shared, e solo i riferimenti a Can condiviso o immutabili essere passato come argomento a spawn (o send) mentre roba passato per valore (le strutture senza riferimenti e primitivi) va bene

anche si dovrebbe mettere la stretta int il gestore come con l'implementazione corrente della presa sarà probabilmente chiuso prima della newl y thread generato ha una possibilità di eseguire

+0

Ha funzionato perfettamente, e grazie per le informazioni aggiuntive! È questo il modo idiomatico di fare qualcosa di simile, o c'è un modo migliore? Il casting in D è decisamente come se stessi facendo qualcosa di sbagliato (cioè in opposizione a C). – Dan

+0

@Dan scorso ho controllato (un anno fa) la semantica 'condivisa' dove non ben definita, non so se sia cambiata da allora –

+1

Non è cambiato nulla rispetto a quello. Ma l'intera comunità D sta aspettando che 'shared' diventi ben definito. – DejanLekic

1

Il problema qui non è il socket, che è una variabile locale. È il clientHandler, la cui dichiarazione non è stata mostrata, ma chiaramente è thread-local come si dice nel messaggio di errore, quando dovrebbe essercene uno nuovo per socket accettato. Il suggerimento è la parola "alias", che si riferisce all'operatore &.

+0

Spiacente, ho chiarito la domanda aggiungendo la dichiarazione di 'clientHandler()'. È una funzione dichiarata nell'ambito globale, quindi forse sono più confuso di quanto pensassi all'inizio, ma dubito che siano i dati locali del thread in questione. – Dan

+0

@Dan Ok, allora che cos'è? Non il socket, a meno che scope() non abbia un qualche effetto su questo, qualunque cosa faccia: non sono un 'd' esperto. – EJP

+0

'scope (exit)' assicura che 's.close()' sarà chiamato alla fine di questo scope, proprio come la parola chiave 'finally' in Java. Certo, non ha un buon senso in cui l'ho aggiunto, ma rimuoverlo o posizionarlo altrove non ha alcun effetto sull'errore di compilazione. Ho letto che [le variabili globali] (http://dlang.org/migrate-to-shared.html) sono automaticamente convertite in thread-locals, ma ciò non dovrebbe applicarsi alle funzioni, e in ogni caso sostituendo l'alias della funzione con un (locale, penso) espressione lambda risultati nello stesso errore pure. – Dan

Problemi correlati