Annotate

util-src/managed_pointer.h @ 13248:db433ed3135c

Merge 0.12->trunk
author Kim Alvefur <zash@zash.se>
date Tue, 25 Jul 2023 12:35:11 +0200
parent 12692:b001b0f42512
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12692
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 /* managed_pointer.h
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 These macros allow wrapping an allocator/deallocator into an object that is
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4 owned and managed by the Lua garbage collector.
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
5
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
6 Why? It is too easy to leak objects that need to be manually released, especially
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
7 when dealing with the Lua API which can throw errors from many operations.
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 USAGE
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10 -----
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 For example, given an object that can be created or released with the following
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 functions:
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 fancy_buffer* new_buffer();
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 void free_buffer(fancy_buffer* p_buffer)
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 You could declare a managed version like so:
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20 MANAGED_POINTER_ALLOCATOR(new_managed_buffer, fancy_buffer*, new_buffer, free_buffer)
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 And then, when you need to create a new fancy_buffer in your code:
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
24 fancy_buffer *my_buffer = new_managed_buffer(L);
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26 NOTES
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 -----
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 Managed objects MUST NOT be freed manually. They will automatically be
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 freed during the next GC sweep after your function exits (even if via an error).
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 The managed object is pushed onto the stack, but should generally be ignored,
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33 but you'll need to bear this in mind when creating managed pointers in the
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
34 middle of a sequence of stack operations.
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
35 */
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 #define MANAGED_POINTER_MT(wrapped_type) #wrapped_type "_managedptr_mt"
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 #define MANAGED_POINTER_ALLOCATOR(name, wrapped_type, wrapped_alloc, wrapped_free) \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 static int _release_ ## name(lua_State *L) { \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 wrapped_type *p = (wrapped_type*)lua_topointer(L, 1); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 if(*p != NULL) { \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 wrapped_free(*p); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 } \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 return 0; \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 } \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 static wrapped_type name(lua_State *L) { \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 wrapped_type *p = (wrapped_type*)lua_newuserdata(L, sizeof(wrapped_type)); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 if(luaL_newmetatable(L, MANAGED_POINTER_MT(wrapped_type)) != 0) { \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 lua_pushcfunction(L, _release_ ## name); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 lua_setfield(L, -2, "__gc"); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 } \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53 lua_setmetatable(L, -2); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 *p = wrapped_alloc(); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 if(*p == NULL) { \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 lua_pushliteral(L, "not enough memory"); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 lua_error(L); \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 } \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 return *p; \
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 }
b001b0f42512 util-src: Add new utility header managed_pointer.h
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61