Blame view

3rdparty/boost_1_81_0/libs/fiber/doc/nonblocking.qbk 2.95 KB
977ed18d   Hu Chunming   提交三方库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  [/
        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]