[/ Copyright Oliver Kowalke, Nat Goodspeed 2015. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt ] [/ import path is relative to this .qbk file] [import ../examples/adapt_nonblocking.cpp] [#nonblocking] [section:nonblocking Integrating Fibers with Nonblocking I/O] [heading Overview] ['Nonblocking] I/O is distinct from ['asynchronous] I/O. A true async I/O operation promises to initiate the operation and notify the caller on completion, usually via some sort of callback (as described in [link callbacks Integrating Fibers with Asynchronous Callbacks]). In contrast, a nonblocking I/O operation refuses to start at all if it would be necessary to block, returning an error code such as [@http://man7.org/linux/man-pages/man3/errno.3.html `EWOULDBLOCK`]. The operation is performed only when it can complete immediately. In effect, the caller must repeatedly retry the operation until it stops returning `EWOULDBLOCK`. In a classic event-driven program, it can be something of a headache to use nonblocking I/O. At the point where the nonblocking I/O is attempted, a return value of `EWOULDBLOCK` requires the caller to pass control back to the main event loop, arranging to retry again on the next iteration. Worse, a nonblocking I/O operation might ['partially] succeed. That means that the relevant business logic must continue receiving control on every main loop iteration until all required data have been processed: a doubly-nested loop, implemented as a callback-driven state machine. __boost_fiber__ can simplify this problem immensely. Once you have integrated with the application's main loop as described in [link integration Sharing a Thread with Another Main Loop], waiting for the next main-loop iteration is as simple as calling [ns_function_link this_fiber..yield]. [heading Example Nonblocking API] For purposes of illustration, consider this API: [NonblockingAPI] [heading Polling for Completion] We can build a low-level wrapper around `NonblockingAPI::read()` that shields its caller from ever having to deal with `EWOULDBLOCK`: [nonblocking_read_chunk] [heading Filling All Desired Data] Given `read_chunk()`, we can straightforwardly iterate until we have all desired data: [nonblocking_read_desired] (Of ['course] there are more efficient ways to accumulate string data. That's not the point of this example.) [heading Wrapping it Up] Finally, we can define a relevant exception: [nonblocking_IncompleteRead] and write a simple `read()` function that either returns all desired data or throws `IncompleteRead`: [nonblocking_read] Once we can transparently wait for the next main-loop iteration using [ns_function_link this_fiber..yield], ordinary encapsulation Just Works. [/ @path link is relative to (eventual) doc/html/index.html, hence ../..] The source code above is found in [@../../examples/adapt_nonblocking.cpp adapt_nonblocking.cpp]. [endsect]