xref: /aosp_15_r20/external/curl/docs/internals/BUFQ.md (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker<!--
2*6236dae4SAndroid Build Coastguard WorkerCopyright (C) Daniel Stenberg, <[email protected]>, et al.
3*6236dae4SAndroid Build Coastguard Worker
4*6236dae4SAndroid Build Coastguard WorkerSPDX-License-Identifier: curl
5*6236dae4SAndroid Build Coastguard Worker-->
6*6236dae4SAndroid Build Coastguard Worker
7*6236dae4SAndroid Build Coastguard Worker# bufq
8*6236dae4SAndroid Build Coastguard Worker
9*6236dae4SAndroid Build Coastguard WorkerThis is an internal module for managing I/O buffers. A `bufq` can be written
10*6236dae4SAndroid Build Coastguard Workerto and read from. It manages read and write positions and has a maximum size.
11*6236dae4SAndroid Build Coastguard Worker
12*6236dae4SAndroid Build Coastguard Worker## read/write
13*6236dae4SAndroid Build Coastguard Worker
14*6236dae4SAndroid Build Coastguard WorkerIts basic read/write functions have a similar signature and return code handling
15*6236dae4SAndroid Build Coastguard Workeras many internal Curl read and write ones.
16*6236dae4SAndroid Build Coastguard Worker
17*6236dae4SAndroid Build Coastguard Worker
18*6236dae4SAndroid Build Coastguard Worker```
19*6236dae4SAndroid Build Coastguard Workerssize_t Curl_bufq_write(struct bufq *q, const unsigned char *buf, size_t len, CURLcode *err);
20*6236dae4SAndroid Build Coastguard Worker
21*6236dae4SAndroid Build Coastguard Worker- returns the length written into `q` or -1 on error.
22*6236dae4SAndroid Build Coastguard Worker- writing to a full `q` returns -1 and set *err to CURLE_AGAIN
23*6236dae4SAndroid Build Coastguard Worker
24*6236dae4SAndroid Build Coastguard Workerssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len, CURLcode *err);
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Worker- returns the length read from `q` or -1 on error.
27*6236dae4SAndroid Build Coastguard Worker- reading from an empty `q` returns -1 and set *err to CURLE_AGAIN
28*6236dae4SAndroid Build Coastguard Worker
29*6236dae4SAndroid Build Coastguard Worker```
30*6236dae4SAndroid Build Coastguard Worker
31*6236dae4SAndroid Build Coastguard WorkerTo pass data into a `bufq` without an extra copy, read callbacks can be used.
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard Worker```
34*6236dae4SAndroid Build Coastguard Workertypedef ssize_t Curl_bufq_reader(void *reader_ctx, unsigned char *buf, size_t len,
35*6236dae4SAndroid Build Coastguard Worker                                 CURLcode *err);
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Workerssize_t Curl_bufq_slurp(struct bufq *q, Curl_bufq_reader *reader, void *reader_ctx,
38*6236dae4SAndroid Build Coastguard Worker                        CURLcode *err);
39*6236dae4SAndroid Build Coastguard Worker```
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Worker`Curl_bufq_slurp()` invokes the given `reader` callback, passing it its own
42*6236dae4SAndroid Build Coastguard Workerinternal buffer memory to write to. It may invoke the `reader` several times,
43*6236dae4SAndroid Build Coastguard Workeras long as it has space and while the `reader` always returns the length that
44*6236dae4SAndroid Build Coastguard Workerwas requested. There are variations of `slurp` that call the `reader` at most
45*6236dae4SAndroid Build Coastguard Workeronce or only read in a maximum amount of bytes.
46*6236dae4SAndroid Build Coastguard Worker
47*6236dae4SAndroid Build Coastguard WorkerThe analog mechanism for write out buffer data is:
48*6236dae4SAndroid Build Coastguard Worker
49*6236dae4SAndroid Build Coastguard Worker```
50*6236dae4SAndroid Build Coastguard Workertypedef ssize_t Curl_bufq_writer(void *writer_ctx, const unsigned char *buf, size_t len,
51*6236dae4SAndroid Build Coastguard Worker                                 CURLcode *err);
52*6236dae4SAndroid Build Coastguard Worker
53*6236dae4SAndroid Build Coastguard Workerssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer, void *writer_ctx,
54*6236dae4SAndroid Build Coastguard Worker                       CURLcode *err);
55*6236dae4SAndroid Build Coastguard Worker```
56*6236dae4SAndroid Build Coastguard Worker
57*6236dae4SAndroid Build Coastguard Worker`Curl_bufq_pass()` invokes the `writer`, passing its internal memory and
58*6236dae4SAndroid Build Coastguard Workerremove the amount that `writer` reports.
59*6236dae4SAndroid Build Coastguard Worker
60*6236dae4SAndroid Build Coastguard Worker## peek and skip
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard WorkerIt is possible to get access to the memory of data stored in a `bufq` with:
63*6236dae4SAndroid Build Coastguard Worker
64*6236dae4SAndroid Build Coastguard Worker```
65*6236dae4SAndroid Build Coastguard Workerbool Curl_bufq_peek(const struct bufq *q, const unsigned char **pbuf, size_t *plen);
66*6236dae4SAndroid Build Coastguard Worker```
67*6236dae4SAndroid Build Coastguard Worker
68*6236dae4SAndroid Build Coastguard WorkerOn returning TRUE, `pbuf` points to internal memory with `plen` bytes that one
69*6236dae4SAndroid Build Coastguard Workermay read. This is only valid until another operation on `bufq` is performed.
70*6236dae4SAndroid Build Coastguard Worker
71*6236dae4SAndroid Build Coastguard WorkerInstead of reading `bufq` data, one may simply skip it:
72*6236dae4SAndroid Build Coastguard Worker
73*6236dae4SAndroid Build Coastguard Worker```
74*6236dae4SAndroid Build Coastguard Workervoid Curl_bufq_skip(struct bufq *q, size_t amount);
75*6236dae4SAndroid Build Coastguard Worker```
76*6236dae4SAndroid Build Coastguard Worker
77*6236dae4SAndroid Build Coastguard WorkerThis removes `amount` number of bytes from the `bufq`.
78*6236dae4SAndroid Build Coastguard Worker
79*6236dae4SAndroid Build Coastguard Worker## unwrite
80*6236dae4SAndroid Build Coastguard Worker
81*6236dae4SAndroid Build Coastguard WorkerIt is possible to undo writes by calling:
82*6236dae4SAndroid Build Coastguard Worker
83*6236dae4SAndroid Build Coastguard Worker```
84*6236dae4SAndroid Build Coastguard WorkerCURLcode Curl_bufq_unwrite(struct bufq *q, size_t len);
85*6236dae4SAndroid Build Coastguard Worker```
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard WorkerThis will remove `len` bytes from the end of the bufq again. When removing
88*6236dae4SAndroid Build Coastguard Workermore bytes than are present, CURLE_AGAIN is returned and the bufq will be
89*6236dae4SAndroid Build Coastguard Workerempty.
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker## lifetime
92*6236dae4SAndroid Build Coastguard Worker
93*6236dae4SAndroid Build Coastguard Worker`bufq` is initialized and freed similar to the `dynbuf` module. Code using
94*6236dae4SAndroid Build Coastguard Worker`bufq` holds a `struct bufq` somewhere. Before it uses it, it invokes:
95*6236dae4SAndroid Build Coastguard Worker
96*6236dae4SAndroid Build Coastguard Worker```
97*6236dae4SAndroid Build Coastguard Workervoid Curl_bufq_init(struct bufq *q, size_t chunk_size, size_t max_chunks);
98*6236dae4SAndroid Build Coastguard Worker```
99*6236dae4SAndroid Build Coastguard Worker
100*6236dae4SAndroid Build Coastguard WorkerThe `bufq` is told how many "chunks" of data it shall hold at maximum and how
101*6236dae4SAndroid Build Coastguard Workerlarge those "chunks" should be. There are some variants of this, allowing for
102*6236dae4SAndroid Build Coastguard Workermore options. How "chunks" are handled in a `bufq` is presented in the section
103*6236dae4SAndroid Build Coastguard Workerabout memory management.
104*6236dae4SAndroid Build Coastguard Worker
105*6236dae4SAndroid Build Coastguard WorkerThe user of the `bufq` has the responsibility to call:
106*6236dae4SAndroid Build Coastguard Worker
107*6236dae4SAndroid Build Coastguard Worker```
108*6236dae4SAndroid Build Coastguard Workervoid Curl_bufq_free(struct bufq *q);
109*6236dae4SAndroid Build Coastguard Worker```
110*6236dae4SAndroid Build Coastguard Workerto free all resources held by `q`. It is possible to reset a `bufq` to empty via:
111*6236dae4SAndroid Build Coastguard Worker
112*6236dae4SAndroid Build Coastguard Worker```
113*6236dae4SAndroid Build Coastguard Workervoid Curl_bufq_reset(struct bufq *q);
114*6236dae4SAndroid Build Coastguard Worker```
115*6236dae4SAndroid Build Coastguard Worker
116*6236dae4SAndroid Build Coastguard Worker## memory management
117*6236dae4SAndroid Build Coastguard Worker
118*6236dae4SAndroid Build Coastguard WorkerInternally, a `bufq` uses allocation of fixed size, e.g. the "chunk_size", up
119*6236dae4SAndroid Build Coastguard Workerto a maximum number, e.g. "max_chunks". These chunks are allocated on demand,
120*6236dae4SAndroid Build Coastguard Workertherefore writing to a `bufq` may return `CURLE_OUT_OF_MEMORY`. Once the max
121*6236dae4SAndroid Build Coastguard Workernumber of chunks are used, the `bufq` reports that it is "full".
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard WorkerEach chunks has a `read` and `write` index. A `bufq` keeps its chunks in a
124*6236dae4SAndroid Build Coastguard Workerlist. Reading happens always at the head chunk, writing always goes to the
125*6236dae4SAndroid Build Coastguard Workertail chunk. When the head chunk becomes empty, it is removed. When the tail
126*6236dae4SAndroid Build Coastguard Workerchunk becomes full, another chunk is added to the end of the list, becoming
127*6236dae4SAndroid Build Coastguard Workerthe new tail.
128*6236dae4SAndroid Build Coastguard Worker
129*6236dae4SAndroid Build Coastguard WorkerChunks that are no longer used are returned to a `spare` list by default. If
130*6236dae4SAndroid Build Coastguard Workerthe `bufq` is created with option `BUFQ_OPT_NO_SPARES` those chunks are freed
131*6236dae4SAndroid Build Coastguard Workerright away.
132*6236dae4SAndroid Build Coastguard Worker
133*6236dae4SAndroid Build Coastguard WorkerIf a `bufq` is created with a `bufc_pool`, the no longer used chunks are
134*6236dae4SAndroid Build Coastguard Workerreturned to the pool. Also `bufq` asks the pool for a chunk when it needs one.
135*6236dae4SAndroid Build Coastguard WorkerMore in section "pools".
136*6236dae4SAndroid Build Coastguard Worker
137*6236dae4SAndroid Build Coastguard Worker## empty, full and overflow
138*6236dae4SAndroid Build Coastguard Worker
139*6236dae4SAndroid Build Coastguard WorkerOne can ask about the state of a `bufq` with methods such as
140*6236dae4SAndroid Build Coastguard Worker`Curl_bufq_is_empty(q)`, `Curl_bufq_is_full(q)`, etc. The amount of data held
141*6236dae4SAndroid Build Coastguard Workerby a `bufq` is the sum of the data in all its chunks. This is what is reported
142*6236dae4SAndroid Build Coastguard Workerby `Curl_bufq_len(q)`.
143*6236dae4SAndroid Build Coastguard Worker
144*6236dae4SAndroid Build Coastguard WorkerNote that a `bufq` length and it being "full" are only loosely related. A
145*6236dae4SAndroid Build Coastguard Workersimple example:
146*6236dae4SAndroid Build Coastguard Worker
147*6236dae4SAndroid Build Coastguard Worker* create a `bufq` with chunk_size=1000 and max_chunks=4.
148*6236dae4SAndroid Build Coastguard Worker* write 4000 bytes to it, it reports "full"
149*6236dae4SAndroid Build Coastguard Worker* read 1 bytes from it, it still reports "full"
150*6236dae4SAndroid Build Coastguard Worker* read 999 more bytes from it, and it is no longer "full"
151*6236dae4SAndroid Build Coastguard Worker
152*6236dae4SAndroid Build Coastguard WorkerThe reason for this is that full really means: *bufq uses max_chunks and the
153*6236dae4SAndroid Build Coastguard Workerlast one cannot be written to*.
154*6236dae4SAndroid Build Coastguard Worker
155*6236dae4SAndroid Build Coastguard WorkerWhen you read 1 byte from the head chunk in the example above, the head still
156*6236dae4SAndroid Build Coastguard Workerhold 999 unread bytes. Only when those are also read, can the head chunk be
157*6236dae4SAndroid Build Coastguard Workerremoved and a new tail be added.
158*6236dae4SAndroid Build Coastguard Worker
159*6236dae4SAndroid Build Coastguard WorkerThere is another variation to this. If you initialized a `bufq` with option
160*6236dae4SAndroid Build Coastguard Worker`BUFQ_OPT_SOFT_LIMIT`, it allows writes **beyond** the `max_chunks`. It
161*6236dae4SAndroid Build Coastguard Workerreports **full**, but one can **still** write. This option is necessary, if
162*6236dae4SAndroid Build Coastguard Workerpartial writes need to be avoided. It means that you need other checks to keep
163*6236dae4SAndroid Build Coastguard Workerthe `bufq` from growing ever larger and larger.
164*6236dae4SAndroid Build Coastguard Worker
165*6236dae4SAndroid Build Coastguard Worker
166*6236dae4SAndroid Build Coastguard Worker## pools
167*6236dae4SAndroid Build Coastguard Worker
168*6236dae4SAndroid Build Coastguard WorkerA `struct bufc_pool` may be used to create chunks for a `bufq` and keep spare
169*6236dae4SAndroid Build Coastguard Workerones around. It is initialized and used via:
170*6236dae4SAndroid Build Coastguard Worker
171*6236dae4SAndroid Build Coastguard Worker```
172*6236dae4SAndroid Build Coastguard Workervoid Curl_bufcp_init(struct bufc_pool *pool, size_t chunk_size, size_t spare_max);
173*6236dae4SAndroid Build Coastguard Worker
174*6236dae4SAndroid Build Coastguard Workervoid Curl_bufq_initp(struct bufq *q, struct bufc_pool *pool, size_t max_chunks, int opts);
175*6236dae4SAndroid Build Coastguard Worker```
176*6236dae4SAndroid Build Coastguard Worker
177*6236dae4SAndroid Build Coastguard WorkerThe pool gets the size and the mount of spares to keep. The `bufq` gets the
178*6236dae4SAndroid Build Coastguard Workerpool and the `max_chunks`. It no longer needs to know the chunk sizes, as
179*6236dae4SAndroid Build Coastguard Workerthose are managed by the pool.
180*6236dae4SAndroid Build Coastguard Worker
181*6236dae4SAndroid Build Coastguard WorkerA pool can be shared between many `bufq`s, as long as all of them operate in
182*6236dae4SAndroid Build Coastguard Workerthe same thread. In curl that would be true for all transfers using the same
183*6236dae4SAndroid Build Coastguard Workermulti handle. The advantages of a pool are:
184*6236dae4SAndroid Build Coastguard Worker
185*6236dae4SAndroid Build Coastguard Worker* when all `bufq`s are empty, only memory for `max_spare` chunks in the pool
186*6236dae4SAndroid Build Coastguard Worker  is used. Empty `bufq`s holds no memory.
187*6236dae4SAndroid Build Coastguard Worker* the latest spare chunk is the first to be handed out again, no matter which
188*6236dae4SAndroid Build Coastguard Worker  `bufq` needs it. This keeps the footprint of "recently used" memory smaller.
189