nonblocking.qbk 3.0 KB

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