C ++, discussioni, classi e conflitti

0

Questa è una domanda correlata al concetto.

Sto scrivendo un programma che esegue il polling per gli avvisi su vari dispositivi, ci sono due diversi tipi di avvisi che ho bisogno di sondare, rossi e arance.

Il mio approccio consiste nel creare due thread, ognuno dei quali esegue il polling del proprio tipo di avvisi in modo indipendente. Ho pensato di utilizzare thread perché entrambe le funzioni di polling devono essere progettate per essere completamente indipendenti e avere intervalli di tempo diversi per l'esecuzione, ad esempio:

  • Rosso: query API 3 volte, attende almeno 30 secondi tra i sondaggi (cerca di evitare i falsi positivi lasciandoli il tempo di svuotare prima di fare cose con gli avvisi)
  • Arancione: molto passivo, sondare una volta, attendere 10 minuti, quindi eseguire nuovamente il sondaggio, confrontare e fare cose (lo stesso principio dei rossi)

Ecco la domanda:

Ogni fase dell'elaborazione degli avvisi viene gestita tramite più classi e vari metodi, ad esempio: chiamate alla classe APIQUERYCLASS DATAPROCESSINGCLASS (fare cose con gli avvisi) - > DATAPARSINGCLASS (fai cose con gli avvisi) - > ANALYSISCLASS (fai cose con gli avvisi) - > ESCALATIONCLASS e così via ...

Ogni thread avrà un oggetto APIQUERYCLASS che creerà altri oggetti dalla catena di classi e userà i metodi.

È un approccio "sano"? I thread saranno veramente indipendenti? C'è un modo migliore per farlo, se sì, come?

EDIT:

Grazie per le risposte ragazzi Per aggiungere un po 'più di chiarezza:

######Worker.h #######
 // Worker.h is the top file where i'm thinking about creating the threads
#include "ToolName.h"
class Worker
{
    RedHandler()
    {
        Tool t_red;
        t_red.GetRedAlerts();
    }
    OrangeHandler() // exact same thing as RedHandler()
    {
       Tool t_orange;
       t_orange......
    }
}

##### ToolName.h #####

#include "Dataprocessing.h"
class Tool
{
    GetRedAlerts()
    {
        // query API , if query result is OK
        DataProcessing d;
        d.ProcessData();
    }
}

##### DataProcessing.h ######

#include "DataParser.h"
class DataProcessing
{
    DoStuff()
    {
     ....
    }
}

La catena funziona praticamente in questo modo fino all'escalation in cui si interrompe (salvo eccezioni) e torna al polling in Worker.h Lo stesso identico esiste per gli avvisi Orange dato che la query API restituisce la stessa identica struttura di JSON.

E mi piacerebbe mettere RedHandler () e OrangeHandler () nei loro thread

Spero che questo chiarisca un po 'la mia domanda

    
posta John 19.10.2018 - 09:22
fonte

2 risposte

0

Se queste chiamate API stanno bloccando le chiamate a una libreria di terze parti che non puoi controllare, questo modello di threading è approssimativamente il meglio che puoi fare.

Se la libreria API è tua e sta facendo solo lettura / selezione socket o altro, non hai davvero bisogno di più thread e puoi usare un Reactor a thread singolo. Anche se hai davvero bisogno di eseguire il polling di qualcosa piuttosto che attendere un socket, se il sondaggio è veloce o non bloccante, puoi comunque farlo su un callback del timer in un normale Reactor a thread singolo.

Non importa in quel caso che i thread non siano indipendenti, come lo sono i gestori - a meno che l'elaborazione non richieda troppo tempo, è probabile che ritarderà il prossimo timer. Per il tuo caso, l'elaborazione di un evento dovrebbe presumibilmente richiedere circa 30 secondi per sopportare qualsiasi rischio significativo di ritardare il prossimo evento.

APIQUERYCLASS -> DATAPROCESSINGCLASS -> DATAPARSINGCLASS -> ANALYSISCLASS ... -> ESCALATIONCLASS

A parte il nome orribile (che presumo sia un segnaposto), questa catena di callback profonda sembra strana. Sicuramente non vuoi che tutte queste classi siano co-dipendenti, quindi hai bisogno almeno di un Osservatore astratto o qualcosa per rompere la dipendenza. Tuttavia, è più facile testare e eseguire il debug di codice come

raw_event = APIQuery.getEvent();
parsed_event = DataParser.parse(raw_event);
DataProcessor.process(parsed_event);

rispetto alla versione concatenata

APIQuery.getEventAndThenParseProcessAnalyzeAndEscalateIt();

o anche

EscalationClass ec;
AnalysisClass ac(&ec);
DataParsingClass dpc(&ac);
DataProcessingClass dproc(&dpc);
APIQueryClass aqc(&dproc);

// ...

aqc.getEventAndTellObserversAboutIt();

Il modello di Osservatore diventa fragile anche se hai dipendenze relative agli ordini da parte dei tuoi osservatori.

    
risposta data 19.10.2018 - 12:11
fonte
2

Non esiste una risposta semplice alla tua domanda. Dipende dai dettagli delle tue lezioni. Prima di dare la risposta, devi chiarire alcuni punti:

  • I thread condividono i dati con altri thread? In tal caso, è necessario assicurarsi che i dati siano accessibili solo da un thread alla volta. Questo normalmente è fatto da oggetti di sincronizzazione (semafori, serrature, ecc.).
  • L'API utilizzata da APIQUERYCLASS è protetta da thread? Può essere chiamato da più thread contemporaneamente?
  • Tutte le API utilizzate dall'elaborazione dati sono thread-safe?

Potresti usare un approccio molto più semplice:

  • Nella maggior parte degli ambienti di runtime è possibile definire timer per intervalli di tempo specifici. Se è trascorso il tempo di un timer, emetterà un evento del timer. Il gestore eventi può quindi interrogare la tua API e avviare l'elaborazione dei dati.

  • La query API e l'elaborazione dei dati per entrambi i tipi di avvisi sarebbero quindi implementati nello stesso thread di lavoro. In questo modo puoi evitare possibili problemi di multi-threading delle tue API. Dato che gli intervalli di polling sono piuttosto lunghi, non dovrebbe esserci problema nell'utilizzare un thread di lavoro per entrambi.

Tecnicamente, un timer normalmente viene implementato come un thread separato che chiama i relativi gestori di eventi se il tempo è scaduto. Se il tuo ambiente di runtime non supporta i timer, dovresti implementarlo da solo.

    
risposta data 19.10.2018 - 10:36
fonte

Leggi altre domande sui tag