Tasks are a primitive for asynchronous programming and an alternative to working with threads directly. Instead of creating a thread, performing work, then waiting on it using synchronization primitives, you only define a unit of work and let a scheduler decide when and where to execute it. The threads that the scheduler uses are created once and reused for many tasks throughout the program's lifetime. In most cases, creating and executing a task requires not even a single syscall and is a significantly faster operation than creating a thread, resulting in lower latency. Furthermore, tasks from different subsystems can be automatically interleaved by the scheduler, which is difficult to achieve manually with threads without communication between the subsystems.
The library is written in standard C11 and only depends on the C POSIX library. It is designed to be easy to integrate into a project by just copying the header and simple enough to be understood in an afternoon.
Started from learning about Protothreads (cooperative concurrency) as described by Adam Dunkels [1], and ended up devising a Task manager/runner library with a main loop, so multiple protothreads could be scheduled easily. At any given point in time, any of the scheduled tasks could be running or yielding on some continuation point.
There's some beauty in grasping these concepts from the ground up. Some time later I had to learn JavaScript, and the concept of async/await clicked so fast and nicely in my mind. Saving distances, the core idea is fundamentally the same, and that was enlightening (and fun!)
[1]: https://dunkels.com/adam/pt/