diff options
| author | William Casarin <jb55@jb55.com> | 2018-07-09 12:10:32 -0700 |
|---|---|---|
| committer | William Casarin <jb55@jb55.com> | 2018-07-09 12:10:32 -0700 |
| commit | 1b8fbbd843ddeb5fc81c9303db9c590a436d499b (patch) | |
| tree | a7227dfe8e4fbaee7b1e0b58b24994dce8078f3f /ccan/take/take.h | |
| parent | 37a9cdd2e80386f2c94e14e4f511284ae14c745a (diff) | |
progress
Diffstat (limited to 'ccan/take/take.h')
| -rw-r--r-- | ccan/take/take.h | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/ccan/take/take.h b/ccan/take/take.h new file mode 100644 index 0000000..8950c6b --- /dev/null +++ b/ccan/take/take.h @@ -0,0 +1,136 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_TAKE_H +#define CCAN_TAKE_H +#include "config.h" +#include <stdbool.h> +#include <ccan/str/str.h> + +#ifdef CCAN_TAKE_DEBUG +#define TAKE_LABEL(p) __FILE__ ":" stringify(__LINE__) ":" stringify(p) +#else +#define TAKE_LABEL(p) NULL +#endif + +/** + * TAKES - annotate a formal parameter as being take()-able + * + * This doesn't do anything, but useful for documentation. + * + * Example: + * void print_string(const char *str TAKES); + * + */ +#define TAKES + +/** + * take - record a pointer to be consumed by the function its handed to. + * @p: the pointer to mark, or NULL. + * + * This marks a pointer object to be freed by the called function, + * which is extremely useful for chaining functions. It works on + * NULL, for pass-through error handling. + */ +#define take(p) (take_typeof(p) take_((p), TAKE_LABEL(p))) + +/** + * taken - check (and un-take) a pointer was passed with take() + * @p: the pointer to check. + * + * A function which accepts take() arguments uses this to see if it + * should own the pointer; it will be removed from the take list, so + * this only returns true once. + * + * Example: + * // Silly routine to add 1 + * static int *add_one(const int *num TAKES) + * { + * int *ret; + * if (taken(num)) + * ret = (int *)num; + * else + * ret = malloc(sizeof(int)); + * if (ret) + * *ret = (*num) + 1; + * return ret; + * } + */ +bool taken(const void *p); + +/** + * is_taken - check if a pointer was passed with take() + * @p: the pointer to check. + * + * This is like the above, but doesn't remove it from the taken list. + * + * Example: + * // Silly routine to add 1: doesn't handle taken args! + * static int *add_one_notake(const int *num) + * { + * int *ret = malloc(sizeof(int)); + * assert(!is_taken(num)); + * if (ret) + * *ret = (*num) + 1; + * return ret; + * } + */ +bool is_taken(const void *p); + +/** + * taken_any - are there any taken pointers? + * + * Mainly useful for debugging take() leaks. With CCAN_TAKE_DEBUG, returns + * the label where the pointer was passed to take(), otherwise returns + * a static char buffer with the pointer value in it. NULL if none are taken. + * + * Example: + * static void cleanup(void) + * { + * assert(!taken_any()); + * } + */ +const char *taken_any(void); + +/** + * take_cleanup - remove all taken pointers from list. + * + * This is useful in atexit() handlers for valgrind-style leak detection. + * + * Example: + * static void cleanup2(void) + * { + * take_cleanup(); + * } + */ +void take_cleanup(void); + +/** + * take_allocfail - set function to call if we can't reallocated taken array. + * @fn: the function. + * + * If this is not set, then if the array reallocation fails, the + * pointer won't be marked taken(). If @fn returns, it is expected to + * free the pointer; we return NULL from take() and the function handles + * it like any allocation failure. + * + * Example: + * static void free_on_fail(const void *p) + * { + * free((void *)p); + * } + * + * static void init(void) + * { + * take_allocfail(free_on_fail); + * } + */ +void take_allocfail(void (*fn)(const void *p)); + +/* Private functions */ +#if HAVE_TYPEOF +#define take_typeof(ptr) (__typeof__(ptr)) +#else +#define take_typeof(ptr) +#endif + +void *take_(const void *p, const char *label); +#endif /* CCAN_TAKE_H */ |
