xref: /aosp_15_r20/external/libwebsockets/lib/misc/lwsac/README.md (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker## LWS Allocated Chunks
2*1c60b9acSAndroid Build Coastguard Worker
3*1c60b9acSAndroid Build Coastguard Worker![lwsac flow](/doc-assets/lwsac.svg)
4*1c60b9acSAndroid Build Coastguard Worker
5*1c60b9acSAndroid Build Coastguard WorkerThese apis provide a way to manage a linked-list of allocated chunks...
6*1c60b9acSAndroid Build Coastguard Worker
7*1c60b9acSAndroid Build Coastguard Worker[ HEAD alloc ] -> [ next alloc ] -> [ next alloc ] -> [ curr alloc ]
8*1c60b9acSAndroid Build Coastguard Worker
9*1c60b9acSAndroid Build Coastguard Worker... and sub-allocate trivially inside the chunks.  These sub-allocations are
10*1c60b9acSAndroid Build Coastguard Workernot tracked by lwsac at all, there is a "used" high-water mark for each chunk
11*1c60b9acSAndroid Build Coastguard Workerthat's simply advanced by the amount sub-allocated.  If the allocation size
12*1c60b9acSAndroid Build Coastguard Workermatches the platform pointer alignment, there is zero overhead to sub-allocate
13*1c60b9acSAndroid Build Coastguard Worker(otherwise the allocation is padded to the next platform pointer alignment
14*1c60b9acSAndroid Build Coastguard Workerautomatically).
15*1c60b9acSAndroid Build Coastguard Worker
16*1c60b9acSAndroid Build Coastguard WorkerIf you have an unknown amount of relatively little things to allocate, including
17*1c60b9acSAndroid Build Coastguard Workerstrings or other unstructured data, lwsac is significantly more efficient than
18*1c60b9acSAndroid Build Coastguard Workerindividual allocations using malloc or so.
19*1c60b9acSAndroid Build Coastguard Worker
20*1c60b9acSAndroid Build Coastguard Worker[lwsac full public api](https://libwebsockets.org/git/libwebsockets/tree/include/libwebsockets/lws-lwsac.h)
21*1c60b9acSAndroid Build Coastguard Worker
22*1c60b9acSAndroid Build Coastguard Worker## lwsac_use() api
23*1c60b9acSAndroid Build Coastguard Worker
24*1c60b9acSAndroid Build Coastguard Worker```
25*1c60b9acSAndroid Build Coastguard Worker/**
26*1c60b9acSAndroid Build Coastguard Worker * lwsac_use - allocate / use some memory from a lwsac
27*1c60b9acSAndroid Build Coastguard Worker *
28*1c60b9acSAndroid Build Coastguard Worker * \param head: pointer to the lwsac list object
29*1c60b9acSAndroid Build Coastguard Worker * \param ensure: the number of bytes we want to use
30*1c60b9acSAndroid Build Coastguard Worker * \param chunk_size: 0, or the size of the chunk to (over)allocate if
31*1c60b9acSAndroid Build Coastguard Worker *			what we want won't fit in the current tail chunk.  If
32*1c60b9acSAndroid Build Coastguard Worker *			0, the default value of 4000 is used. If ensure is
33*1c60b9acSAndroid Build Coastguard Worker *			larger, it is used instead.
34*1c60b9acSAndroid Build Coastguard Worker *
35*1c60b9acSAndroid Build Coastguard Worker * This also serves to init the lwsac if *head is NULL.  Basically it does
36*1c60b9acSAndroid Build Coastguard Worker * whatever is necessary to return you a pointer to ensure bytes of memory
37*1c60b9acSAndroid Build Coastguard Worker * reserved for the caller.
38*1c60b9acSAndroid Build Coastguard Worker *
39*1c60b9acSAndroid Build Coastguard Worker * Returns NULL if OOM.
40*1c60b9acSAndroid Build Coastguard Worker */
41*1c60b9acSAndroid Build Coastguard WorkerLWS_VISIBLE LWS_EXTERN void *
42*1c60b9acSAndroid Build Coastguard Workerlwsac_use(struct lwsac **head, size_t ensure, size_t chunk_size);
43*1c60b9acSAndroid Build Coastguard Worker```
44*1c60b9acSAndroid Build Coastguard Worker
45*1c60b9acSAndroid Build Coastguard WorkerWhen you make an sub-allocation using `lwsac_use()`, you can either
46*1c60b9acSAndroid Build Coastguard Workerset the `chunk_size` arg to zero, defaulting to 4000, or a specific chunk size.
47*1c60b9acSAndroid Build Coastguard WorkerIn the event the requested sub-allocation exceeds the chunk size, the chunk
48*1c60b9acSAndroid Build Coastguard Workersize is increated to match it automatically for this allocation only.
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard WorkerSubsequent `lwsac_use()` calls will advance internal pointers to use up the
51*1c60b9acSAndroid Build Coastguard Workerremaining space inside the current chunk if possible; if not enough remaining
52*1c60b9acSAndroid Build Coastguard Workerspace it is skipped, a new allocation is chained on and the request pointed to
53*1c60b9acSAndroid Build Coastguard Workerthere.
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard WorkerLwsac does not store information about sub-allocations.  There is really zero
56*1c60b9acSAndroid Build Coastguard Workeroverhead for individual sub-allocations (unless their size is not
57*1c60b9acSAndroid Build Coastguard Workerpointer-aligned, in which case the actual amount sub-allocated is rounded up to
58*1c60b9acSAndroid Build Coastguard Workerthe next pointer alignment automatically).  For structs, which are pointer-
59*1c60b9acSAndroid Build Coastguard Workeraligned naturally, and a chunk size relatively large for the sub-allocation
60*1c60b9acSAndroid Build Coastguard Workersize, lwsac is extremely efficient even for huge numbers of small allocations.
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard WorkerThis makes lwsac very effective when the total amount of allocation needed is
63*1c60b9acSAndroid Build Coastguard Workernot known at the start and may be large... it will simply add on chunks to cope
64*1c60b9acSAndroid Build Coastguard Workerwith whatever happens.
65*1c60b9acSAndroid Build Coastguard Worker
66*1c60b9acSAndroid Build Coastguard Worker## lwsac_free() api
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker```
69*1c60b9acSAndroid Build Coastguard Worker/**
70*1c60b9acSAndroid Build Coastguard Worker * lwsac_free - deallocate all chunks in the lwsac and set head NULL
71*1c60b9acSAndroid Build Coastguard Worker *
72*1c60b9acSAndroid Build Coastguard Worker * \param head: pointer to the lwsac list object
73*1c60b9acSAndroid Build Coastguard Worker *
74*1c60b9acSAndroid Build Coastguard Worker * This deallocates all chunks in the lwsac, then sets *head to NULL.  All
75*1c60b9acSAndroid Build Coastguard Worker * lwsac_use() pointers are invalidated in one hit without individual frees.
76*1c60b9acSAndroid Build Coastguard Worker */
77*1c60b9acSAndroid Build Coastguard WorkerLWS_VISIBLE LWS_EXTERN void
78*1c60b9acSAndroid Build Coastguard Workerlwsac_free(struct lwsac **head);
79*1c60b9acSAndroid Build Coastguard Worker```
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard WorkerWhen you are finished with the lwsac, you simply free the chain of allocated
82*1c60b9acSAndroid Build Coastguard Workerchunks using lwsac_free() on the lwsac head.  There's no tracking or individual
83*1c60b9acSAndroid Build Coastguard Workerdestruction of suballocations - the whole chain of chunks the suballocations
84*1c60b9acSAndroid Build Coastguard Workerlive in are freed and invalidated all together.
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard WorkerIf the structs stored in the lwsac allocated things **outside** the lwsac, then the
87*1c60b9acSAndroid Build Coastguard Workeruser must unwind through them and perform the frees.  But the idea of lwsac is
88*1c60b9acSAndroid Build Coastguard Workerthings stored in the lwsac also suballocate into the lwsac, and point into the
89*1c60b9acSAndroid Build Coastguard Workerlwsac if they need to, avoiding any need to visit them during destroy.  It's
90*1c60b9acSAndroid Build Coastguard Workerlike clearing up after a kids' party by gathering up a disposable tablecloth:
91*1c60b9acSAndroid Build Coastguard Workerno matter what was left on the table, it's all gone in one step.
92*1c60b9acSAndroid Build Coastguard Worker
93*1c60b9acSAndroid Build Coastguard Worker## `lws_list_ptr` helpers
94*1c60b9acSAndroid Build Coastguard Worker
95*1c60b9acSAndroid Build Coastguard Worker```
96*1c60b9acSAndroid Build Coastguard Worker/* sort may be NULL if you don't care about order */
97*1c60b9acSAndroid Build Coastguard WorkerLWS_VISIBLE LWS_EXTERN void
98*1c60b9acSAndroid Build Coastguard Workerlws_list_ptr_insert(lws_list_ptr *phead, lws_list_ptr *add,
99*1c60b9acSAndroid Build Coastguard Worker		    lws_list_ptr_sort_func_t sort);
100*1c60b9acSAndroid Build Coastguard Worker```
101*1c60b9acSAndroid Build Coastguard Worker
102*1c60b9acSAndroid Build Coastguard WorkerA common pattern needed with sub-allocated structs is they are on one or more
103*1c60b9acSAndroid Build Coastguard Workerlinked-list.  To make that simple to do cleanly, `lws_list...` apis are provided
104*1c60b9acSAndroid Build Coastguard Workeralong with a generic insertion function that can take a sort callback.  These
105*1c60b9acSAndroid Build Coastguard Workerallow a struct to participate on multiple linked-lists simultaneously.
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker## common const string and blob folding
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard WorkerIn some cases the input to be stored in the lwsac may repeat the same tokens
110*1c60b9acSAndroid Build Coastguard Workermultiple times... if the pattern is to store the string or blob in the lwsac
111*1c60b9acSAndroid Build Coastguard Workerand then point to it, you can make use of a helper api
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker```
114*1c60b9acSAndroid Build Coastguard Workeruint8_t *
115*1c60b9acSAndroid Build Coastguard Workerlwsac_scan_extant(struct lwsac *head, uint8_t *find, size_t len, int nul);
116*1c60b9acSAndroid Build Coastguard Worker```
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard WorkerThis lets you check in all previous used parts of the lwsac for the same
119*1c60b9acSAndroid Build Coastguard Workerstring or blob, plus optionally a terminal NUL afterwards.  If not found,
120*1c60b9acSAndroid Build Coastguard Workerit returns `NULL` and you can copy it into the lwsac as usual.  If it is
121*1c60b9acSAndroid Build Coastguard Workerfound, a pointer is returned, and you can use this directly without copying
122*1c60b9acSAndroid Build Coastguard Workerthe string or blob in again.
123*1c60b9acSAndroid Build Coastguard Worker
124*1c60b9acSAndroid Build Coastguard Worker## optimizations to minimize overhead
125*1c60b9acSAndroid Build Coastguard Worker
126*1c60b9acSAndroid Build Coastguard WorkerIf the lwsac will persist in the system for some time, it's desirable to reduce
127*1c60b9acSAndroid Build Coastguard Workerthe memory needed as overhead.  Overhead is created
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker - once per chunk... in addition to the malloc overhead, there's an lwsac
130*1c60b9acSAndroid Build Coastguard Worker   chunk header of 2 x pointers and 2 x size_t
131*1c60b9acSAndroid Build Coastguard Worker
132*1c60b9acSAndroid Build Coastguard Worker - at the unused part at the end that was allocated but not used
133*1c60b9acSAndroid Build Coastguard Worker
134*1c60b9acSAndroid Build Coastguard WorkerA good strategy is to make the initial allocation reflect the minimum expected
135*1c60b9acSAndroid Build Coastguard Workersize of the overall lwsac in one hit.  Then use a chunk size that is a tradeoff
136*1c60b9acSAndroid Build Coastguard Workerbetween the number of chunks that might be needed and the fact that on average,
137*1c60b9acSAndroid Build Coastguard Workeryou can expect to waste half a chunk.  For example if the storage is typically
138*1c60b9acSAndroid Build Coastguard Workerbetween 4K - 6K, you could allocate 4K or 4.5K for the first chunk and then fill
139*1c60b9acSAndroid Build Coastguard Workerin using 256 or 512 byte chunks.
140*1c60b9acSAndroid Build Coastguard Worker
141*1c60b9acSAndroid Build Coastguard WorkerYou can measure the overhead in an lwsac using `lwsac_total_overhead()`.
142*1c60b9acSAndroid Build Coastguard Worker
143*1c60b9acSAndroid Build Coastguard WorkerThe lwsac apis look first in the unused part of previous chunks, if any, and
144*1c60b9acSAndroid Build Coastguard Workerwill place new allocations there preferentially if they fit.  This helps for the
145*1c60b9acSAndroid Build Coastguard Workercase lwsac was forced to allocate a new chunk because you asked for something
146*1c60b9acSAndroid Build Coastguard Workerlarge, while there was actually significant free space left in the old chunk,
147*1c60b9acSAndroid Build Coastguard Workerjust not enough for that particular allocation.  Subsequent lwsac use can then
148*1c60b9acSAndroid Build Coastguard Worker"backfill" smaller things there to make best use of allocated space.
149