PDA

Visualizza la versione completa : [C++] Delete di un oggetto da + thread


lolide
05-01-2014, 16:10
Salve ragazzi,
avrei un dubbio a proposito di un problema riguardo al delete di un oggetto che potrebbe avvenire anche in contemporanea da + thread.

Il progettino è un semplice programmino client-server TCP tramite i winsock (quindi su windows).
Utilizzo select() per la comunicazione e quindi un'architettura ad eventi. Ho un thread separato dove eseguo la select sui vari socket (il socket del server ed X client connessi al server). Il server mantiene una sua lista di client connessi.

La questione che non capisco come gestire al meglio è il momento della chiusura della connessione del client. Cioè:
- ho il thread della select che, in caso riceva una notifica di chiusura del client, richiama client->close() che andrebbe a chiudere la socket di connessione del client e dovrebbe fare il delete dell'oggetto Socket del client.
- quando il server viene chiuso, il server fa sempre client->close() su tutti i suoi client in lista che chiude la socket di connessione del client e dovrebbe fare il delete dell'oggetto Socket del client.

Quando chiudo il server ed un client notifica la disconnessione nello stesso momento della chiusura del server, 2 thread cercano di fare client->close() e spesso si verifica un seg fault perchè ovviamente entrambi fanno il delete e quello che lo fa per secondo va a cancellare un oggetto già cancellato.

Secondo voi come posso fare a "sincronizzare" i 2 delete..? probabilmente dovrei tenere un flag fuori dall'oggetto così da capire se l'oggetto è stato già deletato e non cancellarlo di nuovo ma mi sembra schifosa come soluzione. Non è una domanda "tecnica" sulla programmazione, piu' che altro chiedo un consiglio sul design..

grazie in anticipo :)

MItaly
05-01-2014, 16:29
Mi lascia perplesso il fatto che a questi oggetti si acceda in maniera così disinvolta dai due thread... devi stabilire per ogni oggetto (1) chi è l'oggetto "proprietario" (che si occupa della sua cancellazione) e (2) in che thread "vive" (o almeno, in che thread nasce e muore). Mischiare tutto in questa maniera non ti può dare che problemi.

Nello specifico, perché il server fa client->close() se già ci pensa l'altro thread quando riceve la notifica di disconnessione?

linoma
05-01-2014, 16:34
Potresti usare una logica simile ogni thread decrementa un contatore alla cancellazione e solo quando vale 0 cancelli l'oggetto. Naturalmente il contatore viene incrementato ad creazione.

MItaly
05-01-2014, 16:39
Be' se vuoi usare uno schema di reference counting allora semplicemente usa uno smart pointer tipo std::shared_ptr (disponibile da C++11 in poi) o boost::shared_ptr (identico, ma utilizzabile in revisioni precedenti del C++).

lolide
05-01-2014, 17:02
Potresti usare una logica simile ogni thread decrementa un contatore alla cancellazione e solo quando vale 0 cancelli l'oggetto. Naturalmente il contatore viene incrementato ad creazione.

Il fatto è che non è detto che il client chiuda la connessione al server... avendo 2 thread che ci accedono, mi dovrei aspettare 2 chiamate al close(), ma se il client lato suo non richiede la chiusura della connessione il client->close() dal thread della select non arriverà mai e non farà mai il delete...


Mi lascia perplesso il fatto che a questi oggetti si acceda in maniera così disinvolta dai due thread... devi stabilire per ogni oggetto (1) chi è l'oggetto "proprietario" (che si occupa della sua cancellazione) e (2) in che thread "vive" (o almeno, in che thread nasce e muore). Mischiare tutto in questa maniera non ti può dare che problemi.

Nello specifico, perché il server fa client->close() se già ci pensa l'altro thread quando riceve la notifica di disconnessione?

Hai ragione.
Il problema di gestire tutto da un solo thread è che mi porterebbe a scegliere:
- Il delete del socket si fa SOLO se il client richiede la disconnessione, quindi dal thread della select().
- SOLO al momento della chiusura del server, quindi dal thread principale che gestisce il server.

Per la prima, non vorrei obbligare il client ad eseguire la disconnessione prima di fare lo shutdown del server.
Per la seconda, se il mio server rimanesse in vita per tanto tempo e si connettessero tanti client, dovrei tenere in memoria gli oggetti di ogni client anche se ormai si è disconnesso fino a quando il server rimane up. A meno di fare qualcosa che ad intervalli pulisca questa lista...

Loading