2012-01-16 10 views
9

Sin utilizar boost::thread y boost::bind directamente, ¿hay alguna manera de implementar el equivalente del siguiente código?Boost equivalente a 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; 
} 

Específicamente, esta parte: auto ftr = std::async(&func);?

Respuesta

8

Ciertamente. Simplemente haga que async<T>(std::function<T()>) devuelva un futuro que invoca func() en el momento en que se espera por primera vez. No obtendrá ninguna asincronicidad, pero la API no garantiza que la función se ejecute de forma asíncrona, por lo que no hay problema.

Si tiene acceso a una biblioteca de subprocesos específica del sistema operativo, puede, por supuesto, usar eso también.

Tenga en cuenta, sin embargo, que el almacenamiento de excepciones no se puede implementar de forma portátil; requiere soporte adicional de la implementación de C++, a menos que pueda restringir las excepciones admitidas a las que tienen una función de clonación polimórfica. Consulte this question para obtener más información.

La implementación final puede tener un aspecto un poco como este (no probado):

// 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

Gracias por la respuesta detallada! Soy un novato en términos de programación de meta, así que no estoy seguro de cómo se podría utilizar de la misma manera que el ejemplo en el OP ... Por ejemplo, ¿dónde estaría el equivalente de 'std :: async () 'entrar en eso? ¿La clase 'myfuture' necesita vincularse de algún modo con un' boost :: thread'? –

+1

Esto no es realmente asincrónico. El contrato 'std :: async' en realidad no garantiza que la rutina asincrónica se ejecutará ... asincrónicamente. Considere si el subproceso asincrónico nunca se programa hasta que llegue al '.get()' - es efectivamente sincrónico. Esto es lo que he hecho aquí, ya que no tienes hilos, solo pretendo que se estaba ejecutando de forma asíncrona y que no terminaste de hacer nada hasta que no busques el resultado. – bdonlan

+0

"* Tenga en cuenta, sin embargo, que el almacenamiento de excepciones no se puede implementar de manera portátil *" ¿No [Boost.Exception] (http://www.boost.org/libs/exception/) hace esto? – ildjarn

Cuestiones relacionadas