1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #ifndef UPB_MEM_ALLOC_H_
9 #define UPB_MEM_ALLOC_H_
10
11 // Must be last.
12 #include "upb/port/def.inc"
13
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17
18 typedef struct upb_alloc upb_alloc;
19
20 /* A combined `malloc()`/`free()` function.
21 * If `size` is 0 then the function acts like `free()`, otherwise it acts like
22 * `realloc()`. Only `oldsize` bytes from a previous allocation are
23 * preserved. */
24 typedef void* upb_alloc_func(upb_alloc* alloc, void* ptr, size_t oldsize,
25 size_t size);
26
27 /* A upb_alloc is a possibly-stateful allocator object.
28 *
29 * It could either be an arena allocator (which doesn't require individual
30 * `free()` calls) or a regular `malloc()` (which does). The client must
31 * therefore free memory unless it knows that the allocator is an arena
32 * allocator. */
33 struct upb_alloc {
34 upb_alloc_func* func;
35 };
36
upb_malloc(upb_alloc * alloc,size_t size)37 UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) {
38 UPB_ASSERT(alloc);
39 return alloc->func(alloc, NULL, 0, size);
40 }
41
upb_realloc(upb_alloc * alloc,void * ptr,size_t oldsize,size_t size)42 UPB_INLINE void* upb_realloc(upb_alloc* alloc, void* ptr, size_t oldsize,
43 size_t size) {
44 UPB_ASSERT(alloc);
45 return alloc->func(alloc, ptr, oldsize, size);
46 }
47
upb_free(upb_alloc * alloc,void * ptr)48 UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) {
49 UPB_ASSERT(alloc);
50 alloc->func(alloc, ptr, 0, 0);
51 }
52
53 // The global allocator used by upb. Uses the standard malloc()/free().
54
55 extern upb_alloc upb_alloc_global;
56
57 /* Functions that hard-code the global malloc.
58 *
59 * We still get benefit because we can put custom logic into our global
60 * allocator, like injecting out-of-memory faults in debug/testing builds. */
61
upb_gmalloc(size_t size)62 UPB_INLINE void* upb_gmalloc(size_t size) {
63 return upb_malloc(&upb_alloc_global, size);
64 }
65
upb_grealloc(void * ptr,size_t oldsize,size_t size)66 UPB_INLINE void* upb_grealloc(void* ptr, size_t oldsize, size_t size) {
67 return upb_realloc(&upb_alloc_global, ptr, oldsize, size);
68 }
69
upb_gfree(void * ptr)70 UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); }
71
72 #ifdef __cplusplus
73 } /* extern "C" */
74 #endif
75
76 #include "upb/port/undef.inc"
77
78 #endif /* UPB_MEM_ALLOC_H_ */
79