12.7. Kanalåteranrop¶
Backend-objektet som skickas till protocol.register() är en Python-klass. Protokollbiblioteket frågar inte klassen vilka metoder den implementerar; det inspekterar instansen och kopplar in dem den hittar. Den introspektionen är vad som gör backend-gränssnittet flexibelt: den minsta användbara backenden är två metoder, den mest avancerade är tolv, och applikationen ansluter sig till varje förmåga en metod i taget.
12.7.1. Introspektionsreglerna¶
När protocol.register() körs går biblioteket igenom en fast lista med anropbara namn och binder varje sådant som det hittar på backend-instansen:
Att lägga till
readi klassen slår påCHANNEL_FLAG_READ. Ett värdanrop tillchannel_read()når bara backenden om denna flagga är satt.Att lägga till
writeslår påCHANNEL_FLAG_WRITEoch aktiverarchannel_write().Att lägga till
lockochunlockslår påCHANNEL_FLAG_LOCKoch låter värden låsa kanalen för en atomär läsning över flera paket.Att lägga till
polllåter värden billigt fråga ”finns det något klart?” utan att tvinga fram en fullständig läsning.
Saknade metoder är inte fel – protokollbiblioteket lämnar bara motsvarande förmåga inaktiverad. En backend med endast size och read är helt giltig; det är en skrivskyddad datakanal.
12.7.2. En skrivskyddad sensorkanal¶
En sensorkanal som publicerar en färsk avläsning varje gång värden frågar och vägrar skrivningar från värden använder fyra av återanropen:
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))
En genomgång av vad varje metod gör:
pollreturnerar färskhetsflaggan. Värden anropar den före läsning och hoppar över läsningen helt när den returnerarFalse. Det sparar in tur-och-retur-kostnaden för ”ingen ny data ännu”.sizeregenererar bufferten vid behov och rapporterar dess längd. Att utföra samplingen här innebär att backenden inte behöver någon bakgrundsuppgift – ett värdanrop driver varje mätning.readreturnerar en del av bufferten. Protokollbiblioteket kan anropa den mer än en gång när bufferten är större än den förhandlade maximala nyttolasten; argumentetoffsetgår igenom fragmenten.Avsaknad av
writeinnebär att skrivningar från värden avvisas i ramnivån, innan backenden är inblandad.
12.7.3. Den fullständiga uppsättningen återanrop¶
För referens, varje metod som biblioteket letar efter på en backend:
Metod |
Returnerar |
Syfte |
|---|---|---|
|
objekt |
Valfri engångsinitialisering när kanalen först binds till en värd. Returnera valfritt värde som inte är |
|
bool |
Returnera |
|
bool |
Reservera kanalen för en atomär överföring över flera paket. |
|
bool |
Frigör ett tidigare |
|
int |
Antal byte som för närvarande kan läsas från kanalen. |
|
tuple |
Upp till fyra heltal som beskriver datastrukturen (t.ex. bildhöjd, bredd, antal byte). Används av värden för att packa upp typade buffertar. |
|
bytes |
Returnera upp till size byte med start vid offset. Anropas en gång per fragment när nyttolasten överskrider det förhandlade maximumet. |
|
bytes |
Nollkopieringsvariant av |
|
int |
Värden skrev data vid offset. |
|
int |
Applikationsdefinierad opkod utanför läs-/skrivmodellen. Negativ retur är ett fel. |
|
objekt |
Kasta all buffrad data. Anropas när värden vill återställa kanalen. |
|
bool |
Endast meningsfull på backendar som representerar en fysisk transport (de inbyggda USB-kanalerna). Applikationskanaler behöver inte detta. |
Det är hela backend-gränssnittet. Tolv metodnamn, alla valfria, och protokollbiblioteket avgör vad varje kanal kan göra utifrån vilka som finns.