Add context-aware read/write (#57)

Adds ReadContext/WriteContext methods to endpoints and to streams. Update rawread example tool to use ReadContext for implementation of "timeout" flag.
This commit is contained in:
Sebastian Zagrodzki
2018-11-05 15:33:31 +01:00
committed by GitHub
parent 593cfb67e9
commit da849d96b5
11 changed files with 273 additions and 80 deletions

View File

@@ -22,10 +22,17 @@ import (
)
type fakeTransfer struct {
// done is the channel that needs to be closed when the transfer has finished.
// done is the channel that needs to receive a signal when the transfer has
// finished.
// This is different from finished below - done is provided by the caller
// and is used to signal the caller.
done chan struct{}
// mu protects transfer data and status.
mu sync.Mutex
// buf is the slice for reading/writing data between the submit() and wait() returning.
buf []byte
// finished is true after the transfer is no longer in flight
finished bool
// status will be returned by wait() on this transfer
status TransferStatus
// length is the number of bytes used from the buffer (write) or available
@@ -33,6 +40,36 @@ type fakeTransfer struct {
length int
}
func (t *fakeTransfer) setData(d []byte) {
t.mu.Lock()
defer t.mu.Unlock()
if t.finished {
return
}
copy(t.buf, d)
t.length = len(d)
}
func (t *fakeTransfer) setLength(n int) {
t.mu.Lock()
defer t.mu.Unlock()
if t.finished {
return
}
t.length = n
}
func (t *fakeTransfer) setStatus(st TransferStatus) {
t.mu.Lock()
defer t.mu.Unlock()
if t.finished {
return
}
t.status = st
t.finished = true
t.done <- struct{}{}
}
// fakeLibusb implements a fake libusb stack that pretends to have a number of
// devices connected to it (see fakeDevices variable for a list of devices).
// fakeLibusb is expected to implement all the functions related to device
@@ -162,18 +199,25 @@ func (f *fakeLibusb) setAlt(d *libusbDevHandle, intf, alt uint8) error {
return nil
}
func (f *fakeLibusb) alloc(_ *libusbDevHandle, _ *EndpointDesc, _ time.Duration, _ int, bufLen int, done chan struct{}) (*libusbTransfer, error) {
func (f *fakeLibusb) alloc(_ *libusbDevHandle, _ *EndpointDesc, _ int, bufLen int, done chan struct{}) (*libusbTransfer, error) {
f.mu.Lock()
defer f.mu.Unlock()
t := newFakeTransferPointer()
f.ts[t] = &fakeTransfer{buf: make([]byte, bufLen), done: done}
return t, nil
}
func (f *fakeLibusb) cancel(t *libusbTransfer) error { return errors.New("not implemented") }
func (f *fakeLibusb) cancel(t *libusbTransfer) error {
f.mu.Lock()
ft := f.ts[t]
f.mu.Unlock()
ft.setStatus(TransferCancelled)
return nil
}
func (f *fakeLibusb) submit(t *libusbTransfer) error {
f.mu.Lock()
ft := f.ts[t]
f.mu.Unlock()
ft.finished = false
f.submitted <- ft
return nil
}