Annotate

util-src/managed_pointer.h @ 12956:52fcdfe710ca

storagemanager: Add keyval+ (combined keyval + map) store type This combines the two most common store types, which modules often end up opening with both interfaces separately anyway. As well as combining them, I've taken the opportunity to improve some of the method names to make them clearer.
author Matthew Wild <mwild1@gmail.com>
date Tue, 27 Sep 2022 17:46:27 +0100
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