cancel_reader

Version, currently main branch1 version
  • main branchlatestFeb 19, 2026

github.com/dsisnero/cancel_reader

A Crystal port of muesli/cancelreader - a cancelable reader that allows interrupting read operations without consuming data. Supports Linux (epoll), BSD (kqueue), Unix (select), and Windows (fallback).

0 stars
1 dependent
License: MIT

Installation

# Add this to your shard.yml
dependencies:
  cancel_reader:
    github: dsisnero/cancel_reader
    branch: main

main is a branch, not a release, so this tracks it rather than pinning a version.

Then run:

shards install

shard.yml

Crystal
>= 1.19.1
License
MIT
Author
Dominic Sisneros
Target
  • cancel_reader from src/cancel_reader.cr

Dependencies

Development Dependencies

  • ameba~> 1.0github: crystal-ameba/amebadev

README

cancel_reader

CI Version License Crystal

A Crystal port of muesli/cancelreader Go library.

This library provides a cancelable reader that allows interrupting read operations.

Source: The original Go source is included as a git submodule in vendor/ (commit 245609e).

Status: Complete port with all functionality from the Go library. All tests pass on Linux, macOS, and Windows (except BSD kqueue tests which are pending due to timing issues). The library is ready for production use.

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      cancel_reader:
        github: dsisnero/cancel_reader
  2. Run shards install

Usage

require "cancel_reader"

# Create a cancelable reader from any IO
reader = CancelReader.new_reader(some_io)

# Read from the reader (blocks until data available)
slice = Bytes.new(1024)
bytes_read = reader.read(slice)

# Cancel ongoing reads (returns true if cancellation succeeded)
cancelled = reader.cancel

# After cancellation, subsequent reads raise CancelReader::CanceledError
begin
  reader.read(slice)
rescue ex : CancelReader::CanceledError
  puts "Read was canceled"
end

Platform Support

  • Linux: Uses epoll for file descriptors.
  • BSD (macOS, FreeBSD, etc.): Uses kqueue, except for /dev/tty which falls back to select.
  • Other Unix: Uses select.
  • Windows: Falls back to a non‑interruptible reader (cancellation only prevents future reads).
  • FD_SETSIZE limit: File descriptors ≥ 1024 cannot be used with select‑based implementations (BSD /dev/tty and other Unix); they automatically fall back to the non‑interruptible reader.

See the original Go documentation for detailed usage.

Development

This project uses standard Crystal development tools:

  • make install – Install dependencies
  • make update – Update dependencies
  • make format – Check code formatting
  • make lint – Run ameba linter (auto‑fix + check)
  • make test – Run Crystal specs
  • make clean – Remove temporary files
  • See examples/ directory for usage examples

Always run make lint and make test before committing.

Contributing

This is a port; changes must match the behavior of the original Go library. If you find a discrepancy, please open an issue.

Detailed contribution guidelines are in CONTRIBUTING.md. Please read them before submitting changes.

The quick workflow:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/your-change)
  3. Make your changes, ensuring they match Go behavior
  4. Run make lint and make test
  5. Commit with a descriptive message
  6. Push and open a Pull Request

Contributors