Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: net/docs/code-patterns.md

Issue 1320933003: Writeup summary of common netstack coding patterns. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporated many comments. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | net/net.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Chrome Network Stack Common Coding Patterns
2
3 ## Combined error and byte count into a single value
4
5 At many places in the network stack, functions return a value that, if
6 positive, indicate a count of bytes that the the function read or
7 wrote, and if negative, indicates a network stack error code (see
8 [net_error_list.h](https://chromium.googlesource.com/chromium/src/+/master/net/b ase/net_error_list.h#1)).
9 Zero indicates either net::OK or zero bytes read (usually EOF)
10 depending on the context. This pattern is generally specified by
11 an |int| return type.
12
Ryan Sleevi 2015/08/31 22:17:43 Worth discussing the net::CompletionCallback that
Randy Smith (Not in Mondays) 2015/09/02 02:32:28 I detest net::CompletionCallback and consider it a
Ryan Sleevi 2015/09/02 19:14:56 Maybe, but I'm happy to save that discussion for a
13 Many functions also have variables (often named |result|) containing
14 such value; this is especially common in the [DoLoop](#DoLoop) pattern
15 described below.
16
17 ## Sync/Async Return
18
19 Many network stack routines may return synchronously or
20 asynchronously. These functions generally return an int as described
21 above. There are three cases:
22
23 * If the value is positive or zero, that indicates a synchronous
24 successful return, with a zero return value possibly indicating zero
25 bytes/EOF and possibly indicating net::OK, depending on context.
26 * If the value is negative and != net::ERR_IO_PENDING, it is an error
27 code specifying a synchronous failing return.
28 * If the return value is the special value net::ERR_IO_PENDING, it
29 indicates that the routine will complete asynchronously. An IOBuffer
30 provided will be retained by the called entity until completion, to
31 be written into or read from as required. Other buffers must be kept
Ryan Sleevi 2015/08/31 22:17:43 s/buffers/pointers/ (or objects)
Randy Smith (Not in Mondays) 2015/09/02 02:32:29 Done.
32 alive manually until asynchronous completion is signaled.
33 If a callback was provided, that callback will be called upon
34 completion with the return value; if a callback is not provided, it
35 usually means that some known callback mechanism will be employed.
36
37 ## DoLoop
38
39 The pattern usually used to construct state machines in the Chrome
40 network stack is the DoLoop function. Any class that must drive a
41 state machine will contain an enum listing all states of that machine,
42 and define a function, |DoLoop|, to drive that state
43 machine. Sometimes a single class may have multiple state machines,
44 driven by multiple methods (e.g. DoFooLoop and DoBarLoop), and
45 sometimes a larger state machine may be broken into smaller state
46 machines, e.g. |DoHandshakeLoop|.
47
48 The characteristics of the DoLoop pattern are:
49
50 * Each state has a corresponding function which is called by DoLoop
Ryan Sleevi 2015/08/31 22:17:43 STYLE PEDANTRY: Google style is three spaces, not
Randy Smith (Not in Mondays) 2015/09/02 02:32:28 Huh. The markdown documentation that I found said
51 for handling when the state machine is in that state. Generally the
52 states are named STATE_<state name> (upper case separated by
53 underscores), and the routine is named Do<StateName> (CamelCase).
54 Those functions both take and return values that are either
55 net::Errors or the above combined error and byte count value.
56 * There are often pairs of related states, such as STATE_SEND_HEADERS
57 and STATE_SEND_HEADERS_COMPLETE. The routine associated with the
Ryan Sleevi 2015/08/31 22:17:43 pedantry: You introduced another double space :P [
Randy Smith (Not in Mondays) 2015/09/02 02:32:29 I *did* warn you :-}. Done.
58 second state handles completion processing (e.g. success vs. error)
59 and determining the next state to transition to (e.g. back to
60 STATE_SEND_HEADERS if the headers haven't actually all been sent).
Ryan Sleevi 2015/08/31 22:17:43 I would suggest rewording this; we don't do FOO/FO
Randy Smith (Not in Mondays) 2015/09/02 02:32:28 SGTM; this is exactly the kind of thing I'm relyin
61 * Each state handling function has two basic responsibilities in
62 addition to state specific handling: Setting the data member
63 (named |next_state_| or something similar)
64 to specify the next state, and returning a net::Error (or combined
65 error and byte count, as above).
66 * DoLoop loops, saving next_state_ to a local variable and resetting
67 it to STATE_NONE, and then calling the appropriate state handling
68 based the original value of next_state_.
Ryan Sleevi 2015/08/31 22:17:43 Suggestion: Add a sentence explaining why * On
Randy Smith (Not in Mondays) 2015/09/02 02:32:28 Thanks for the explanation; done.
69 * If the return value from the state handling function is
70 net::ERR_IO_PENDING, that indicates that the function has arranged
71 for DoLoop() to be called at some point in the future, when further
72 progress can be made on the state transitions. The next_state_ variable
73 will have been set to the value proper for handling that incoming
74 call. In this case, DoLoop() will exit.
75 * A class state machine is generally invoked in response to a consumer
76 calling one of its methods. While the operation that method
77 requested is occuring, the state machine stays actively, possibly
78 over multiple asynchronous operations and state transitions. When
79 that operation is complete, the state machine transitions to
80 STATE_NONE (by a DoLoop callee not setting next_state_) or
81 STATE_DONE (by explicitly setting next_state_ to STATE_DONE
82 indicating that the operation is complete *and* the state machine is
83 not amenable to further driving). At this point the consumer is
84 notified of the completion of the operation (by synchronous return
85 or asynchronous callback).
86
87 Note that this implies that when DoLoop() returns, one of two
88 things will be true:
89
90 * The return value will be net::ERR_IO_PENDING, indicating that the
91 caller should take no action and instead wait for asynchronous
92 notification.
93 * The state of the machine will be either STATE_DONE or STATE_NONE,
94 indicating that the operation that first initiated the DoLoop() has
95 completed.
96
97 * DoLoop is called from two places: a) methods exposed to the consumer
98 for specific operations (e.g. |ReadHeaders|), and b) IO completion
99 callbacks called asynchronously by spawned IO operations.
100
101 In the first case, the return value from DoLoop is returned directly
102 to the caller; if the operation completed synchronously, that will
103 contain the operation result, and if it completed asynchronously, it
104 will be net::ERR_IO_PENDING.
105
106 In the second case, the IO completion callback will examine the
107 return value from DoLoop(). If it is net::ERR_IO_PENDING, no
108 further action will be taken, and the IO completion callback will be
109 called again at some future point. If it is not
110 net::ERR_IO_PENDING, that is a signal that the operation has
111 completed, and the IO completion callback will call the appropriate
112 consumer callback to notify the consumer that the operation has
113 completed. Note that it is important that this callback be done
114 from the IO completion callback and not DoLoop or a DoLoop callee,
115 both to support the sync/async error return (DoLoop and its callees
116 don't konw the difference) and to avoid consumer callbacks deleting
Ryan Sleevi 2015/08/31 22:17:43 typo: know
Randy Smith (Not in Mondays) 2015/09/02 02:32:28 Done.
117 the object out from under DoLoop().
118
119 Public class methods should have as little processing as possible,
120 often simply making copies of arguments into data members, setting the
121 next_state_ variable to indicate the section of the state diagram to
122 process, and calling DoLoop().
123
124 This idiom allows synchronous and asynchronous logic to be written in
125 the same fashion; it's all just state transition handling. For mostly
126 linear state diagrams, the handling code can be very easy to
127 comprehend, as such code is usually written linearly (in different
128 handling functions) in the order it's executed. If there can be
129 multiple different events that complete outstanding IO, the framework
130 doesn't handle that explicitly; the state handling code for the
131 receiving state must explicitly distinguish between those events and
132 do the appropriate state transition.
133
134 For examples of this idiom, see
135
136 * [HttpStreamParser::DoLoop](https://code.google.com/p/chromium/codesearch#chrom ium/src/net/http/http_stream_parser.cc&q=HttpStreamParser::DoLoop&sq=package:chr omium).
137 * [HttpNetworkTransaction::DoLoop](https://code.google.com/p/chromium/codesearch #chromium/src/net/http/http_network_transaction.cc&q=HttpNetworkTransaction::DoL oop&sq=package:chromium)
138
OLDNEW
« no previous file with comments | « no previous file | net/net.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698