Come faccio a eliminare i riferimenti ciclici in questo design?

2

Ho 3 classi: Riunione , Progetto e Agenda .

  • Un progetto contiene tutti i tipi di informazioni + un elenco di riunioni.
  • L' Agenda contiene un elenco di riunioni imminenti.
  • Un Riunione contiene alcuni dati + un elenco di progetti che sono stati discussi qui.

L'agenda verifica le prossime riunioni. Quando ne trova uno, chiama il suo metodo Meeting :: alarm () , che a sua volta visualizza i dati che ottiene dall'elenco dei progetti a cui questo meeting fa riferimento.

Le riunioni possono essere referenziate in un progetto senza essere programmate nell'agenda , ma non ha senso avere un riferimento a una riunione nell'agenda se non è contenuto in un progetto.

Poiché l' agenda può essere analizzata in un thread mentre il thread principale elimina un progetto , ho fatto in modo che sia Agenda sia Project usino i puntatori condivisi nelle riunioni, in modo che l'analisi thread non trova un puntatore pendente.

Nel distruttore del Progetto , chiedo a Agenda di controllare le riunioni relative a questo progetto per ripulire quelli che non hanno altri progetti correlati.

Ecco il mio problema:
Che tipo di struttura dati dovrebbe essere il membro Meeting :: parentProjects?
Se un meeting viene chiamato dall'agenda mentre il suo progetto viene eliminato e genitoreProjects è un semplice contenitore di puntatori grezzi, potrei avere un penzoloni qui. Ma non posso neanche usare un shared_ptr per Project, dato che farebbe una dipendenza ciclica ... Mi sembra che sia inutilmente complicato.

Come potrei refactoring? Nota: I devono mantenere i 2 thread.

    
posta adanselm 06.09.2013 - 15:22
fonte

2 risposte

1

Il modo in cui ti stai ponendo questa domanda sembra implicare che ti aspetti che la risposta debba essere nella struttura dei dati. Non sono sicuro che lo sia.

Il problema chiave è che si desidera modificare e accedere ai dati contemporaneamente e ci si è resi conto che il tentativo di accedere a dati parzialmente modificati non è corretto.

Ci sono diverse strategie che puoi fare con questo.

  1. In un ambiente in cui tutte le azioni sui dati sono veloci e c'è a basso volume di modifiche è possibile utilizzare un Mutex (o se vuoi, semafori leggeri) e forza la seconda azione per bloccare fino al completamento della prima azione.

  2. Se queste azioni possono richiedere un tempo notevole per verificarsi. (ad esempio 1/2 al secondo o di più) allora sarei tentato di creare una coda di azioni e di avere un tuo i thread attuali posizionano le attività sulla coda e hanno un terzo thread eseguite queste azioni in sequenza, chiamando una callback sull'attività in notifica il thread originale è stato completato.

In termini semplici, il problema principale che si presenta è l'accesso simultaneo ai dati, piuttosto che la struttura dei dati, quindi è necessario risolverli gestendo l'accesso, piuttosto che con un approccio basato sulla struttura dei dati pura.

    
risposta data 06.09.2013 - 16:15
fonte
0

Sebbene condivido le preoccupazioni di Tolomeo riguardo al design, c'è anche una risposta semplice.

Meeting::parentProjects dovrebbe essere un weak_ptr. Ciò richiede che la durata del progetto sia controllata da shared_ptr in primo luogo.

If a Meeting gets called by the Agenda while its Project is being deleted ...

rompiamolo. O:

  1. La chiamata viene chiamata, mentre il progetto principale è ancora attivo (shared_ptr ha un conteggio diverso da zero)

    • chiamando weak_ptr::lock produce un shared_ptr che mantiene vivo il Progetto genitore per la durata di questa chiamata
    • quando termina la chiamata corrente, il shared_ptr che implementa il blocco temporaneo esce dall'ambito

    o

  2. La riunione viene chiamata dopo che il progetto principale è stato distrutto (shared_ptr ha zero refcount)

    • chiamare weak_ptr::lock produce un shared_ptr vuoto: puoi testarlo e decidere come gestirlo

Quindi, la Riunione non manterrà mai vivo il suo Progetto tranne quando lo sta usando e il Progetto non può essere cancellato mentre il Meeting lo sta usando.

    
risposta data 06.09.2013 - 16:56
fonte

Leggi altre domande sui tag