12.7. Callbacks de canal¶
O objeto de backend passado a protocol.register() é uma classe Python. A biblioteca de protocolo não interroga a classe sobre os métodos que implementa; inspeciona a instância e liga os que encontra. É essa introspecção que torna a interface de backend flexível: o backend minimamente útil tem dois métodos, o mais elaborado tem doze, e a aplicação adere a cada capacidade um método de cada vez.
12.7.1. As regras de introspecção¶
Quando protocol.register() é executado, a biblioteca percorre uma lista fixa de nomes invocáveis e liga cada um que encontrar na instância de backend:
Adicionar
readà classe ativaCHANNEL_FLAG_READ. Uma chamada do host achannel_read()só chega ao backend se este sinalizador estiver ativo.Adicionar
writeativaCHANNEL_FLAG_WRITE, habilitandochannel_write().Adicionar
lockeunlockativaCHANNEL_FLAG_LOCK, permitindo ao host bloquear o canal para uma leitura atómica de múltiplos pacotes.Adicionar
pollpermite ao host perguntar «há algo pronto?» de forma económica, sem forçar uma leitura completa.
Os métodos em falta não são erros – a biblioteca de protocolo simplesmente deixa a capacidade correspondente desativada. Um backend com apenas size e read é perfeitamente válido; é um canal de dados só de leitura.
12.7.2. Um canal de sensor só de leitura¶
Um canal de sensor que publica uma leitura atualizada sempre que o host pergunta, recusando escritas do host, exercita quatro dos callbacks:
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))
Percorrendo o que cada método faz:
polldevolve o sinalizador de atualização. O host chama-o antes de ler e salta a leitura por completo quando devolveFalse. Isto poupa o custo da ida e volta para «ainda não há dados novos.»sizeregenera o buffer a pedido e reporta o seu comprimento. Fazer a amostragem aqui significa que o backend não precisa de uma tarefa em segundo plano – cada medição é desencadeada por uma chamada do host.readdevolve uma fatia do buffer. A biblioteca de protocolo pode chamá-lo mais do que uma vez quando o buffer é maior que o payload máximo negociado; o argumentooffsetpercorre os fragmentos.A ausência de
writefaz com que as escritas do host sejam recusadas na camada de enquadramento, antes de o backend ser envolvido.
12.7.3. O conjunto completo de callbacks¶
Para referência, todos os métodos que a biblioteca procura num backend:
Método |
Devolve |
Objetivo |
|---|---|---|
|
objeto |
Inicialização opcional de execução única quando o canal se liga pela primeira vez a um host. Devolva qualquer valor não |
|
bool |
Devolve |
|
bool |
Adquire o canal para uma transferência atómica de múltiplos pacotes. |
|
bool |
Liberta um |
|
int |
Número de bytes atualmente legíveis do canal. |
|
tuple |
Até quatro inteiros que descrevem a estrutura dos dados (por exemplo, altura, largura e contagem de bytes de uma imagem). Usado pelo host para desempacotar buffers tipados. |
|
bytes |
Devolve até size bytes a partir de offset. Chamado uma vez por fragmento quando o payload excede o máximo negociado. |
|
bytes |
Variante de cópia zero de |
|
int |
O host escreveu data em offset. |
|
int |
Opcode definido pela aplicação fora do modelo de leitura/escrita. Um valor de retorno negativo indica erro. |
|
objeto |
Descarta quaisquer dados em buffer. Chamado quando o host quer reiniciar o canal. |
|
bool |
Só é relevante em backends que representam um transporte físico (os canais USB integrados). Os canais de aplicação não precisam disto. |
É esta a interface de backend completa. Doze nomes de métodos, todos opcionais, e a biblioteca de protocolo decide o que cada canal pode fazer com base nos que estão presentes.