util-src/managed_pointer.h
author Matthew Wild <mwild1@gmail.com>
Sun, 17 Mar 2024 10:10:24 +0000
changeset 13464 a688947fab1e
parent 12696 b001b0f42512
permissions -rw-r--r--
mod_bosh: Set base_type on session This fixes a traceback with mod_saslauth. Ideally we move this to util.session at some point, though.
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