¿Significa FIXME: NYI en MutableCallSite.syncAll que aún no está implementado?
En java.lang.invoke
existen dos constructos interesantes, MutableCallSite
y SwitchPoint
. Se describen como ofreciendo una forma de cambiar sus objetivos (a cualquier objetivo diferente para un MutableCallSite
o a un objetivo predefinido cuando se invalide para un SwitchPoint
), con la garantía de que otros hilos recogerán la actualización, pero con una sobrecarga reducida para los usos de la MCS o SP cuando no se ha cambiado (reducido, en comparación con una comprobación con efectos de sincronización en cada uso). La documentación de SwitchPoint
dice que se puede construir sobre MutableCallSite
, y en las fuentes de OpenJDK en GitHub, se hace. Así que el lugar para buscar la magia está en MutableCallSite.syncAll
.
En la fuente de ese método, la magia parece tener tres pasos:
- El paso 1 es un
lazySet
(efectos JMM desetRelease
) en unAtomicInteger
privado que ningún otro hilo nunca leerá; - El paso 2 mira todas las referencias
MutableCallSite
pasadas para confirmar que ninguna es nula; - El paso 3 es un comentario:
// FIXME: NYI
A un ojo inexperto, parece que hay trabajo real que hacer para ese comentario. ;).
Parece que los desarrolladores de Android vieron ese comentario y eliminaron el método de Android porque no querían publicitar un método no implementado (aunque MutableCallSite
sin syncAll
no parece ser una construcción útil). ¿Tenían razón?
Por otro lado, parece muy poco probable que esté faltando tan claramente su funcionalidad. Ha estado en Java desde Java 7, y aparentemente proyectos importantes como Nashorn y JRuby han hecho un uso intensivo de MutableCallSite
y SwitchPoint
. No he tropezado con comentarios sobre que estén rotos debido a esto.
Además, entiendo que algunas implementaciones en la biblioteca de clases de Java pueden parecer incompletas porque partes de la magia son suministradas por la implementación de la JVM. Este parece ser un ejemplo principal donde eso podría estar sucediendo, pero no he podido encontrar los detalles.
¿Alguien conoce los detalles? Sería bueno saber qué comportamiento confiable realmente tiene. La documentación de syncAll
suena muy prometedora al principio. Parafraseando:
- su efecto es forzar a todos los futuros lectores del objetivo de cada sitio de llamada a aceptar el valor más recientemente almacenado
- puede (¿puede??) bloquearse hasta que todos los lectores hayan (de alguna manera) eliminado todas las versiones anteriores
- los hilos de lectura pueden observar versiones anteriores del objetivo hasta que se devuelve la llamada a
syncAll
(¿Significa esto que pueden no hacerlo después de que se haya devuelto la llamada asyncAll
? Y si es así, ¿no implicaría eso que #2 es realmente algo más fuerte que “puede”?) - es “probablemente costoso” (como la compensación por tener
getTarget
sea barato; esa es la parte mágica).
Pero más tarde en la misma documentación, profundizando en los detalles de JMM, dice “Si (otro hilo) T ejecuta una acción de sincronización A después de la escritura volátil” … entonces debe ver el objetivo actualizado.
Eso suena un poco… menos sólido.
¿Se basa todo esto en algún conocimiento de implementación de JVM que coloca un límite superior en cuanto tiempo puede tardar después de que se devuelve la llamada a syncAll
? Si es así, ¿se puede establecer ese límite superior?
Si realmente no falta nada y la cosa funciona como se anuncia, ¿valdría la pena eliminar el // FIXME: NYI
del origen (y tal vez reemplazarlo por una explicación de lo que realmente sucede)?
Para más información: versión anterior de esta pregunta publicada en la lista mlvm-dev
pero no atrajo ninguna respuesta.
davy.ai
Pregunta:
¿Cuál es la funcionalidad de
MutableCallSite
ySwitchPoint
enjava.lang.invoke
? ¿Cómo funcionaMutableCallSite.syncAll
y por qué fue eliminado de Android? ¿Es posible que la funcionalidad faltante sea proporcionada por la implementación de la JVM? ¿Cuáles son los detalles de los efectos de JMM desyncAll
y es confiable? ¿Debería eliminarse elFIXME: NYI
en el código fuente y reemplazarse con una explicación de lo que realmente sucede?Respuesta:
En
java.lang.invoke
,MutableCallSite
ySwitchPoint
proporcionan construcciones que permiten cambiar los objetivos con la garantía de que otros hilos recogerán la actualización, pero sin la sobrecarga de sincronización asociada con el bloqueo.MutableCallSite
permite que sus objetivos se cambien por un objetivo arbitrario diferente, mientras queSwitchPoint
permite que se cambien a un objetivo predefinido cuando se invalida. La documentación deSwitchPoint
indica que puede construirse sobreMutableCallSite
mediante el uso del métodosyncAll
.En el código fuente de
MutableCallSite.syncAll
, hay tres pasos. El primer paso es una operaciónlazySet
en unAtomicInteger
privado que ningún otro hilo leerá. El segundo paso confirma que ninguna de las referenciasMutableCallSite
pasadas es nula. El tercer paso es un comentarioFIXME: NYI
, lo que indica que el método aún no está implementado.Android eliminó el método
MutableCallSite.syncAll
de su implementación porque no quería anunciar un método no implementado, aunqueMutableCallSite
sinsyncAll
no es una construcción útil. Sin embargo, parece poco probable que falte la funcionalidad de un método tan importante y proyectos como Nashorn y JRuby han hecho un uso intensivo deMutableCallSite
ySwitchPoint
sin encontrar ningún problema.Es posible que la funcionalidad faltante de
MutableCallSite.syncAll
sea proporcionada por la implementación de la JVM. Algunas implementaciones en la biblioteca de clases de Java pueden parecer incompletas porque partes de la magia son suministradas por la implementación de la JVM. Sin embargo, los detalles de esto no están claros.Los efectos de JMM de
syncAll
son prometedores, ya que obligan a todos los lectores futuros del destino de cada sitio de llamada a aceptar el valor almacenado más reciente. Sin embargo, el método puede bloquearse hasta que todos los lectores hayan eliminado caché de las versiones anteriores, y los hilos lectores pueden observar versiones anteriores del objetivo hasta que se haya realizado la llamadasyncAll
. Esto implica que la robustez desyncAll
no está del todo clara.No está claro si el límite máximo de tiempo que puede tardar un hilo en ejecutar una acción de sincronización después de la escritura volátil se basa en el conocimiento de la implementación de la JVM. Si no hay funcionalidad faltante, puede valer la pena eliminar el comentario
FIXME: NYI
del código fuente y reemplazarlo con una explicación de lo que realmente sucede.