1159. Identidad de la lección
1160. Objetivo de aprendizaje
Al terminar esta lección, podrás modelar el ciclo de vida de un recurso del juego, identificar a su responsable o a quien lo usa en préstamo, corregir transiciones de limpieza ausentes, distinguir la reutilización de la recuperación y explicar cómo se evita una doble liberación.
1161. Por qué importa
Un recurso puede crearse correctamente y aun así provocar fallos si permanece activo después de que termine su uso válido o si se libera mientras otro sistema todavía depende de él. Las texturas, los identificadores de audio, las suscripciones, los objetos similares a archivos, las entidades de un pool y los recursos vinculados a la GPU necesitan contratos explícitos de ciclo de vida.
Los cambios de escena, las cancelaciones, los reintentos y las inicializaciones parciales pueden dejar referencias obsoletas, callbacks duplicados, recursos sin devolver o liberaciones prematuras. La IA puede sugerir código de limpieza, pero no puede deducir de forma segura un contrato de responsabilidad que no esté documentado. Tú debes determinar quién controla cada recurso o derecho de uso, cuándo termina ese uso y qué ocurre en cada salida posible.
1162. Conocimientos previos
Debes poder distinguir una observación de rendimiento medida de una hipótesis, como se practicó en 3.7 L2 — Measure before changing. También debes poder seguir un flujo pequeño de código e identificar el objeto o sistema que solicita un recurso. No se requiere ningún lenguaje ni API de motor en particular.
1163. Concepto central
El ciclo de vida de un recurso es una secuencia de responsabilidades, no solo un constructor seguido de un destructor.
Un modelo útil distingue estas operaciones:
- Crear o adquirir: asignar un recurso, abrirlo, suscribirse u obtener un derecho de uso de otro responsable.
- Usar: realizar trabajo mientras el recurso o el derecho de uso siga siendo válido.
- Ejecutar
dispose: indicar que un componente ha terminado y ejecutar su contrato de limpieza. - Liberar: cerrar, cancelar una suscripción, reducir un contador, devolver un elemento a un pool o renunciar de otra forma a lo adquirido. En algunas APIs,
disposerealiza la liberación; en otras, coordina varias operaciones. - Reutilizar: iniciar un nuevo periodo de uso válido para un recurso existente o para un elemento equivalente de un pool.
- Recuperar: responder a una creación fallida, un uso fallido, una inicialización parcial o una limpieza incompleta mediante un reintento, una alternativa o el registro y la notificación del fallo.
Toda adquisición necesita un contrato explícito de responsabilidad, pero eso no significa que cada usuario deba liberar el recurso compartido subyacente. El responsable libera los recursos o derechos que posee. Quien usa un recurso en préstamo debe terminar su uso y devolver o abandonar ese derecho según el contrato; no debe destruir ni liberar un recurso subyacente que pertenece a un pool, un gestor o un servicio compartido.
1164. Modelo responsable–vida útil–salida
| Pregunta | Respuesta necesaria |
|---|---|
| Responsable o usuario en préstamo | ¿Qué objeto o sistema posee el recurso y qué componentes solo lo usan temporalmente? |
| Vida útil | ¿Durante qué estados u operaciones puede utilizarse cada derecho de uso? |
| Salida | ¿Qué evento pone fin al derecho y qué limpieza, devolución, liberación o transferencia ocurre después? |
| Estado del ciclo de vida | Responsabilidad | Evidencia que debes inspeccionar |
|---|---|---|
| Creado o adquirido | Registrar el recurso o derecho de uso y a su responsable | Resultado de una asignación, suscripción, apertura o retirada de un pool |
| En uso | Mantener válido el derecho e impedir su liberación durante el uso | Llamadas que consumen o referencian el recurso |
| En limpieza | Impedir nuevos usos y ejecutar la limpieza como máximo una vez | Guarda, cambio de estado o callback del ciclo de vida |
| Liberado o devuelto | Abandonar únicamente los derechos que posee este componente | Cierre, desuscripción, decremento, devolución al pool o llamada de liberación |
| Reutilizado | Establecer un nuevo derecho válido y un nuevo usuario | Nueva retirada del pool o readquisición |
| En recuperación | Gestionar el fallo sin fingir que la adquisición tuvo éxito | Reintento, alternativa, reversión, registro o notificación del fallo |
Representa el ciclo de vida mediante flechas, una lista numerada de transiciones o una tabla de estados. Etiqueta cada transición con el evento que la activa. Si no se conoce al responsable, al usuario, el evento o el estado siguiente, marca ese punto como defecto en lugar de suponer cómo funciona la API.
1165. Ejemplo concreto
Imagina una DialogueAudioSession que solicita un stream a un pool de audio y después se suscribe al callback que indica el final del diálogo.
Comienza el diálogo
-> Solicitar un stream al pool
-> Si la solicitud tiene éxito, suscribirse al callback de finalización
-> Reproducir el diálogo
-> El diálogo termina, se omite o se descarga la escena
-> Ejecutar dispose en la sesión una sola vez
-> Cancelar la suscripción y devolver al pool el derecho de uso del stream
-> El pool podrá entregar más adelante el stream mediante un nuevo derecho de uso
El pool puede ser el responsable del stream subyacente, mientras que la sesión solo controla temporalmente el derecho obtenido al retirarlo. Según ese contrato, la sesión debe devolver su derecho de uso, pero no debe destruir el recurso que pertenece al pool.
Examina al menos estos recorridos:
- Finalización normal: termina la última línea, la sesión se cierra una sola vez, se elimina el callback y el derecho de uso del stream vuelve al pool.
- Cancelación o descarga: se aplican las mismas obligaciones de limpieza aunque nunca se ejecute la última línea.
- Adquisición fallida: no existe ningún derecho sobre el stream, por lo que la limpieza no debe intentar devolverlo ni liberarlo. La sesión sigue una ruta definida de recuperación o notificación.
- Adquisición parcial: la retirada del stream tiene éxito, pero falla la suscripción al callback. La limpieza debe devolver el stream adquirido sin intentar cancelar una suscripción que nunca llegó a establecerse.
1166. Reutilización no es recuperación
La reutilización y la recuperación pueden conducir a un estado utilizable, pero responden a preguntas distintas:
- Reutilización: ¿cómo recibe un recurso válido un nuevo responsable o usuario temporal después de terminar el derecho anterior?
- Recuperación: ¿qué respuesta se aplica después de un fallo o de un estado parcial?
Devolver un stream al pool y retirarlo de nuevo más tarde es reutilización. Registrar un fallo de adquisición, revertir una sesión creada solo en parte, reintentar según una política definida o seleccionar una alternativa son acciones de recuperación.
1167. Cómo evitar una doble liberación
Más de un evento puede solicitar la limpieza. Por ejemplo, una cancelación y una descarga de escena podrían ocurrir casi al mismo tiempo. Un ciclo de vida seguro debe hacer que la limpieza sea idempotente o protegerla para que cada derecho adquirido se abandone como máximo una vez.
Una protección conceptual puede expresarse así:
si el estado es Activo o AdquiridoParcialmente:
cambiar el estado a EnLimpieza
liberar solo los derechos registrados como adquiridos
borrar esos registros
cambiar el estado a Cerrado
si no:
no realizar una segunda liberación
La sintaxis exacta depende de la API. La evidencia importante es el cambio de estado o la protección que impide que dos eventos terminales liberen dos veces el mismo derecho.
1168. Lista de comprobación de responsabilidades
Para cada recurso o derecho de uso, responde:
- ¿Quién posee el recurso subyacente?
- ¿Este componente lo posee, lo comparte o solo lo usa en préstamo?
- ¿Qué adquisición correcta registra esa responsabilidad?
- ¿Qué eventos terminan el uso válido?
- ¿Qué derechos propios deben liberarse, devolverse, cerrarse o desuscribirse?
- ¿Qué recursos subyacentes debe dejar intactos este usuario temporal?
- ¿Cómo sabe la limpieza si la adquisición fue completa, parcial o fallida?
- ¿Qué impide liberar dos veces el mismo derecho?
- ¿Qué transición permite la reutilización?
- ¿Qué respuesta constituye la recuperación después de un fallo?
1169. Práctica evaluada
Completa Corrección de un ciclo de vida de recursos. Inspeccionarás un ciclo de vida deliberadamente incompleto para un stream de audio procedente de un pool y una suscripción a un callback.
El ciclo proporcionado incluye recorridos de finalización normal, cancelación y adquisición parcial, pero omite varias decisiones de responsabilidad y limpieza. Identifica al responsable del recurso subyacente y los derechos temporales, marca o etiqueta las transiciones ausentes, distingue la reutilización de la recuperación y explica la protección contra la doble liberación.
Puedes entregar cualquiera de estos formatos equivalentes:
- un diagrama con anotaciones;
- una lista estructurada de transiciones; o
- una tabla de estados con columnas para estado, responsable o usuario temporal, evento activador, acción, estado siguiente y ruta de fallo.
No es necesario rodear elementos visualmente. Puedes marcar los defectos con etiquetas como RESPONSABLE AUSENTE, TRANSICIÓN AUSENTE, RIESGO DE DOBLE LIBERACIÓN o LIBERACIÓN NO VÁLIDA.
1170. Validación y evidencia
La práctica se evalúa con estos criterios:
- un responsable identificado para el recurso subyacente y una explicación clara de qué posee o toma prestado la sesión;
- transiciones de creación o adquisición, uso,
disposey liberación o devolución; - recorridos de finalización normal, cancelación y adquisición parcial;
- una ruta de adquisición fallida que no intente liberar un derecho inexistente;
- una distinción correcta entre reutilización y recuperación;
- una protección o cambio de estado explícito contra la doble liberación;
- ningún uso posterior a la liberación o devolución.
El ciclo está completo cuando otra persona puede determinar quién limpia, cuándo comienza la limpieza, qué derechos se abandonan, si es seguro repetir la solicitud de limpieza y qué sucede después de un fallo. Cualquier comportamiento desconocido debe quedar marcado como defecto y no completarse con una suposición sobre la API.
1171. Ideas clave
- La vida útil de un recurso se define mediante la responsabilidad, el uso en préstamo, los estados válidos y los eventos de salida.
disposecoordina el contrato de limpieza de un componente; no siempre equivale a liberar un recurso compartido subyacente.- Cada responsable libera los derechos que posee. Quien usa un recurso en préstamo termina su uso sin destruir recursos que pertenecen a otro sistema.
- La finalización normal, la cancelación, la adquisición fallida y la adquisición parcial necesitan recorridos explícitos.
- La reutilización crea un nuevo derecho válido; la recuperación responde a un fallo.
- El ciclo de vida necesita una protección o transición observable que evite la doble liberación.
1172. Próxima lección
Continúa con 3.8 L2 — Reproducir un fallo del ciclo de vida. Utiliza el ciclo corregido y la nota de responsabilidades como punto de partida para reproducir un fallo acotado.
1173. Comprobación
Responde estas preguntas por tu cuenta antes de leer las respuestas.
Una sesión obtiene temporalmente un stream de un pool. ¿Qué contrato de limpieza es correcto?
Mostrar respuesta y explicación
Respuesta: La sesión termina su uso y devuelve su derecho; el pool conserva la responsabilidad sobre el recurso subyacente.
Por qué: Quien usa un recurso en préstamo debe terminar su uso según el contrato sin destruir el recurso subyacente que pertenece al pool.
La retirada de un stream tiene éxito, pero falla la suscripción al callback. ¿Qué acciones corresponden al recorrido de adquisición parcial?
Mostrar respuesta y explicación
Respuesta: Devolver el derecho adquirido sobre el stream.; Registrar o notificar el fallo de suscripción.
Por qué: La limpieza parcial abandona únicamente los derechos adquiridos correctamente y sigue una ruta definida de registro, notificación o recuperación.
¿Qué ejemplo corresponde a reutilización y no a recuperación?
Mostrar respuesta y explicación
Respuesta: Retirar de nuevo un stream devuelto mediante un nuevo derecho válido.
Por qué: La reutilización establece un nuevo derecho válido sobre un recurso existente. Las demás opciones responden a fallos y son acciones de recuperación.
La cancelación y la descarga de escena pueden solicitar la limpieza. ¿Qué evidencia demuestra mejor que se evita una doble liberación?
Mostrar respuesta y explicación
Respuesta: Una transición de estado o protección permite liberar cada derecho propio como máximo una vez.
Por qué: El ciclo de vida necesita un cambio de estado o una protección observable para que varios eventos terminales no liberen dos veces el mismo derecho.