Exigences relatives à la durée de vie des objets NDKPI
Un consommateur NDK lance une demande de création pour un objet NDK en appelant la fonction create du fournisseur NDK pour cet objet.
Lorsque le consommateur appelle une fonction create, il passe un NdkCreateCompletion (NDK_FN_CREATE_COMPLETION) en tant que paramètre.
Le consommateur lance diverses requêtes en appelant les fonctions du fournisseur dans la table dispatch de l’objet, en passant un rappel d’achèvement NdkRequestCompletion (NDK_FN_REQUEST_COMPLETION) en tant que paramètre.
Lorsqu’un objet n’est plus nécessaire, le consommateur appelle la fonction NdkCloseObject (NDK_FN_CLOSE_OBJECT) du fournisseur pour lancer une demande de fermeture pour l’objet, en passant un rappel NdkCloseCompletion (NDK_FN_CLOSE_COMPLETION) en tant que paramètre.
Le fournisseur appelle la fonction de rappel du consommateur pour effectuer la requête de manière asynchrone. Cet appel indique au consommateur que le fournisseur a terminé l’opération (par exemple, en fermant l’objet) et qu’il retourne le contrôle au consommateur. Si le fournisseur termine la demande de fermeture de manière synchrone, avec succès ou par erreur, il n’appelle pas la fonction de rappel du consommateur.
Lorsqu’un fournisseur a créé un objet à la demande d’un consommateur, le fournisseur appelle le rappel NdkCreateCompletion du consommateur pour indiquer que l’objet est prêt à être utilisé.
Le consommateur peut appeler d’autres fonctions de fournisseur pour le même objet sans attendre le retour du premier rappel.
Le consommateur n’appellera pas la fonction NdkCloseObject pour un objet tant que toutes les fonctions du fournisseur pour cet objet n’ont pas été retournées.
Toutefois, si la fonction fournisseur lance une demande d’achèvement, le consommateur est libre d’appeler NdkCloseObject à partir de ce rappel d’achèvement, même si la fonction fournisseur n’a pas été retournée.
Une fonction de fournisseur peut lancer une demande d’achèvement avant de revenir à partir d’un rappel en effectuant l’une des opérations suivantes :
- Appel du rappel d’achèvement directement
- Mise en file d’attente de la demande d’achèvement vers un autre thread
En lançant une demande d’achèvement, le fournisseur retourne effectivement le contrôle au consommateur. Le fournisseur doit supposer que l’objet peut être fermé à tout moment après que le fournisseur a lancé la demande d’achèvement.
Note Pour éviter l’interblocage après le lancement d’une demande d’achèvement, le fournisseur doit :
- N’effectuez pas d’autres opérations sur l’objet tant que le rappel d’achèvement n’est pas retourné.
- Prenez les mesures nécessaires pour conserver l’objet intact, si le fournisseur doit absolument toucher l’objet.
Examinez le cas suivant :
- Le consommateur crée un connecteur (NDK_CONNECTOR), puis appelle NdkConnect (NDK_FN_CONNECT).
- Le fournisseur traite la demande de connexion, rencontre un échec et appelle le rappel d’achèvement du consommateur dans le contexte de l’appel NdkConnect (par opposition au retour d’un échec inline en raison d’un choix d’implémentation interne).
- Le consommateur appelle NdkCloseObject dans le contexte de ce rappel d’achèvement, même si l’appel NdkConnect n’a pas encore été retourné au consommateur.
Pour éviter l’interblocage, le fournisseur ne doit pas toucher l’objet connecteur après l’étape 2 (le point où il a lancé le rappel d’achèvement à l’intérieur de l’appel NdkConnect ).
Le fournisseur doit être prêt pour que le consommateur appelle la fonction NdkCloseObject pour fermer un objet antérieur avant que le consommateur appelle NdkCloseObject pour les objets successeurs . Si le consommateur le fait, voici ce que le fournisseur doit faire :
- Le fournisseur ne doit pas fermer l’objet antécédent tant que tous les objets successeurs n’ont pas été fermés, c’est-à-dire que le fournisseur doit retourner STATUS_PENDING de la demande de fermeture et la terminer (en appelant la fonction NdkCloseCompletion inscrite pour la demande de fermeture) une fois tous les objets successeurs fermés.
- Le consommateur n’utilisera pas l’objet d’antécédent après avoir appelé NdkCloseObject sur celui-ci, de sorte que le fournisseur n’a pas à ajouter de gestion en cas d’échec d’autres fonctions de fournisseur sur l’objet antécédent (mais il peut le faire s’il le souhaite).
- Le fournisseur peut traiter la demande de fermeture comme une simple déréférencement qui n’a aucun autre effet secondaire jusqu’à ce que le dernier objet successeur soit fermé, sauf indication contraire (voir le cas de fermeture de l’écouteur NDK ci-dessous qui a un effet secondaire obligatoire).
Le fournisseur ne doit pas terminer la demande de fermeture sur un objet antécédent (y compris la demande de fermeture NDK_ADAPTER ) avant qu’un rappel d’achèvement de fermeture en cours sur un objet successeur ne retourne au fournisseur. Cela permet aux consommateurs NDK de décharger en toute sécurité.
Un consommateur NDK n’appelle pas NdkCloseObject pour un objet NDK_ADAPTER (qui est un appel bloquant) à partir d’une fonction de rappel de consommateur.
Examinez le cas suivant :
- Le consommateur appelle NdkCloseObject sur un objet de file d’attente d’achèvement (CQ).
- Le fournisseur retourne STATUS_PENDING et appelle ultérieurement le rappel d’achèvement du consommateur.
- Dans ce rappel d’achèvement, le consommateur signale à un événement qu’il est maintenant ok pour fermer le NDK_ADAPTER.
- Un autre thread se réveille sur ce signal, ferme le NDK_ADAPTER et procède au déchargement.
- Toutefois, le thread dans lequel le rappel de fin de fermeture CQ du consommateur a été appelé peut toujours se trouver à l’intérieur de la fonction de rappel du consommateur (par exemple, l’épilogue de la fonction). Il n’est donc pas sûr pour le pilote consommateur de décharger.
- Étant donné que le contexte de rappel d’achèvement est le seul contexte que le consommateur peut signaler l’événement, le pilote consommateur ne peut pas résoudre le problème de déchargement sécurisé lui-même.
Il doit y avoir un moment où le consommateur peut être assuré que tous ses rappels ont retourné le contrôle. Dans NDKPI, ce point correspond au moment où la demande de fermeture sur un NDK_ADAPTER retourne le contrôle. Notez que NDK_ADAPTER demande de fermeture est un appel bloquant. Lorsqu’une demande de fermeture NDK_ADAPTER retourne, il est garanti que tous les rappels sur tous les objets qui descendent de cet objet NDK_ADAPTER ont retourné le contrôle au fournisseur.
Le fournisseur ne doit pas terminer une demande de fermeture sur un objet tant que :
- Toutes les demandes asynchrones en attente sur l’objet ont été effectuées (en d’autres termes, leurs rappels d’achèvement sont retournés au fournisseur).
- Tous les rappels d’événements du consommateur (par exemple, NdkCqNotificationCallback (NDK_FN_CQ_NOTIFICATION_CALLBACK) sur un CQ, NdkConnectEventCallback (NDK_FN_CONNECT_EVENT_CALLBACK) sur un écouteur) sont retournés au fournisseur.
Le fournisseur doit garantir qu’il n’y aura plus de rappels après l’appel du rappel d’achèvement de fermeture ou après le retour de la demande de fermeture STATUS_SUCCESS. Notez qu’une demande de fermeture doit également lancer tout vidage ou annulation nécessaire des demandes asynchrones en attente.
Note Il découle logiquement de ce qui précède qu’un consommateur NDK ne doit pas appeler NdkCloseObject pour un objet NDK_ADAPTER (qui est un appel bloquant) à partir d’une fonction de rappel de consommateur.