#include #include #include "config.h" /** * talloc_link - link helper for talloc * * Talloc references can be confusing and buggy. In the cases where an object * needs multiple parents, all parents need to be aware of the situation; thus * talloc_link is a helper where all "parents" talloc_link an object they * agree to share ownership of. * * Example: * // Silly program which keeps a cache of uppercased strings. * // The cache wants to keep strings around even after they may have * // been "freed" by the caller. * #include * #include * #include * #include * #include * #include * * struct upcache { * const char *str; * const char *upstr; * }; * * static struct upcache *cache; * static unsigned int cache_hits = 0; * #define CACHE_SIZE 4 * void init_upcase(void) * { * cache = talloc_zero_array(NULL, struct upcache, CACHE_SIZE); * } * * static struct upcache *lookup_upcase(const char *str) * { * unsigned int i; * for (i = 0; i < CACHE_SIZE; i++) * if (cache[i].str && !strcmp(cache[i].str, str)) { * cache_hits++; * return &cache[i]; * } * return NULL; * } * * static struct upcache *new_upcase(const char *str) * { * unsigned int i; * char *upstr; * * upstr = talloc_linked(cache, talloc_strdup(NULL, str)); * if (!upstr) * return NULL; * * i = random() % CACHE_SIZE; * * // Throw out old: works fine if cache[i].upstr is NULL. * talloc_delink(cache, cache[i].upstr); * * // Replace with new. * cache[i].str = str; * cache[i].upstr = upstr; * while (*upstr) { * *upstr = toupper(*upstr); * upstr++; * } * return &cache[i]; * } * * // If you want to keep the result, talloc_link it. * const char *get_upcase(const char *str) * { * struct upcache *uc = lookup_upcase(str); * if (!uc) * uc = new_upcase(str); * if (!uc) * return NULL; * return uc->upstr; * } * * void exit_upcase(void) * { * talloc_free(cache); * printf("Cache hits: %u\n", cache_hits); * } * * int main(int argc, char *argv[]) * { * unsigned int i; * const char **values; * * // Will dump any memory leaks to stderr on exit. * talloc_enable_leak_report(); * * // Initialize cache. * init_upcase(); * * // Throw values in. * values = talloc_array(NULL, const char *, argc); * for (i = 1; i < argc; i++) { * values[i-1] = talloc_link(values, get_upcase(argv[i])); * if (!values[i-1]) * err(1, "Out of memory"); * } * // This will free all the values, but cache will still work. * talloc_free(values); * * // Repeat! * values = talloc_array(NULL, const char *, argc); * for (i = 1; i < argc; i++) { * values[i-1] = talloc_link(values, get_upcase(argv[i])); * if (!values[i-1]) * err(1, "Out of memory"); * } * * // This will remove cache links, but we still have a link. * exit_upcase(); * * // Show values, so we output something. * for (i = 0; i < argc - 1; i++) * printf("%s ", values[i]); * printf("\n"); * * // This will finally free the upcase strings (last link). * talloc_free(values); * * return 0; * } * * Licence: GPL (2 or any later version) */ int main(int argc, char *argv[]) { if (argc != 2) return 1; if (strcmp(argv[1], "depends") == 0) { printf("ccan/talloc\n"); printf("ccan/list\n"); return 0; } return 1; }