12.7. Funciones de retorno de canal¶
El objeto backend que se pasa a protocol.register() es una clase de Python. La biblioteca del protocolo no le pregunta a la clase qué métodos implementa; inspecciona la instancia y conecta los que encuentra. Esa introspección es lo que hace flexible la interfaz del backend: el backend útil más pequeño tiene dos métodos, el más elaborado tiene doce, y la aplicación opta por cada capacidad de un método a la vez.
12.7.1. Las reglas de introspección¶
Cuando se ejecuta protocol.register(), la biblioteca recorre una lista fija de nombres de invocables y vincula cada uno que encuentra en la instancia del backend:
Añadir
reada la clase activaCHANNEL_FLAG_READ. Una llamada del host achannel_read()solo llega al backend si este indicador está activado.Añadir
writeactivaCHANNEL_FLAG_WRITE, habilitandochannel_write().Añadir
lockyunlockactivaCHANNEL_FLAG_LOCK, permitiendo al host bloquear el canal para una lectura atómica de varios paquetes.Añadir
pollpermite al host preguntar «¿hay algo listo?» de forma económica, sin forzar una lectura completa.
Los métodos faltantes no son errores: la biblioteca del protocolo simplemente deja deshabilitada la capacidad correspondiente. Un backend con solo size y read es perfectamente válido; es un canal de datos de solo lectura.
12.7.2. Un canal de sensor de solo lectura¶
Un canal de sensor que publica una lectura nueva cada vez que el host lo solicita, rechazando las escrituras del host, utiliza cuatro de las funciones de retorno:
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))
Recorriendo lo que hace cada método:
polldevuelve el indicador de frescura. El host lo llama antes de leer y omite la lectura por completo cuando devuelveFalse. Eso ahorra el costo de ida y vuelta para «todavía no hay datos nuevos».sizeregenera el búfer bajo demanda e informa su longitud. Realizar el muestreo aquí significa que el backend no necesita una tarea en segundo plano: una llamada del host impulsa cada medición.readdevuelve un segmento del búfer. La biblioteca del protocolo puede llamarlo más de una vez cuando el búfer es más grande que la carga útil máxima negociada; el argumentooffsetrecorre los fragmentos.La ausencia de
writesignifica que las escrituras del host se rechazan en la capa de tramado, antes de que el backend intervenga.
12.7.3. El conjunto completo de funciones de retorno¶
Como referencia, cada método que la biblioteca busca en un backend:
Método |
Devuelve |
Propósito |
|---|---|---|
|
object |
Inicialización opcional de una sola vez cuando el canal se vincula por primera vez a un host. Devuelve cualquier valor distinto de |
|
bool |
Devuelve |
|
bool |
Adquiere el canal para una transferencia atómica de varios paquetes. |
|
bool |
Libera un |
|
int |
Número de bytes actualmente legibles del canal. |
|
tuple |
Hasta cuatro enteros que describen la estructura de datos (p. ej., altura de imagen, ancho, recuento de bytes). Usado por el host para desempaquetar búferes tipados. |
|
bytes |
Devuelve hasta size bytes empezando en offset. Se llama una vez por fragmento cuando la carga útil supera el máximo negociado. |
|
bytes |
Variante sin copia de |
|
int |
El host escribió data en offset. |
|
int |
Código de operación definido por la aplicación fuera del modelo de lectura/escritura. Un valor de retorno negativo es un error. |
|
object |
Descarta cualquier dato almacenado en búfer. Se llama cuando el host quiere restablecer el canal. |
|
bool |
Solo tiene sentido en backends que representan un transporte físico (los canales USB integrados). Los canales de aplicación no lo necesitan. |
Esa es toda la interfaz del backend. Doce nombres de método, todos opcionales, y la biblioteca del protocolo decide lo que puede hacer cada canal según cuáles estén presentes.