En informática , futuro , promesa , retraso y diferido se refieren a construcciones utilizadas para sincronizar la ejecución de programas en algunos lenguajes de programación concurrentes . Describen un objeto que actúa como proxy de un resultado que inicialmente se desconoce, generalmente porque el cálculo de su valor aún no está completo.
El término promesa fue propuesto en 1976 por Daniel P. Friedman y David Wise, [1] y Peter Hibbard lo llamó eventual . [2] Un concepto de futuro algo similar se introdujo en 1977 en un artículo de Henry Baker y Carl Hewitt . [3]
Los términos futuro , promesa , demora y diferido a menudo se usan indistintamente, aunque a continuación se tratan algunas diferencias en el uso entre futuro y promesa . Específicamente, cuando se distingue el uso, un futuro es una vista de marcador de posición de solo lectura de una variable, mientras que una promesa es un contenedor de asignación única que se puede escribir y que establece el valor del futuro. En particular, un futuro puede definirse sin especificar qué promesa específica establecerá su valor, y diferentes promesas posibles pueden establecer el valor de un futuro determinado, aunque esto solo se puede hacer una vez para un futuro determinado. En otros casos, un futuro y una promesa se crean juntos y se asocian entre sí: el futuro es el valor, la promesa es la función que establece el valor, esencialmente el valor de retorno (futuro) de una función asincrónica (promesa). Establecer el valor de un futuro también se llama resolverlo , cumplirlo o vincularlo .
Aplicaciones
Los futuros y las promesas se originaron en la programación funcional y paradigmas relacionados (como la programación lógica ) para desacoplar un valor (un futuro) de cómo se calculó (una promesa), lo que permitió que el cálculo se hiciera de manera más flexible, en particular paralelizándolo. Más tarde, encontró uso en la computación distribuida , para reducir la latencia de los viajes de ida y vuelta de las comunicaciones. Más tarde, ganó más uso al permitir escribir programas asincrónicos en estilo directo , en lugar de en estilo de paso de continuación .
Implícito vs explícito
El uso de futuros puede ser implícito (cualquier uso del futuro obtiene automáticamente su valor, como si fuera una referencia ordinaria ) o explícito (el usuario debe llamar a una función para obtener el valor, como el get
método de java.util.concurrent.Future
en Java ). Obtener el valor de un futuro explícito puede llamarse punzar o forzar . Los futuros explícitos se pueden implementar como una biblioteca, mientras que los futuros implícitos generalmente se implementan como parte del lenguaje.
El artículo original de Baker y Hewitt describía futuros implícitos, que se apoyan naturalmente en el modelo de actor de computación y en lenguajes de programación puramente orientados a objetos como Smalltalk . El artículo de Friedman y Wise describió solo futuros explícitos, probablemente reflejando la dificultad de implementar de manera eficiente los futuros implícitos en el hardware de valores. La dificultad es que el hardware de valores no se ocupa de futuros para tipos de datos primitivos como enteros. Por ejemplo, una instrucción de suma no sabe cómo manejarla . En lenguajes puros de actor u objeto, este problema se puede resolver enviando el mensaje , que pide al futuro que se agregue a sí mismo y devuelva el resultado. Tenga en cuenta que el enfoque de paso de mensajes funciona independientemente de cuándo finalice el cálculo y que no se necesita punzar / forzar.3 + future factorial(100000)
future factorial(100000)
+[3]
3
factorial(100000)
Promesa canalización
El uso de futuros puede reducir drásticamente la latencia en los sistemas distribuidos . Por ejemplo, los futuros permiten la canalización de promesas , [4] [5] como se implementó en los lenguajes E y Joule , que también se denominó call-stream [6] en el lenguaje Argus .
Considere una expresión que involucre llamadas a procedimientos remotos convencionales , como:
t3: = (xa ()) .c (yb ())
que podría ampliarse a
t1: = xa (); t2: = yb (); t3: = t1.c (t2);
Cada declaración necesita que se envíe un mensaje y se reciba una respuesta antes de que pueda continuar la siguiente declaración. Supongamos, por ejemplo, que x
, y
, t1
, y t2
están ubicados en la misma máquina remota. En este caso, se deben realizar dos viajes de ida y vuelta completos de la red a esa máquina antes de que la tercera instrucción pueda comenzar a ejecutarse. La tercera declaración provocará otro viaje de ida y vuelta a la misma máquina remota.
Usando futuros, la expresión anterior podría escribirse
t3: = (x <- a ()) <- c (y <- b ())
que podría ampliarse a
t1: = x <- a (); t2: = y <- b (); t3: = t1 <- c (t2);
La sintaxis utilizada aquí es la del lenguaje E, donde x <- a()
significa enviar el mensaje de a()
forma asincrónica x
. A las tres variables se les asignan futuros inmediatamente por sus resultados, y la ejecución procede a las declaraciones posteriores. Los intentos posteriores de resolver el valor de t3
pueden causar un retraso; sin embargo, la canalización puede reducir la cantidad de viajes de ida y vuelta necesarios. Si, como en el ejemplo anterior, x
, y
, t1
, y t2
están ubicados en la misma máquina remota, una aplicación pipeline puede calcular t3
con uno de ida y vuelta en lugar de tres. Debido a que los tres mensajes están destinados a objetos que están en la misma máquina remota, solo se necesita enviar una solicitud y solo se necesita recibir una respuesta que contenga el resultado. El envío t1 <- c(t2)
no se bloquearía incluso si t1
y t2
estuvieran en máquinas diferentes entre sí, o para x
o y
.
La canalización de promesas debe distinguirse del paso de mensajes asincrónico paralelo. En un sistema que soporta el paso de mensajes en paralelo, pero no la canalización, el mensaje envía x <- a()
y y <- b()
en el ejemplo anterior podría realizarse de forma paralela, pero el envío de t1 <- c(t2)
tendría que esperar hasta que los dos t1
y t2
se había recibido, aun cuando x
, y
, t1
, y t2
están en la misma distancia máquina. La ventaja de latencia relativa de la canalización se vuelve aún mayor en situaciones más complicadas que involucran muchos mensajes.
La canalización de promesas tampoco debe confundirse con el procesamiento de mensajes canalizados en sistemas de actores, donde es posible que un actor especifique y comience a ejecutar un comportamiento para el siguiente mensaje antes de haber completado el procesamiento del mensaje actual.
Vistas de solo lectura
En algunos lenguajes de programación como Oz , E y AmbientTalk , es posible obtener una vista de solo lectura de un futuro, lo que permite leer su valor cuando se resuelve, pero no permite resolverlo:
- En Oz, el
!!
operador se utiliza para obtener una vista de solo lectura. - En E y AmbientTalk, un futuro está representado por un par de valores llamado par promesa / resolutor . La promesa representa la vista de solo lectura y el resolutor es necesario para establecer el valor del futuro.
- En C ++ 11 a
std::future
proporciona una vista de solo lectura. El valor se establece directamente usando astd::promise
, o se establece en el resultado de una llamada de función usandostd::packaged_task
ostd::async
. - En la API diferida de Dojo Toolkit a partir de la versión 1.5, un objeto de promesa solo para el consumidor representa una vista de solo lectura. [7]
- En Alice ML , los futuros proporcionan una vista de solo lectura , mientras que una promesa contiene tanto un futuro como la capacidad de resolver el futuro [8] [9]
- En .NET Framework 4.0
System.Threading.Tasks.Task
representa una vista de solo lectura. La resolución del valor se puede realizar a través deSystem.Threading.Tasks.TaskCompletionSource
.
El soporte para vistas de solo lectura es consistente con el principio de privilegio mínimo , ya que permite que la capacidad de establecer el valor se restrinja a los sujetos que necesitan establecerlo. En un sistema que también admite la canalización, el remitente de un mensaje asincrónico (con resultado) recibe la promesa de solo lectura para el resultado y el objetivo del mensaje recibe el solucionador.
Futuros específicos de subprocesos
Algunos lenguajes, como Alice ML , definen futuros que están asociados con un hilo específico que calcula el valor del futuro. [9] Este cálculo puede comenzar con entusiasmo cuando se crea el futuro o con pereza cuando se necesita su valor por primera vez. Un futuro perezoso es similar a un procesador , en el sentido de un cálculo retrasado.
Alice ML también admite futuros que pueden resolverse mediante cualquier hilo y llama a estas promesas . [8] Este uso de promesa es diferente de su uso en E como se describe anteriormente . En Alice, una promesa no es una vista de solo lectura y la canalización de promesas no es compatible. En cambio, la canalización ocurre naturalmente para los futuros, incluidos los asociados con las promesas.
Semántica bloqueante vs no bloqueante
Si se accede al valor de un futuro de forma asincrónica, por ejemplo, enviándole un mensaje, o esperándolo explícitamente utilizando una construcción como when
en E, entonces no hay dificultad en retrasar hasta que el futuro se resuelva antes de que el mensaje pueda ser enviado. recibido o la espera se completa. Este es el único caso a considerar en sistemas puramente asincrónicos como los lenguajes de actor puro.
Sin embargo, en algunos sistemas también puede ser posible intentar acceder de forma inmediata o sincrónica al valor de un futuro. Entonces hay que hacer una elección de diseño:
- el acceso podría bloquear el hilo o proceso actual hasta que se resuelva el futuro (posiblemente con un tiempo de espera). Esta es la semántica de las variables de flujo de datos en el lenguaje Oz .
- el intento de acceso síncrono siempre podría indicar un error, por ejemplo, lanzar una excepción . Esta es la semántica de las promesas remotas en E. [10]
- potencialmente, el acceso podría tener éxito si el futuro ya está resuelto, pero señalar un error si no lo está. Esto tendría la desventaja de introducir el no determinismo y el potencial de condiciones de carrera , y parece ser una elección de diseño poco común.
Como ejemplo de la primera posibilidad, en C ++ 11 , un hilo que necesita el valor de un futuro puede bloquearse hasta que esté disponible llamando a las funciones miembro wait()
o get()
. También puede especificar un tiempo de espera en la espera utilizando las funciones miembro wait_for()
o wait_until()
para evitar un bloqueo indefinido. Si el futuro surgió de una llamada a, std::async
entonces una espera de bloqueo (sin un tiempo de espera) puede causar la invocación sincrónica de la función para calcular el resultado en el subproceso en espera.
Construcciones relacionadas
Future es un caso particular de Event (primitiva de sincronización) , que solo se puede completar una vez. En general, los eventos pueden restablecerse al estado vacío inicial y, por lo tanto, completarse tantas veces como desee. [11]
Un I-var (como en el idioma Id ) es un futuro con semántica de bloqueo como se define anteriormente. Una estructura I es una estructura de datos que contiene I-vars. Una construcción de sincronización relacionada que se puede configurar varias veces con diferentes valores se denomina M-var . Las M-vars admiten operaciones atómicas para tomar o poner el valor actual, donde tomar el valor también devuelve la M-var a su estado vacío inicial . [12]
Una variable lógica concurrente [ cita requerida ] es similar a un futuro, pero se actualiza por unificación , de la misma manera que las variables lógicas en la programación lógica . Por lo tanto, se puede vincular más de una vez a valores unificables, pero no se puede volver a un estado vacío o sin resolver. Las variables de flujo de datos de Oz actúan como variables lógicas concurrentes y también tienen semántica de bloqueo como se mencionó anteriormente.
Una variable de restricción concurrente es una generalización de variables lógicas concurrentes para admitir la programación lógica de restricción : la restricción se puede reducir varias veces, lo que indica conjuntos más pequeños de valores posibles. Normalmente, hay una forma de especificar un procesador que debería ejecutarse siempre que la restricción se reduzca aún más; esto es necesario para soportar la propagación de restricciones .
Relaciones entre la expresividad de diferentes formas de futuro
Los futuros ansiosos específicos de subprocesos se pueden implementar directamente en futuros no específicos de subprocesos, creando un subproceso para calcular el valor al mismo tiempo que se crea el futuro. En este caso, es deseable devolver una vista de solo lectura al cliente, de modo que solo el hilo recién creado pueda resolver este futuro.
Para implementar futuros implícitos específicos de subprocesos perezosos (como los proporciona Alice ML, por ejemplo) en términos de futuros no específicos de subprocesos, se necesita un mecanismo para determinar cuándo se necesita por primera vez el valor del futuro (por ejemplo, la WaitNeeded
construcción en Oz [13 ] ). Si todos los valores son objetos, entonces la capacidad de implementar objetos de reenvío transparentes es suficiente, ya que el primer mensaje enviado al reenviador indica que se necesita el valor del futuro.
Los futuros no específicos de subprocesos se pueden implementar en futuros específicos de subprocesos, asumiendo que el sistema admite el paso de mensajes, haciendo que el subproceso de resolución envíe un mensaje al subproceso propio del futuro. Sin embargo, esto puede verse como una complejidad innecesaria. En los lenguajes de programación basados en subprocesos, el enfoque más expresivo parece ser proporcionar una combinación de futuros no específicos de subprocesos, vistas de solo lectura y una construcción WaitNeeded o soporte para reenvío transparente.
Estrategia de evaluación
La estrategia de evaluación de futuros, que puede denominarse llamada por futuro , no es determinista: el valor de un futuro se evaluará en algún momento entre el momento en que se crea el futuro y el momento en que se utiliza su valor, pero no se determina el momento preciso. de antemano y puede cambiar de una ejecución a otra. El cálculo puede comenzar tan pronto como se cree el futuro ( evaluación ansiosa ) o solo cuando el valor sea realmente necesario ( evaluación diferida ), y puede suspenderse a la mitad o ejecutarse en una sola ejecución. Una vez que se asigna el valor de un futuro, no se vuelve a calcular en accesos futuros; esto es como la memorización utilizada en la llamada por necesidad .
A El futuro perezoso es un futuro que tiene determinísticamente una semántica de evaluación perezosa: el cálculo del valor del futuro comienza cuando el valor se necesita por primera vez, como en la llamada por necesidad. Los futuros perezosos son útiles en lenguajes cuya estrategia de evaluación no es perezosa por defecto. Por ejemplo, enC ++ 11,estos futuros perezosos se pueden crear pasando lastd::launch::deferred
política de lanzamiento astd::async
, junto con la función para calcular el valor.
Semántica de futuros en el modelo de actor
En el modelo de actor, una expresión de la forma future
se define por cómo responde a un Eval
mensaje con el entorno E y el cliente C de la siguiente manera: La expresión futura responde al Eval
mensaje enviando al cliente C un actor F recién creado (el proxy para el la respuesta de la evaluación
) como valor de retorno simultáneamente con el envío de
un Eval
mensaje con el medio ambiente e y el cliente C . El comportamiento predeterminado de F es el siguiente:
- Cuando F recibe una solicitud R , luego verifica si ya ha recibido una respuesta (que puede ser un valor de retorno o una excepción lanzada) al evaluar el
procedimiento de la siguiente manera:- Si ya tiene una respuesta V , entonces
- Si V es un valor de retorno, entonces se envía la solicitud R .
- Si V es una excepción, entonces se lanza al cliente de la solicitud R .
- Si no tiene ya una respuesta, entonces R se almacena en la cola de solicitudes dentro de la F .
- Si ya tiene una respuesta V , entonces
- Cuando F recibe la respuesta V de la evaluación
, entonces V se almacena en F y- Si V es un valor de retorno, entonces todas las solicitudes en cola son enviados a V .
- Si V es una excepción, se envía al cliente de cada una de las solicitudes en cola.
Sin embargo, algunos futuros pueden tratar las solicitudes de formas especiales para proporcionar un mayor paralelismo. Por ejemplo, la expresión 1 + future factorial(n)
puede crear un nuevo futuro que se comportará como el número 1+factorial(n)
. Este truco no siempre funciona. Por ejemplo, la siguiente expresión condicional:
if m>future factorial(n) then print("bigger") else print("smaller")
Suspende hasta que el futuro factorial(n)
haya respondido a la solicitud preguntando si m
es mayor que él mismo.
Historia
Las construcciones de futuro y / o promesa se implementaron por primera vez en lenguajes de programación como MultiLisp y Act 1 . El uso de variables lógicas para la comunicación en lenguajes de programación lógica concurrentes fue bastante similar a los futuros. Estos comenzaron en Prolog con Freeze e IC Prolog , y se convirtieron en una verdadera primitiva de concurrencia con Relational Language, Concurrent Prolog , cláusulas de Horn guardadas (GHC), Parlog , Strand , Vulcan , Janus , Oz-Mozart , Flow Java y Alice ML . El I-var de asignación única de los lenguajes de programación de flujo de datos , que se origina en Id e incluido en el ML concurrente de Reppy , es muy parecido a la variable lógica concurrente.
La técnica de canalización de promesas (usando futuros para superar la latencia) fue inventada por Barbara Liskov y Liuba Shrira en 1988, [6] e independientemente por Mark S. Miller , Dean Tribble y Rob Jellinghaus en el contexto del Proyecto Xanadu alrededor de 1989. [14]
El término promesa fue acuñado por Liskov y Shrira, aunque se refirieron al mecanismo de canalización con el nombre de flujo de llamadas , que ahora rara vez se usa.
Tanto el diseño descrito en el artículo de Liskov y Shrira, como la implementación de la canalización de promesas en Xanadu, tenían el límite de que los valores de las promesas no eran de primera clase : un argumento o el valor devuelto por una llamada o envío no podía ser directamente una promesa. (por lo que el ejemplo de canalización de promesas dado anteriormente, que usa una promesa para el resultado de un envío como argumento a otro, no se habría podido expresar directamente en el diseño del flujo de llamadas o en la implementación de Xanadu). Parece que las promesas y los flujos de llamadas nunca se implementaron en ningún lanzamiento público de Argus, [15] el lenguaje de programación utilizado en el artículo de Liskov y Shrira. El desarrollo de Argus se detuvo alrededor de 1988. [16] La implementación de Xanadu de la canalización de promesas solo estuvo disponible públicamente con el lanzamiento del código fuente de Udanax Gold [17] en 1999, y nunca se explicó en ningún documento publicado. [18] Las implementaciones posteriores en Joule y E admiten promesas y resolutores de primera clase.
Varios lenguajes de actores tempranos, incluida la serie Act, [19] [20] admitían tanto el paso de mensajes en paralelo como el procesamiento de mensajes canalizados, pero no la canalización de promesas. (Aunque es técnicamente posible implementar la última de estas características en las dos primeras, no hay evidencia de que los lenguajes Act lo hicieran).
Después de 2000, se produjo un gran resurgimiento del interés en los futuros y las promesas, debido a su uso en la capacidad de respuesta de las interfaces de usuario y en el desarrollo web , debido al modelo de solicitud-respuesta de paso de mensajes. Varios lenguajes convencionales ahora tienen soporte de lenguaje para futuros y promesas, más notablemente popularizado por FutureTask
en Java 5 (anunciado en 2004) [21] y las construcciones async / await en .NET 4.5 (anunciado en 2010, lanzado en 2012) [22] [23] en gran parte inspirado en los flujos de trabajo asincrónicos de F #, [24] que data de 2007. [25] Esto ha sido posteriormente adoptado por otros lenguajes, en particular Dart (2014), [26] Python (2015), [27] Hack (HHVM), y borradores de ECMAScript 7 (JavaScript), Scala y C ++.
Lista de implementaciones
Algunos lenguajes de programación admiten futuros, promesas, variables lógicas concurrentes, variables de flujo de datos o I-vars, ya sea mediante soporte de lenguaje directo o en la biblioteca estándar.
- ABCL / f [28]
- Alice ML
- AmbientTalk (incluidos los solucionadores de primera clase y las promesas de solo lectura)
- C ++ , comenzando con C ++ 11 : std :: future y std :: promise
- Composicional C ++
- Crystal (lenguaje de programación)
- Dart (con clases Future / Completer [29] y las palabras clave aguardan y async [26] )
- Elm (lenguaje de programación) a través del módulo de tareas [30]
- Glasgow Haskell (solo I-vars y M-vars)
- Id (solo I-vars y M-vars)
- Io [31]
- Java a través de
java.util.concurrent.Future
ojava.util.concurrent.CompletableFuture
- JavaScript a partir de ECMAScript 2015, [32] y a través de las palabras clave
async
yawait
desde ECMAScript 2017 [33] - Lucid (solo flujo de datos)
- Algunos Lisps
- Clojure [34]
- MultiLisp
- .NET a través de Task s
- C # , desde .NET Framework 4.5, [22] a través de las palabras clave
async
yawait
[23]
- C # , desde .NET Framework 4.5, [22] a través de las palabras clave
- Nim
- oxígeno
- Oz versión 3 [35]
- Python concurrent.futures , desde 3.2, [36] según lo propuesto por el PEP 3148 , y Python 3.5 agregó async y await [37]
- R (promesas para una evaluación perezosa, todavía de un solo subproceso)
- Raqueta [38]
- Raku [39]
- Scala a través del paquete scala.concurrent
- Esquema
- Chillido Smalltalk
- Hebra
- Swift (solo a través de bibliotecas de terceros)
- Visual Basic [ aclaración necesaria ] 11 (a través de las palabras clave Async y Await ) [23]
Los idiomas que también admiten la canalización de promesas incluyen:
- mi
- Joule
Lista de implementaciones de futuros no estándar basadas en bibliotecas
- Para Common Lisp :
- Mirlo [40]
- Ansioso por el futuro2 [41]
- lparallel [42]
- PCall [43]
- Para C ++:
- Biblioteca de impulso [44]
- Dlib [45]
- Locura [46]
- HPX [47]
- Bibliotecas POCO C ++ (resultados activos) [48]
- Qt [49]
- Estrella de mar [50]
- stlab [51]
- Para C # y otros lenguajes .NET : la biblioteca de extensiones paralelas
- Para Groovy : GPars [52]
- Para JavaScript :
- Cujo.js ' [53] when.js [54] proporciona promesas que cumplen con la especificación Promises / A + [55] 1.1
- El Dojo Toolkit proporciona promesas [56] y aplazamientos de estilo Twisted
- MochiKit [57] inspirado en Twisted's Deferreds
- jQuery objeto diferido se basa en los CommonJS Promesas / Un diseño.
- AngularJS [58]
- nodo -promise [59]
- Q, de Kris Kowal, se ajusta a Promises / A + 1.1 [60]
- RSVP.js, se ajusta a Promises / A + 1.1 [61]
- La clase de promesa [63] de YUI [62] cumple con la especificación Promises / A + 1.0.
- Bluebird, de Petka Antonov [64]
- La Biblioteca de cierre 's promesa se ajusta a las promesas de paquetes / A + especificación.
- Consulte la lista de Promise / A + para ver más implementaciones basadas en el diseño de Promise / A +.
- Para Java :
- JDeferred, proporciona API de promesa diferida y un comportamiento similar a JQuery . Objeto diferido [65]
- ParSeq [66] proporciona API de promesa de tarea ideal para canalización y ramificación asincrónicas, mantenida por LinkedIn
- Para Lua :
- El módulo cqueues [1] contiene una API Promise.
- Para Objective-C : MAFuture, [67] [68] RXPromise, [69] ObjC-CollapsingFutures, [70] PromiseKit, [71] objc-promise, [72] OAPromise, [73]
- Para OCaml : el módulo Lazy implementa futuros explícitos perezosos [74]
- Para Perl : Future, [75] Promises, [76] Reflex, [77] Promise :: ES6, [78] y Promise :: XS [79]
- Para PHP : React / Promise [80]
- Para Python :
- Implementación incorporada [81]
- pythonfutures [82]
- Diferidos de Twisted [83]
- Para R :
- futuro, implementa una API futura extensible con futuros síncronos perezosos y ansiosos y (multinúcleo o distribuidos) asíncronos [84] [85]
- Para Ruby :
- Joya de promesa [86]
- libuv gem, implementa promesas [87]
- Gema de celuloide, futuros de implementos [88]
- recurso-futuro [89]
- Para el óxido :
- futuros-rs [90]
- Para Scala :
- Biblioteca de utilidades de Twitter [91]
- Para Swift :
- Marco asíncrono, implementa estilo C #
async
/ sin bloqueoawait
[92] - FutureKit, [93] implementa una versión para Apple GCD [94]
- FutureLib, biblioteca Swift 2 pura que implementa futuros y promesas al estilo Scala con cancelación al estilo TPL [95]
- Biblioteca Swift diferida y pura inspirada en Deferred [96] de OCaml
- BrightFutures [97]
- Marco asíncrono, implementa estilo C #
- Para Tcl : tcl-promise [98]
Corutinas
Los futuros se pueden implementar en corrutinas [27] o generadores , [99] resultando en la misma estrategia de evaluación (por ejemplo, multitarea cooperativa o evaluación perezosa).
Canales
Los futuros se pueden implementar fácilmente en los canales : un futuro es un canal de un elemento y una promesa es un proceso que envía al canal, cumpliendo el futuro. [100] [101] Esto permite implementar futuros en lenguajes de programación concurrentes con soporte para canales, como CSP y Go . Los futuros resultantes son explícitos, ya que se debe acceder a ellos mediante la lectura del canal, en lugar de solo una evaluación.
Ver también
- Fibra (informática)
- Futex
- Pyramid of doom (programación) , un antipatrón de diseño evitado por promesas
Referencias
- ^ Friedman, Daniel; David Wise (1976). El impacto de la programación aplicativa en el multiprocesamiento . Conferencia Internacional sobre Procesamiento Paralelo. págs. 263-272.
- ^ Hibbard, Peter (1976). Instalaciones de procesamiento en paralelo . Nuevas direcciones en lenguajes algorítmicos, (ed.) Stephen A. Schuman, IRIA, 1976.
- ^ Henry Baker; Carl Hewitt (agosto de 1977). La recolección de basura incremental de procesos . Actas del Simposio sobre lenguajes de programación de inteligencia artificial. ACM SIGPLAN Avisos 12, 8. págs. 55–59.
- ^ Promesa Pipelining en erights.org
- ^ Promise Pipelining en la wiki de C2
- ^ a b Barbara Liskov; Liuba Shrira (1988). "Promesas: soporte lingüístico para llamadas a procedimientos asincrónicos eficientes en sistemas distribuidos". Actas de la conferencia SIGPLAN '88 sobre diseño e implementación de lenguajes de programación; Atlanta, Georgia, Estados Unidos . ACM. págs. 260–267. doi : 10.1145 / 53990.54016 . ISBN 0-89791-269-1.También publicado en ACM SIGPLAN Notices 23 (7).
- ^ Promesas sólidas con Dojo diferido , Site Pen, 3 de mayo de 2010
- ^ a b "Promesa" , Alice Manual , DE: Uni-SB
- ^ a b "Futuro" , manual de Alice , DE: Uni-SB
- ^ Promesa , derechos E
- ^ 500 líneas o menos, "Un rastreador web con asyncio Coroutines" de A. Jesse Jiryu Davis y Guido van Rossum dice "la implementación utiliza un asyncio. Aquí se muestra el evento en lugar del futuro. La diferencia es que un evento se puede restablecer, un futuro no puede pasar de resuelto a pendiente ".
- ^ Control Concurrent MVar , Haskell, archivado desde el original el 18 de abril de 2009
- ^ WaitNeeded , Mozart Oz
- ^ Promise , Sunless Sea, archivado desde el original el 23 de octubre de 2007
- ^ Argus , MIT
- ^ Liskov, Barbara, Computación distribuida y Argus , Historia oral, IEEE GHN
- ^ Gold , Udanax, archivado desde el original el 11 de octubre de 2008
- ^ Pipeline , derechos E
- ^ Henry Lieberman (junio de 1981). "Una vista previa del acto 1". Nota 625 de AI del MIT. Cite journal requiere
|journal=
( ayuda ) - ^ Henry Lieberman (junio de 1981). "Pensar en muchas cosas a la vez sin confundirse: paralelismo en el acto 1". Nota 626 del MIT AI. Cite journal requiere
|journal=
( ayuda ) - ^ Goetz, Brian (23 de noviembre de 2004). "Concurrencia en JDK 5.0" .
- ^ a b "Async en 4.5: Vale la pena esperar - Blog de .NET - Página principal del sitio - Blogs de MSDN" . Blogs.msdn.com . Consultado el 13 de mayo de 2014 .
- ^ a b c "Programación asincrónica con Async y Await (C # y Visual Basic)" . Msdn.microsoft.com . Consultado el 13 de mayo de 2014 .
- ^ Tomas Petricek (29 de octubre de 2010). "Asincrónico C # y F # (I.): Introducción simultánea" .
- ^ Don Syme; Tomas Petricek; Dmitry Lomov (21 de octubre de 2010). "El modelo de programación asincrónica de F #, PADL 2011" .
- ^ a b Gilad Bracha (octubre de 2014). "Soporte de asincronía de lenguaje Dart: Fase 1" .
- ^ a b "PEP 0492 - Coroutines con async y aguardar sintaxis" .
- ^ Kenjiro Taura; Satoshi Matsuoka; Akinori Yonezawa (1994). "ABCL / f: un lenguaje orientado a objetos concurrentes de tipo polimórfico basado en el futuro - su diseño e implementación". En Proceedings of the DIMACS Workshop on Specification of Parallel Algorithms, number 18 in Dimacs Series in Discrete Mathematics and Theoretical Computer Science . Sociedad Matemática Estadounidense. págs. 275-292. CiteSeerX 10.1.1.23.1161 .
- ^ "Dart SDK dart async Completer" .
- ^ "Tarea" .
- ^ Steve Dekorte (2005). "Io, el lenguaje de programación" .
- ^ "Usando promesas" . Red de desarrolladores de Mozilla . Consultado el 23 de febrero de 2021 .
- ^ "Facilitando la programación asincrónica con async y await" . Red de desarrolladores de Mozilla . Consultado el 23 de febrero de 2021 .
- ^ Rich Hickey (2009). "changes.txt en 1.1.x del clojure de richhickey" .
- ^ Seif Haridi; Nils Franzen. "Tutorial de Oz" . Biblioteca de usuarios globales de Mozart . Consultado el 12 de abril de 2011 .
- ^ Versión de Python 3.2
- ^ Lanzamiento de Python 3.5
- ^ "Paralelismo con futuros" . PLT . Consultado el 2 de marzo de 2012 .
- ^ Clase de promesa en Perl 6
- ^ Mirlo Lisp común
- ^ Common Lisp Eager Future2
- ^ Lisp en paralelo: una biblioteca de programación paralela para Common Lisp
- ^ Common Lisp PCall
- ^ "Capítulo 30. Thread 4.0.0" . Consultado el 26 de junio de 2013 .
- ^ "Biblioteca Dlib C ++ #thread_pool" . Consultado el 26 de junio de 2013 .
- ^ "GitHub - facebook / folly: una biblioteca de C ++ de código abierto desarrollada y utilizada en Facebook" . 8 de enero de 2019.
- ^ "HPX" . 10 de febrero de 2019.
- ^ "Diapositivas de hilos de POCO" (PDF) .
- ^ "QtCore 5.0: Clase QFuture" . Proyecto Qt. Archivado desde el original el 1 de junio de 2013 . Consultado el 26 de junio de 2013 .
- ^ "Seastar" . Proyecto Seastar . Consultado el 22 de agosto de 2016 .
- ^ "stlab es el trabajo en curso de lo que fue el Laboratorio de Tecnología de Software de Adobe. Las Bibliotecas de Origen de Adobe (ASL), las Bibliotecas de Plataforma y las nuevas bibliotecas de stlab están alojadas en github" . 31 de enero de 2021.
- ^ Groovy GPars Archivado el 12 de enero de 2013 en Wayback Machine.
- ^ Cujo.js
- ^ JavaScript when.js
- ^ Promesas / Especificación A +
- ^ promesas
- ^ JavaScript MochKit.Async
- ^ JavaScript Angularjs
- ^ Promesa de nodo de JavaScript
- ^ JavaScript Q
- ^ JavaScript RSVP.js
- ^ Biblioteca de clases de JavaScript YUI
- ^ Clase de promesa de YUI JavaScript
- ^ JavaScript Bluebird
- ^ Java JDeferred
- ^ Java ParSeq
- ^ Objective-C MAFuture GitHub
- ^ Objective-C MAFuture mikeash.com
- ^ Objective-C RXPromise
- ^ ObjC-CollapsingFutures
- ^ Kit de promesa de Objective-C
- ^ Objc-promesa de Objective-C
- ^ Objetivo-C OAPromise
- ^ OCaml Lazy
- ^ Futuro de Perl
- ^ Promesas de Perl
- ^ Reflejo de Perl
- ^ Promesa de Perl :: ES6
- ^ "Promise :: XS - Promesas rápidas en Perl - metacpan.org" . metacpan.org . Consultado el 14 de febrero de 2021 .
- ^ PHP Reaccionar / Promesa
- ^ Implementación incorporada de Python
- ^ pythonfutures
- ^ Diferidos retorcidos
- ^ R futuro del paquete
- ^ futuro
- ^ Gema Ruby Promise
- ^ Ruby libuv
- ^ Gema de celuloide rubí
- ^ Recurso futuro de Ruby
- ^ caja de futuros-rs
- ^ Biblioteca de utilidades de Twitter
- ^ Asíncrono rápido
- ↑ Swift FutureKit
- ^ Swift Apple GCD
- ^ Swift FutureLib
- ^ bignerdranch / diferido
- ^ Thomvis / BrightFutures
- ^ tcl-promesa
- ^ ¿Async / await resuelve un problema real?
- ^ Vaya patrones de lenguaje Futuros
- ^ Ir a patrones de idioma
enlaces externos
- Presentación de patrones de concurrencia dada en scaleconf
- Canalización de valores y promesas futuros en el repositorio de patrones de Portland
- Fácil subprocesamiento con futuros en Python