1[/ 2 Copyright Oliver Kowalke, Nat Goodspeed 2015. 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 http://www.boost.org/LICENSE_1_0.txt 6] 7 8[/ import path is relative to this .qbk file] 9[import ../examples/adapt_nonblocking.cpp] 10 11[#nonblocking] 12[section:nonblocking Integrating Fibers with Nonblocking I/O] 13 14[heading Overview] 15 16['Nonblocking] I/O is distinct from ['asynchronous] I/O. A true async I/O 17operation promises to initiate the operation and notify the caller on 18completion, usually via some sort of callback (as described in [link callbacks 19Integrating Fibers with Asynchronous Callbacks]). 20 21In contrast, a nonblocking I/O operation refuses to start at all if it would 22be necessary to block, returning an error code such as 23[@http://man7.org/linux/man-pages/man3/errno.3.html `EWOULDBLOCK`]. The 24operation is performed only when it can complete immediately. In effect, the 25caller must repeatedly retry the operation until it stops returning 26`EWOULDBLOCK`. 27 28In a classic event-driven program, it can be something of a headache to use 29nonblocking I/O. At the point where the nonblocking I/O is attempted, a return 30value of `EWOULDBLOCK` requires the caller to pass control back to the main 31event loop, arranging to retry again on the next iteration. 32 33Worse, a nonblocking I/O operation might ['partially] succeed. That means that 34the relevant business logic must continue receiving control on every main loop 35iteration until all required data have been processed: a doubly-nested loop, 36implemented as a callback-driven state machine. 37 38__boost_fiber__ can simplify this problem immensely. Once you have integrated 39with the application's main loop as described in [link integration Sharing a 40Thread with Another Main Loop], waiting for the next main-loop iteration is as 41simple as calling [ns_function_link this_fiber..yield]. 42 43[heading Example Nonblocking API] 44 45For purposes of illustration, consider this API: 46 47[NonblockingAPI] 48 49[heading Polling for Completion] 50 51We can build a low-level wrapper around `NonblockingAPI::read()` that 52shields its caller from ever having to deal with `EWOULDBLOCK`: 53 54[nonblocking_read_chunk] 55 56[heading Filling All Desired Data] 57 58Given `read_chunk()`, we can straightforwardly iterate until we have all 59desired data: 60 61[nonblocking_read_desired] 62 63(Of ['course] there are more efficient ways to accumulate string data. That's 64not the point of this example.) 65 66[heading Wrapping it Up] 67 68Finally, we can define a relevant exception: 69 70[nonblocking_IncompleteRead] 71 72and write a simple `read()` function that either returns all desired data or 73throws `IncompleteRead`: 74 75[nonblocking_read] 76 77Once we can transparently wait for the next main-loop iteration using 78[ns_function_link this_fiber..yield], ordinary encapsulation Just Works. 79 80[/ @path link is relative to (eventual) doc/html/index.html, hence ../..] 81The source code above is found in 82[@../../examples/adapt_nonblocking.cpp adapt_nonblocking.cpp]. 83 84[endsect] 85