util-src/managed_pointer.h
author Kim Alvefur <zash@zash.se>
Sat, 23 Mar 2024 20:48:19 +0100
changeset 13465 c673ff1075bd
parent 12696 b001b0f42512
permissions -rw-r--r--
mod_posix: Move everything to util.startup This allows greater control over the order of events. Notably, the internal ordering between daemonization, initialization of libunbound and setup of signal handling is sensitive. libunbound starts a separate thread for processing DNS requests. If this thread is started before signal handling has been set up, it will not inherit the signal handlers and instead behave as it would have before signal handlers were set up, i.e. cause the whole process to immediately exit. libunbound is usually initialized on the first DNS request, usually triggered by an outgoing s2s connection attempt. If daemonization happens before signals have been set up, signals may not be processed at all.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12696
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