12.7. Hàm gọi lại kênh¶
Đối tượng backend được truyền vào protocol.register() là một lớp Python. Thư viện protocol không kiểm tra lớp đó triển khai những phương thức nào; nó kiểm tra instance và kết nối những phương thức tìm thấy. Cơ chế introspection đó chính là điều làm cho giao diện backend trở nên linh hoạt: backend nhỏ nhất chỉ cần hai phương thức, backend phức tạp nhất có mười hai, và ứng dụng có thể chọn từng khả năng một.
12.7.1. Các quy tắc introspection¶
Khi protocol.register() chạy, thư viện duyệt qua một danh sách cố định các tên callable và liên kết từng tên tìm thấy trên instance backend:
Thêm
readvào lớp sẽ bậtCHANNEL_FLAG_READ. Một lệnh gọi từ host tớichannel_read()chỉ đến backend nếu cờ này được đặt.Thêm
writesẽ bậtCHANNEL_FLAG_WRITE, kích hoạtchannel_write().Thêm
lockvàunlocksẽ bậtCHANNEL_FLAG_LOCK, cho phép host khóa kênh để thực hiện đọc nguyên tử nhiều gói.Thêm
pollcho phép host hỏi "có dữ liệu sẵn sàng không?" một cách nhẹ nhàng, không cần thực hiện đọc đầy đủ.
Các phương thức bị thiếu không phải là lỗi -- thư viện protocol chỉ để khả năng tương ứng bị vô hiệu hóa. Một backend chỉ có size và read là hoàn toàn hợp lệ; đó là kênh dữ liệu chỉ đọc.
12.7.2. Kênh cảm biến chỉ đọc¶
Một kênh cảm biến công bố dữ liệu mới mỗi khi host yêu cầu, từ chối ghi từ host, sử dụng bốn hàm gọi lại:
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))
Giải thích từng phương thức làm gì:
polltrả về cờ freshness. Host gọi nó trước khi đọc và bỏ qua việc đọc hoàn toàn khi nó trả vềFalse. Điều đó tiết kiệm chi phí round-trip cho trường hợp "chưa có dữ liệu mới".sizetái tạo bộ đệm theo yêu cầu và báo cáo độ dài của nó. Việc lấy mẫu tại đây có nghĩa là backend không cần tác vụ nền -- mỗi lệnh gọi từ host điều khiển một phép đo.readtrả về một đoạn của bộ đệm. Thư viện protocol có thể gọi nó nhiều hơn một lần khi bộ đệm lớn hơn payload tối đa đã thỏa thuận; tham sốoffsetduyệt qua các đoạn.Không có
writenghĩa là ghi từ host bị từ chối ở tầng đóng khung, trước khi backend tham gia.
12.7.3. Tập hàm gọi lại đầy đủ¶
Để tham khảo, mọi phương thức mà thư viện tìm kiếm trên một backend:
Phương thức |
Trả về |
Mục đích |
|---|---|---|
|
object |
Khởi tạo một lần tùy chọn khi kênh lần đầu liên kết với host. Trả về bất kỳ giá trị nào khác |
|
bool |
Trả về |
|
bool |
Giữ kênh để thực hiện truyền nguyên tử nhiều gói. |
|
bool |
Giải phóng |
|
int |
Số byte hiện có thể đọc từ kênh. |
|
tuple |
Tối đa bốn số nguyên mô tả cấu trúc dữ liệu (ví dụ: chiều cao ảnh, chiều rộng, số byte). Được host sử dụng để giải mã bộ đệm có kiểu. |
|
bytes |
Trả về tối đa size byte bắt đầu từ offset. Được gọi một lần cho mỗi đoạn khi payload vượt quá giới hạn tối đa đã thỏa thuận. |
|
bytes |
Biến thể zero-copy của |
|
int |
Host đã ghi data tại offset. |
|
int |
Opcode do ứng dụng định nghĩa nằm ngoài mô hình đọc/ghi. Giá trị trả về âm là lỗi. |
|
object |
Xóa dữ liệu đang được đệm. Được gọi khi host muốn đặt lại kênh. |
|
bool |
Chỉ có nghĩa với các backend đại diện cho transport vật lý (các kênh USB tích hợp). Các kênh ứng dụng không cần điều này. |
Đó là toàn bộ giao diện backend. Mười hai tên phương thức, tất cả đều tùy chọn, và thư viện protocol quyết định mỗi kênh có thể làm gì dựa trên những phương thức nào có mặt.