12.7. Fonctions de rappel de canal¶
L’objet backend transmis à protocol.register() est une classe Python. La bibliothèque de protocole ne demande pas à la classe quelles méthodes elle implémente ; elle inspecte l’instance et connecte celles qu’elle trouve. Cette introspection est ce qui rend l’interface du backend flexible : le plus petit backend utile compte deux méthodes, le plus élaboré en compte douze, et l’application active chaque capacité une méthode à la fois.
12.7.1. Les règles d’introspection¶
Lorsque protocol.register() s’exécute, la bibliothèque parcourt une liste fixe de noms appelables et lie chacun de ceux qu’elle trouve sur l’instance du backend :
Ajouter
readà la classe activeCHANNEL_FLAG_READ. Un appel hôte àchannel_read()n’atteint le backend que si cet indicateur est défini.Ajouter
writeactiveCHANNEL_FLAG_WRITE, ce qui rend possiblechannel_write().Ajouter
locketunlockactiveCHANNEL_FLAG_LOCK, permettant à l’hôte de verrouiller le canal pour une lecture atomique sur plusieurs paquets.Ajouter
pollpermet à l’hôte de demander à moindre coût « quelque chose est-il prêt ? », sans forcer une lecture complète.
Les méthodes manquantes ne sont pas des erreurs – la bibliothèque de protocole laisse simplement la capacité correspondante désactivée. Un backend doté uniquement de size et read est parfaitement valide ; c’est un canal de données en lecture seule.
12.7.2. Un canal de capteur en lecture seule¶
Un canal de capteur qui publie une nouvelle lecture chaque fois que l’hôte la demande, en refusant les écritures de l’hôte, met en œuvre quatre des fonctions de rappel
import protocol
import struct
class TempChannel:
def __init__(self, read_sensor):
self._read_sensor = read_sensor
self._buf = b''
self._fresh = False
def poll(self):
# Tell the host whether a reading is waiting.
return self._fresh
def size(self):
# Sample fresh data on every host-side size query.
value = self._read_sensor()
self._buf = struct.pack('<f', value)
self._fresh = True
return len(self._buf)
def read(self, offset, size):
end = offset + size
if end >= len(self._buf):
self._fresh = False
return self._buf[offset:end]
protocol.register(name='temp', backend=TempChannel(read_temperature))
Passons en revue ce que fait chaque méthode :
pollrenvoie l’indicateur de fraîcheur. L’hôte l’appelle avant de lire et saute entièrement la lecture lorsqu’il renvoieFalse. Cela évite le coût de l’aller-retour pour « pas encore de nouvelles données ».sizerégénère le tampon à la demande et indique sa longueur. Réaliser l’échantillonnage ici signifie que le backend n’a pas besoin d’une tâche en arrière-plan – un appel hôte pilote chaque mesure.readrenvoie une portion du tampon. La bibliothèque de protocole peut l’appeler plusieurs fois lorsque le tampon est plus grand que la charge utile maximale négociée ; l’argumentoffsetparcourt les fragments.L’absence de
writesignifie que les écritures de l’hôte sont refusées au niveau de la couche de tramage, avant même que le backend ne soit impliqué.
12.7.3. L’ensemble complet des fonctions de rappel¶
Pour référence, voici toutes les méthodes que la bibliothèque recherche sur un backend :
Méthode |
Renvoie |
Objet |
|---|---|---|
|
objet |
Initialisation facultative en une seule fois lorsque le canal se lie pour la première fois à un hôte. Renvoie toute valeur non |
|
bool |
Renvoie |
|
bool |
Acquiert le canal pour un transfert atomique sur plusieurs paquets. |
|
bool |
Libère un |
|
int |
Nombre d’octets actuellement lisibles depuis le canal. |
|
tuple |
Jusqu’à quatre entiers décrivant la structure des données (par exemple hauteur d’image, largeur, nombre d’octets). Utilisé par l’hôte pour décompresser les tampons typés. |
|
bytes |
Renvoie jusqu’à size octets à partir de offset. Appelé une fois par fragment lorsque la charge utile dépasse le maximum négocié. |
|
bytes |
Variante sans copie de |
|
int |
L’hôte a écrit data à l’emplacement offset. |
|
int |
Opcode défini par l’application en dehors du modèle lecture/écriture. Une valeur de retour négative indique une erreur. |
|
objet |
Supprime toutes les données mises en tampon. Appelé lorsque l’hôte souhaite réinitialiser le canal. |
|
bool |
N’a de sens que sur les backends qui représentent un transport physique (les canaux USB intégrés). Les canaux d’application n’en ont pas besoin. |
C’est là toute l’interface du backend. Douze noms de méthodes, toutes facultatives, et la bibliothèque de protocole décide de ce que chaque canal peut faire en fonction de celles qui sont présentes.