2012-01-16 20 views
9

Senza utilizzare boost::thread e boost::bind direttamente, esiste un modo per implementare l'equivalente del seguente codice?Boost equivalente di std :: async()

std::string func() 
{ 
    std::string str("Hello from async task!"); 
    return str; 
} 

int main() 
{ 
    auto ftr = std::async(&func); 
    std::cout << "Hello from main!"; 
    std::string str = ftr.get(); 
    std::cout << str << std::endl;  
    return 0; 
} 

In particolare, questa parte: auto ftr = std::async(&func);?

risposta

8

Certamente. È sufficiente rendere async<T>(std::function<T()>) restituire un futuro che invoca func() nel momento in cui viene atteso per la prima volta. Non otterrai alcuna asincronicità, ma l'API in realtà non garantisce che la funzione verrà eseguita in modo asincrono, quindi non è un problema.

Se si ha accesso a una libreria di threading specifica del sistema operativo, è possibile ovviamente utilizzare anche questa.

Nota, tuttavia, che la memorizzazione di eccezioni non può essere implementata in modo portabile; richiede un supporto aggiuntivo dall'implementazione C++, a meno che non sia possibile limitare le eccezioni supportate a quelle con una funzione clone polimorfica. Vedere this question per ulteriori informazioni.

L'implementazione finale potrebbe apparire un po 'come questo (non testata):

// NOTE - we assume a SINGLE THREADED environment 

template<typename T> 
class myfuture_detail { 
    mutable boost::variant<T, boost::function<T()> > val; 

public: 
    myfuture_detail(const boost::function<T()> &f) 
     : val(f) { } 

    const T &get() const { 
     if (T *t = boost::get<T>(&val)) { 
      return *t; 
     } else { 
      boost::function<T()> f = *boost::get<boost::function<T> >(&val); 
      val = f(); 

      T *t = boost::get<T>(&val); 
      assert(t); 

      return *t; 
     } 
    } 
}; 

template<typename T> 
class myfuture { 
    boost::shared_ptr<myfuture_detail<T> > ptr; 

public: 
    myfuture(const boost::function<T()> &f) 
     : ptr(boost::make_shared<myfuture_detail<T> >(f)) 
    {} 

    myfuture() { } 

    const T &get() const { 
     return ptr->get(); 
    } 
}; 
+0

Grazie per la risposta dettagliata! Sono una sorta di novizio in termini di meta-programmazione, quindi non sono sicuro di come questo possa essere usato nello stesso modo dell'esempio nell'OP ... Ad esempio, dove sarebbe l'equivalente di 'std :: async () vieni dentro? La classe 'myfuture' deve in qualche modo essere associata a un' boost :: thread'? –

+1

Questo non è in realtà asincrono. Il contratto 'std :: async' in realtà non garantisce che la routine asincrona verrà eseguita ... in modo asincrono. Considera se il thread asincrono non è mai programmato finché non arrivi a ".get()" - è effettivamente sincrono. Questo è quello che ho fatto qui - dal momento che non hai discussioni, faccio solo finta di funzionare in modo asincrono e mi è capitato di non fare nulla finché non sei venuto a cercare il risultato. – bdonlan

+0

"* Si noti, tuttavia, che la memorizzazione delle eccezioni non può essere implementata in modo portabile *" Non fa [Boost.Exception] (http://www.boost.org/libs/exception/) come segue? – ildjarn

Problemi correlati