# ncurses-poll ## 1. Introduction This repository contains a simple header, [ncurses-poll.hpp](src/ncurses-poll.hpp). With it, you can perform non-blocking I/O in your ncurses application. ## 2. Features ### 2.1 Multiple instances Each instance of `ncurses_poll` wraps an ncurses `SCREEN*`. Multiple instances can be handled simultaneously in one thread. Note that there's no need to call `set_term()` because this is done by the header before callbacks are invoked. ### 2.2 Boost.Asio and coroutines Asynchronous I/O is achieved using Boost.Asio. Thus, other libraries(e.g. [Beast](https://github.com/boostorg/beast)) which uses Boost.Asio can be easily integrated into your ncurses applications. Boost.Asio's stackless coroutine is also supported for cleaner and human-friendlier code. ## 3. Documentation ### 3.1 Event loop An `ncurses_poll` instance must run within a Boost.Asio event loop (aka `io_context`). A const reference to an `io_context` instance should be passed to the constructor. ### 3.2 Session The `ncurses_poll` class template requires a parameter `Session`, which is the type of session. The session may contain username, permission, or other data concerning a specific connection. `Session` must be a class with a constructor which accepts a pointer to this `ncurses_poll` class. To get pointer to current session instance of an `ncurses_poll` instance, call `session()` method. ### 3.2 Async read/write A read/write operation may block, so we need to determine whether the stream is readable/writable before performing I/O. The `on_readable` and `on_writable` methods accept a single parameter, the const reference to a callback function. Once the stream is readable/writable, the given callback will be invoked. The callback function should be of the following type: ```C++ using callback = std::function; ``` * The first argument of callback is the error code, upon success it yields zero, otherwise it is set to the corresponding errno. You should always handle `error_code` before performing I/O. * The second argument is the pointer to the `ncurses_poll` instance. ### 3.3 Using coroutines Boost.Asio's stackless coroutine requires a `boost::asio::coroutine` instance. You can simply use the `coro` property of `ncurses_poll`. For example, in a callback function: ```C++ if (!ec) reenter(poll->coro) for (;;) { yield poll->on_writable(cb); // ... } ``` ### 3.4 Other operations To get corresponding `io_context` instance, call `get_io_context()` method. To get `SCREEN` pointer to current ncurses instance, call `screen()` method. ### 3.5 See also * [Examples](/examples) for using `ncurses_poll`. * [Ncurses Programming Guide](http://www.cs.ukzn.ac.za/~hughm/os/notes/ncurses.html). * Boost.Asio [documentation](https://www.boost.org/doc/libs/1_67_0/doc/html/boost_asio.html).