README.md

 1# CancelReader
 2
 3[![Latest Release](https://img.shields.io/github/release/muesli/cancelreader.svg?style=for-the-badge)](https://github.com/muesli/cancelreader/releases)
 4[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=for-the-badge)](https://pkg.go.dev/github.com/muesli/cancelreader)
 5[![Software License](https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge)](/LICENSE)
 6[![Build Status](https://img.shields.io/github/workflow/status/muesli/cancelreader/build?style=for-the-badge)](https://github.com/muesli/cancelreader/actions)
 7[![Go ReportCard](https://goreportcard.com/badge/github.com/muesli/cancelreader?style=for-the-badge)](https://goreportcard.com/report/muesli/cancelreader)
 8
 9A cancelable reader for Go
10
11This package is based on the fantastic work of [Erik Geiser](https://github.com/erikgeiser)
12in Charm's [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework.
13
14## Usage
15
16`NewReader` returns a reader with a `Cancel` function. If the input reader is a
17`File`, the cancel function can be used to interrupt a blocking `Read` call.
18In this case, the cancel function returns true if the call was canceled
19successfully. If the input reader is not a `File`, the cancel function does
20nothing and always returns false.
21
22```go
23r, err := cancelreader.NewReader(file)
24if err != nil {
25    // handle error
26    ...
27}
28
29// cancel after five seconds
30go func() {
31    time.Sleep(5 * time.Second)
32    r.Cancel()
33}()
34
35// keep reading
36for {
37    var buf [1024]byte
38    _, err := r.Read(buf[:])
39
40    if errors.Is(err, cancelreader.ErrCanceled) {
41        fmt.Println("canceled!")
42        break
43    }
44    if err != nil {
45        // handle other errors
46        ...
47    }
48
49    // handle data
50    ...
51}
52```
53
54## Implementations
55
56- The Linux implementation is based on the epoll mechanism
57- The BSD and macOS implementation is based on the kqueue mechanism
58- The generic Unix implementation is based on the posix select syscall
59
60## Caution
61
62The Windows implementation is based on WaitForMultipleObject with overlapping
63reads from CONIN$. At this point it only supports canceling reads from
64`os.Stdin`.