]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Comm.dox
Merged from trunk rev.13445
[thirdparty/squid.git] / src / Comm.dox
1 /**
2 \defgroup Comm Comm Module
3 \ingroup Components
4
5
6 \section Basic Basic Comm API principles
7
8 \par
9 Comm API supports four major kinds of socket-related operations:
10 accept, connect, read, and write. Sockets are identified by their
11 descriptors.
12
13 \par
14 A Comm user requests its interest in operations by calling an
15 appropriate API function (e.g., comm_read()) and optionally providing
16 a notification "callback" (a.k.a., handler). For a given descriptor,
17 there can be no more than one registered user per operation.
18
19 \par
20 In addition to the four operations listed above, a user can register
21 to be notified when a given descriptor is closed.
22
23 \par
24 When a Comm operation completes, all users that registered the
25 corresponding handler are notified. When a descriptor is closed, all
26 users that registered any callback for the descriptor are notified
27 (this will change though, see "Anticipated changes" below).
28
29 \par
30 All Comm notifications are asynchronous, performed using the
31 AsyncCall API.
32
33 \par
34 Notifications for four operations listed above are scheduled in the
35 order of the corresponding operations completion. User code can assume
36 that the operation has completed (possibly with an error) only after
37 receiving a notification. Until then, I/O resources such as buffers
38 must remain available for the operation.
39
40 \par
41 Notifications related to closing of a descriptor are documented
42 separately.
43
44
45 \section IO-cancel I/O cancellation
46
47 \par
48 To cancel an interest in a read operation, call comm_read_cancel()
49 with an AsyncCall object. This call guarantees that the passed Call
50 will be canceled (see the AsyncCall API for call cancellation
51 definitions and details). Naturally, the code has to store the
52 original read callback Call pointer to use this interface.
53
54 \par
55 The comm_read_cancel() call does not guarantee that the read operation
56 has not already happen.
57
58 \par
59 The comm_read_cancel() call guarantees that the read operation will not
60 start for read operations that are performed by Comm (i.e., where read
61 start is controlled by Comm). There is no such guarantee for
62 asynchronous read operations scheduled by Comm but started by the
63 operating system or other threads.
64
65 \par
66 The above applies to comm_read_cancel() interface with an AsyncCall
67 object as a parameter. You cannot reliably cancel an interest in read
68 operation using the old comm_read_cancel() call that uses a function
69 pointer. The handler may get even called after old comm_read_cancel()
70 was called.
71
72 \par
73 It is OK to call comm_read_cancel (both flavors) at any time as long
74 as the descriptor has not been closed and there is either no read
75 interest registered or the passed parameters match the registered
76 ones. If the descriptor has been closed, the behavior is undefined.
77 Otherwise, if parameters do not match, you get an assertion.
78
79 \par
80 To cancel Comm operations other than read, close the descriptor with
81 comm_close().
82
83
84 \section comm-close Descriptor closing with comm_close
85
86 \par
87 The comm_close() function does not close the descriptor but initiates
88 the following closing sequence:
89
90 \par
91 -# The descriptor is placed in a "closing" state.
92 -# The registered read, write, and accept callbacks (if any) are
93 scheduled (in an unspecified order).
94 -# The close callbacks are scheduled (in an unspecified order).
95 -# A call to the internal descriptor closing handler is
96 scheduled.
97
98 \par
99 The "unspecified" order above means that the user should not rely on
100 any specific or deterministic order because the currently hard-coded
101 order may change.
102
103 \par
104 The read, write, and accept notifications (scheduled in step #2
105 above) carry the Comm::ERR_CLOSING error flag. When handling
106 Comm::ERR_CLOSING event, the user code should limit
107 descriptor-related processing, especially Comm calls, because
108 supported Comm functionality is very limited when the descriptor is
109 closing. New code should use the close handlers instead (scheduled
110 in step #3).
111
112 \par
113 The internal closing handler (scheduled in step #4 above) closes the
114 descriptor. When the descriptor is closed, all operations on the
115 descriptor are prohibited and may cause bugs and asserts. Currently,
116 the same descriptor will eventually be reused for another socket and
117 Comm may not notice that a buggy code is still using a stale
118 descriptor, but that may change.
119
120 \par
121 Since all notifications are asynchronous, it is possible for a read
122 or write notification that was scheduled before comm_close() was
123 called to arrive at its destination after comm_close() was called.
124 Such notification will arrive with Comm::ERR_CLOSING flag even though
125 that flag was not set at the time of the I/O (and the I/O may have
126 been successful). This behavior may change.
127
128
129 \section Future Anticipated changes and preparation recommendations
130
131 \par
132 This section lists anticipated Comm API changes and provides
133 recommendations for developers writing new (or rewriting old) Comm
134 user code. The changes are listed in a rough order from more likely
135 to less certain and from near-feature to long-term.
136
137 \par
138 The old comm_read_cancel() function that uses a function pointer will be
139 removed as unreliable. Use the AsyncCall-based comm_read_cancel()
140 instead.
141
142 \par
143 Comm::ERR_CLOSING interface will be removed. The read, write, and
144 accept notifications will not be scheduled after comm_close() is
145 called. New user code should register close handlers instead.
146
147 \par
148 When Comm::ERR_CLOSING interface is removed, pending notifications
149 (if any) will be canceled after comm_close() is called. However, the
150 cancellation may be removed later if Comm is modified to provide safe
151 access to closing descriptors and their fragile state. New user code
152 should continue to assume that it is safe to access Comm in a read,
153 write, and accept handlers.
154
155 \par
156 The old comm_read_cancel() call that uses a function pointer will be
157 removed as unreliable. New user code should use comm_read_cancel() with
158 an AsyncCall parameter.
159
160 \par
161 Comm users may be required to become children of Comm-provided
162 classes, to eliminate the need for a complicated (albeit hidden)
163 hierarchy of Comm callback dialers (see CommCalls.h) and to provide
164 default implementation for common I/O handling cases. New user code
165 should use methods of AsyncJob-derived classes to handle Comm
166 notifications instead of using stand-alone functions. Additionally, it
167 should not call comm_close() for descriptors it does not "own".
168
169 \par
170 The comm_close() API will be used exclusively for "stop future I/O,
171 schedule a close callback call, and cancel all other callbacks"
172 purposes. New user code should not use comm_close() for the purpose of
173 immediately ending a job.
174
175 \par
176 Raw socket descriptors will be replaced with unique IDs or small
177 objects that help detect stale descriptor/socket usage bugs and
178 encapsulate access to socket-specific information. New user code
179 should treat descriptor integers as opaque objects.
180
181
182 */