2013-03-17 24 views
6
std::promise<int> p1; 
auto f = p1.get_future(); 

{ 
    std::promise<int> p2(std::move(pr)); 
} 

bool valid = f.valid(); // true 
f.wait(); // does not throw, or fail, but returns immediately 
f.get(); // throws an exception 

C'è un modo per verificare se un futuro sta per lanciare prima di chiamare get? Speravo che valid controllasse ... Non sono proprio sicuro di come ottenere valid per restituire false. Distruggere il promise senza impostare un valore non lo fa.futures, promesse ed eccezioni

+2

Un 'std :: future' può essere visto come un osservatore allo stato di un' std :: promise'. Se la promessa è andata, il futuro sta penzolando. Non è UB come dice lui, ma ottieni un'eccezione 'std :: broken_promise', perché la promessa non può mai essere soddisfatta. – Xeo

+0

valido restituirà false una volta che hai chiamato 'get' o' share' una volta. – inf

+1

[futuro :: valido] (http://en.cppreference.com/w/cpp/thread/future/valid) dice "Controlla se il futuro si riferisce a uno stato condiviso". Se la promessa è andata e il valore non è mai stato impostato, non significa che non esiste uno stato condiviso? – David

risposta

5

C'è un modo per verificare se un futuro sta per gettare prima di chiamare ottenere?

No, poiché sarebbe in qualche modo uguale ricevere il valore memorizzato in futuro.

Spero valido verrebbe controllato ... Non sono davvero sicuro di come ottenere valido per restituire falso.

valido restituirà true se il futuro si riferisce ad uno stato condiviso che può essere creato solo da std::async, std::packaged_task o std::promise. Un controesempio sarebbe un valore predefinito creato std::future. Valido sarà anche falso una volta che hai chiamato get o share su un futuro valido (= = true) valido una volta.
La chiamata a qualsiasi altra funzione di valid o l'operatore di assegnazione spostamento su un valore non valido (valido == falso) futuro è UB.

Distruggere la promessa senza impostare un valore non lo fa.

No, come detto sopra non è il punto di validità, poiché il futuro si riferisce ancora allo stato condiviso solo che l'altra parte - la promessa - non è stata soddisfatta. Se sulla distruzione di una promessa non è stato impostato alcun valore o eccezione, viene impostata un'eccezione per indicare che la promessa non è stata corretta.

1

C'è un modo per controllare se un futuro sta per lanciare prima di chiamare ottenere?

La tua domanda è equivalente a:
Esiste un modo per verificare se una funzionesta per gettare prima di chiamarlo?

La risposta a entrambe le domande è, in generale, n.

considerare:

int func_that_might_throw() 
{ 
    if (rand() % 2) 
    throw 1; 
    return 0; 
} 

std::future<int> f = std::async(&func_that_might_throw); 

int result = f.get(); 

La chiamata async potrebbe tornare una funzione differita, nel qual caso la funzione non ha nemmeno eseguito fino alla chiamata get(), quindi, in generale, non c'è modo di dire in anticipo se la il risultato sarà un valore o un'eccezione. (È possibile rilevare una funzione differita chiamando f.wait_for(std::chrono::seconds(0)), ma async potrebbe non restituire una funzione di differita, e in tal caso la funzione potrebbe ancora essere in esecuzione in modo asincrono quando si tenta di controllare se ha un un'eccezione memorizzati, in modo che ci si deve controllare se è pronto e ha un'eccezione memorizzato, quindi il controllo solo diventa molto disordinato.)

una valida future con uno stato condiviso che è pronto ha un risultato, che è un valore o di un'eccezione. Entrambi sono risultati validi.Se non si desidera gestire le eccezioni, è necessario assicurarsi che l'eccezione non sia impostata nello stato condiviso in primo luogo.

+0

In futuro :: get non ci deve essere qualcosa come 'if (IsReady()) restituisce valore; altrimenti se (! PromiseExists()) viene interrotto: promise; '? Quindi potrebbe esserci una funzione che restituisce '! IsReady() &&! PromiseExists()'. Non capisco davvero perché questo caso non sia adatto per essere valido (... 'valid() == false') ma i progettisti non lo hanno fatto. – David

+0

Per parlare brevemente del mio caso d'uso: avvio un gruppo di task asincroni (usando la mia coda asincrona, non std :: async) ogni frame (~ 20). Il prossimo frame voglio cancellare qualsiasi attività che non è stata ancora eseguita e spingere un nuovo gruppo di 20 per essere potenzialmente eseguito. Voglio che la mia coda asincrona mi restituisca un futuro quando spingo un lavoro in esso, ma se non posso dire che un lavoro è stato cancellato o no usando il futuro non posso usare il futuro, o dovrò avvolgeteli. Posso farlo chiamando get e rilevando l'eccezione, ma è troppo lento. – David

+0

Al tuo primo commento: Il 'broken_promise' viene impostato quando la promessa scompare, non quando si cerca il risultato. 'valid()' significa "ha stato condiviso" e il futuro ha ancora uno stato condiviso, come è stato affermato più volte. –