Leggere in inglese

Condividi tramite


Requisiti di durata dell'oggetto NDKPI

Come vengono creati, usati e chiusi gli oggetti NDK

Un consumer NDK avvia una richiesta di creazione per un oggetto NDK chiamando la funzione di creazione del provider NDK per tale oggetto.

Quando il consumer chiama una funzione create, passa un NdkCreateCompletion (NDK_FN_CREATE_COMPLETION) come parametro.

Il consumatore avvia varie richieste chiamando le funzioni del provider nella tabella di dispatch dell'oggetto, passando un callback di completamento NdkRequestCompletion (NDK_FN_REQUEST_COMPLETION) come parametro.

Quando un oggetto non è più necessario, il consumatore chiama la funzione NdkCloseObject (NDK_FN_CLOSE_OBJECT) per avviare una richiesta di chiusura per l'oggetto, passando un callback NdkCloseCompletion (NDK_FN_CLOSE_COMPLETION) come parametro.

Il fornitore chiama la funzione di richiamata del consumatore per completare la richiesta in modo asincrono. Questa chiamata indica al consumer che il provider ha completato l'operazione , ad esempio chiudendo l'oggetto, e restituendo il controllo al consumer. Se il provider completa la richiesta di chiusura in modo sincrono, con successo o con un errore, non effettuerà la chiamata alla funzione di callback del consumer.

Regole per i callback di completamento

Quando un provider ha creato un oggetto su richiesta di un consumatore, il provider chiama il callback NdkCreateCompletion per indicare che l'oggetto è pronto per l'uso.

Il consumer può chiamare altre funzioni del provider per lo stesso oggetto senza attendere che venga restituito il primo callback.

Il consumer non chiamerà la funzione NdkCloseObject per un oggetto finché non vengono restituite tutte le funzioni del provider per tale oggetto.

Tuttavia, se la funzione del provider avvia una richiesta di completamento, il consumer è libero di chiamare NdkCloseObject dall'interno del callback di completamento, anche se la funzione del provider non è stata restituita.

Una funzione del provider può avviare una richiesta di completamento prima di restituire da un callback eseguendo una delle operazioni seguenti:

  • Richiamare direttamente il callback di completamento
  • Mettere in coda la richiesta di completamento su un altro thread

Avviando una richiesta di completamento, il provider restituisce effettivamente il controllo al consumer. Il provider deve presupporre che l'oggetto possa essere chiuso in qualsiasi momento dopo che il provider avvia la richiesta di completamento.

Nota Per evitare deadlock dopo l'avvio di una richiesta di completamento, il provider deve:

  • Non eseguire altre operazioni sull'oggetto fino a quando non viene restituito il callback di completamento.
  • Prendere le misure necessarie per mantenere intatto l'oggetto, se il provider deve assolutamente toccare l'oggetto.

Esempio: interazione Consumer-Provider

Si consideri lo scenario seguente:

  1. Il consumer crea un connettore (NDK_CONNECTOR) e quindi chiama NdkConnect (NDK_FN_CONNECT).
  2. Il provider elabora la richiesta di connessione, incontra un errore e chiama il callback di completamento del consumatore nel contesto della chiamata NdkConnect (anziché restituire immediatamente un errore a causa di una scelta di implementazione interna).
  3. Il consumatore chiama NdkCloseObject nel contesto di questo callback di completamento, anche se la chiamata a NdkConnect non è ancora stata restituita al consumatore.

Per evitare deadlock, il provider non deve toccare l'oggetto del connettore dopo la fase 2 (il punto in cui ha avviato il callback di completamento all'interno della chiamata NdkConnect).

Chiusura di oggetti antecedenti e successori

Il provider deve essere preparato affinché il consumer chiami la funzione NdkCloseObject per chiudere un oggetto precedente prima che il consumer chiami NdkCloseObject per gli oggetti successori. Se il consumer esegue questa operazione, ecco cosa deve fare il provider:

  • Il provider non deve chiudere l'oggetto antecedente finché tutti gli oggetti successori non vengono chiusi, cioè, il provider deve restituire STATUS_PENDING dalla richiesta di chiusura e completarla (chiamando la funzione NdkCloseCompletion registrata per la richiesta di chiusura) una volta chiusi tutti gli oggetti successori.
  • Il consumer non utilizzerà l'oggetto precedente dopo aver chiamato NdkCloseObject su di esso, quindi il provider non deve aggiungere alcuna gestione per i fallimenti di ulteriori funzioni del provider sull'oggetto precedente (ma potrebbe farlo se lo desidera).
  • Il provider può trattare la richiesta di chiusura come una semplice dereferenziazione che non ha altro effetto collaterale fino alla chiusura dell'ultimo oggetto successore, a meno che non sia diversamente richiesto (vedere il caso di chiusura del listener NDK sotto il quale ha un effetto collaterale obbligatorio).

Il provider non deve completare la richiesta di chiusura su un oggetto precedente (inclusa la richiesta di chiusura NDK_ADAPTER) prima che qualsiasi callback di completamento di chiusura in corso su qualsiasi oggetto successore venga restituita al provider. Ciò consente ai consumer NDK di scaricare in modo sicuro.

Un consumer NDK non chiamerà NdkCloseObject per un oggetto NDK_ADAPTER (ovvero una chiamata di blocco) dall'interno di una funzione di callback del consumer.

Chiusura di oggetti adattatore

Si consideri lo scenario seguente:

  1. Il consumer chiama NdkCloseObject su un oggetto CQ (Completion Queue).
  2. Il provider restituisce STATUS_PENDING e successivamente chiama il callback di completamento del consumer.
  3. All'interno di questo callback di completamento, il consumatore segnala un evento che indica che ora si può chiudere l'NDK_ADAPTER.
  4. Un altro thread si sveglia su questo segnale e chiude il NDK_ADAPTER e procede a scaricare.
  5. Tuttavia, il thread in cui è stato chiamato il callback di chiusura CQ del consumer potrebbe ancora trovarsi all'interno della funzione di callback del consumer ( ad esempio, la funzione epilogo), quindi non è sicuro che il driver consumer scarichi.
  6. Poiché il contesto di callback di completamento è l'unico contesto che il consumer può segnalare l'evento, il driver consumer non può risolvere il problema di scaricamento sicuro stesso.

Deve esserci un punto in cui il consumer può essere certo che tutte le sue callback abbiano restituito il controllo. In NDKPI questo punto è quando la richiesta di chiusura restituisce il controllo in un NDK_ADAPTER. Si noti che NDK_ADAPTER richiesta di chiusura è una chiamata di blocco. Quando viene restituita una richiesta di chiusura NDK_ADAPTER, è garantito che tutti i callback su tutti gli oggetti che derivano da tale oggetto NDK_ADAPTER abbiano restituito il controllo al provider.

Completamento delle richieste di chiusura

Il provider non deve completare una richiesta di chiusura su un oggetto fino a quando:

  • Tutte le richieste asincrone in sospeso sull'oggetto sono state completate (in altre parole, i callback di completamento sono tornati al provider).
  • Tutti i callback dell'evento del consumer (ad esempio, NdkCqNotificationCallback (NDK_FN_CQ_NOTIFICATION_CALLBACK) su un CQ, NdkConnectEventCallback (NDK_FN_CONNECT_EVENT_CALLBACK) su un listener) sono stati restituiti al provider.

Il provider deve garantire che non avvengano ulteriori callback dopo che il callback di completamento di chiusura è invocato o dopo che la richiesta di chiusura restituisce STATUS_SUCCESS. Si noti che una richiesta di chiusura deve anche avviare qualsiasi svuotamento o annullamento necessario di richieste asincrone in sospeso.

Nota È logico che un consumer NDK non debba chiamare NdkCloseObject per un oggetto NDK_ADAPTER (ovvero una chiamata di blocco) all'interno di una funzione di callback consumer.

Network Direct Kernel Provider Interface (NDKPI)