visual studio programacion móviles microsoft español descargar desarrollo curso community aplicaciones c++ multithreading c++11 stdasync

c++ - studio - ¿Cómo se puede ejecutar una función "como si" en un nuevo hilo sin hacerlo?



visual studio 2017 community español (7)

Según [futures.async] / 3 bullet 1 de C ++ Standard, cuando se pasa una función f a std::async con la política de lanzamiento std::launch::async , f se ejecutará "como si estuviera en un nuevo hilo de ejecución. ".

Dado que f puede hacer cualquier cosa, incluido el bucle infinito y el bloqueo para siempre, ¿cómo puede una implementación ofrecer el comportamiento de f ejecutándose en su propio hilo sin ejecutarlo realmente en su propio hilo? Es decir, ¿cómo puede una implementación aprovechar el margen de maniobra "como si" que el Estándar ofrece?


AFAIK el tiempo de ejecución de C ++ puede administrar algunos subprocesos internos (o especializados), que se distinguen de los subprocesos estándar .

Mi conjetura (aún estoy aprendiendo las características avanzadas de C ++) es que, con el indicador std::launch::async , el std::async() lanzará f en un nuevo hilo interno .

Puedes lanzar f en un nuevo hilo estándar usando std::thread . En este caso, las excepciones se manejarán en el subproceso llamado y el código principal tendrá que obtener el valor de retorno de f .

Con el subproceso interno , el valor de retorno y la eventual excepción se almacenan en std::future , devuelto por std::async() y compartido entre los subprocesos.

Así que "como si" significa "como si ejecutara f con std::thread pero no tengo que hacerlo". Pero seguro, f se ejecutará en un nuevo hilo.

Para responder a su pregunta sobre la implementación, una vez que el tiempo de ejecución ya tenga implementados los subprocesos estándar , sería solo el esfuerzo de especializarlos para usos específicos. Consulte también la política de ejecución para los algoritmos que admiten la paralelización .


Algunas formas en las que puedo pensar que f podría ejecutarse "como si" en un nuevo subproceso sin hacerlo realmente sería si f no utiliza ningún estado compartido con otros subprocesos; luego, la implementación podría ejecutarse como un proceso separado (ya que no necesita espacio de memoria compartida), también podría ejecutarse en el subproceso principal como otra llamada de función (si puede demostrar que f no se bloquea o se puede observar) efectos secundarios que difieren cuando se ejecuta de esta manera). También podría programarse para ejecutarse en un subproceso existente (pero inactivo) (grupo de subprocesos).

Y si quieres ser tonto, creo que también podrías considerar la noción de no ejecutar f en absoluto , ya que no hay garantías de cuándo un nuevo sistema operativo programará nuevos subprocesos, por lo que una implementación malvada podría simplemente decir que el sistema operativo nunca programa ningún subproceso, excepto el subproceso principal, por lo que no ejecutar f es equivalente a programarlo en un nuevo subproceso. Por supuesto, esto es estúpido / tonto y ninguna implementación sensata lo haría, pero en teoría el lenguaje permite una implementación tan degenerada (creo).


En los documentos, decía allí,

La función de plantilla async ejecuta la función f asincrónicamente (potencialmente en un subproceso separado que puede ser parte de un grupo de subprocesos) y devuelve un std :: future que eventualmente retendrá el resultado de esa llamada de función.

here


La única solución sin Thread, que se me ocurre, es la división del tiempo de ayer, que es una forma de multitarea. Las funciones deben hacerse reingresantes. En tal escenario, cada función se ejecutará como si estuvieran en subprocesos diferentes, aunque prácticamente están en un solo subproceso.


La ventaja de esta solución es que tiene una implementación optimizada para un rol específico en el mundo de subprocesos múltiples. Como estoy involucrado en los procedimientos de actualización de software, usaré tal ejemplo. Por razones de optimización puede llamar:

std::thread::hardware_concurrency();

Usted recibirá:

Devuelve el número de subprocesos simultáneos admitidos por la implementación.

Digamos que tienes un resultado igual a 4. Deseas actualizar muchas cosas en paralelo. El hilo principal es monitorear la lista de futuros (3 a la izquierda) y verificar de vez en cuando si está hecho o no, y si es así, ejecute lo siguiente desde la lista de tareas pendientes. La ganancia aquí es, por ejemplo, si está actualizando diferentes tipos de memoria como 1-FileSystem, 2-EEPROM, 3-NOR o algo así. No se obtienen beneficios de la verificación en bucle sin demora, por lo que desea asignar una tarea a la 4ª secuencia entre las comprobaciones. Está escribiendo una función que está cavando bitcoins durante 50 milisegundos :) y la activa como diferida entre las comprobaciones.

Y luego, como usted mencionó, tenemos:

ventaja de la sala de maniobra "como si" que el Estándar proporciona


Mirando en los refs de C ++ como aparecen here y here , parece que el objetivo "como si" es permitirle al implementador de la biblioteca cierto grado de libertad. Por ejemplo, dice

como si fuera generado por std :: thread (std :: forward (f), std :: forward (args) ...), excepto que si la función f devuelve un valor o lanza una excepción, se almacena en el estado compartido accesible a través de std :: future que async regresa a la persona que llama.

en la primera fuente, y

como si un objeto de subproceso se construyera con fn y args como argumentos, y accediendo al estado compartido del futuro devuelto se une a él

en el segundo. Así que parece que el comportamiento es similar al de std::thread pero podría implementarse de una manera diferente. Esto es interesante, ya que la frase de ejecución de la frase que usted cita aquí es distinguible de std::thread . Aún así, parece que ambas fuentes entienden el "si" de esa manera.

Otra opción podría ser, como lo sugirió François Andrieux para permitir el uso de threadpool, como se expresa en la primera fuente:

La función de plantilla async ejecuta la función f asincrónicamente (potencialmente en un subproceso separado que puede ser parte de un grupo de subprocesos)


Veo la idea principal de que "f se ejecutará" como si en un nuevo subproceso de ejecución "" es que f se ejecutará de forma asíncrona. Si debe ser un nuevo hilo o algo más son los detalles de la implementación.