Coda di blocco per la sincronizzazione basata su token

0

Attualmente sto cercando una buona soluzione per il seguente caso d'uso in C ++ (preferibilmente C ++ 11 o C ++ 14):

Il programma sta eseguendo un server con una connessione TCP. Altri client possono connettersi in qualsiasi momento a questo server e attivare un calcolo (che richiede alcuni secondi). Dovrebbe essere eseguito solo un calcolo alla volta. Altre chiamate di calcolo devono essere accodate e la chiamata viene bloccata fino a quando il risultato non è pronto. Se il calcolo corrente fallisce, tutti gli altri calcoli non devono essere eseguiti e restituiti immediatamente.

Ecco alcuni esempi di codice che descrivono i passaggi:

// the first client calling this function should get the token,
// all others have to wait until first one finished.
// Then the next in the queue can continue
bool gotCalculateRequest() {

    // blocks until currently running calulation finished.
    // If getToken returns false, do not queue this request for calculation
    if (!getToken()) {
        // notify client that calculation was aborted
        return false;
    }

    // now we have the token and we can start calculation

    if (!doStuff()) {
        // give back the token and abort other requests in the queue
        freeTokenAndAbortOthers();
        return false;
    }

    // give back the token. This should automatically notify the next waiting request to continue
    freeToken();
    return true;
}

Ho pensato di utilizzare std::promise e std::future per quello: quando una richiesta arriva in future viene aggiunta a una coda e la chiamata attende in futuro. Al termine del calcolo precedente utilizza la promessa di notificare il prossimo chiamante. Riesci a pensare a una soluzione migliore?

    
posta Stefan Profanter 25.02.2016 - 10:39
fonte

1 risposta

1

Al posto del token extra e così via, gestisco le cose sul back-end. In altre parole, quando arriva una richiesta, è sufficiente inserirla nella coda.

Il back-end (la parte che richiama le richieste dalla coda) tira solo gli oggetti ed esegue i calcoli. Quando / se si verifica un errore, imposta semplicemente un flag failed e da quel momento in poi restituisce false (o qualsiasi altra cosa che deve fare per segnalare un errore).

bool do_calculation(calc_spec const &input, result_type &output) { 
    static bool failed;

    if (failed)
       return false;

    output = calculation_impl(input);
    if (calc_failed(output)) {
         failed = true;
         return false;
    }

    return true;
}
    
risposta data 25.02.2016 - 20:26
fonte

Leggi altre domande sui tag