X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftake%2Ftake.c;fp=ccan%2Ftake%2Ftake.c;h=73e5c29d206fcf5a5cf23e7b6f8d4836a3d06fc4;hp=0000000000000000000000000000000000000000;hb=c8a55bb39404772d459f0153f07db7ecc91ecfd0;hpb=84b29c907c7608a024f65c4ef6803a1f5bb80ccd diff --git a/ccan/take/take.c b/ccan/take/take.c new file mode 100644 index 00000000..73e5c29d --- /dev/null +++ b/ccan/take/take.c @@ -0,0 +1,86 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#include +#include +#include +#include + +static const void **takenarr; +static size_t max_taken, num_taken; +static size_t allocfail; +static void (*allocfailfn)(const void *p); + +void *take_(const void *p) +{ + if (unlikely(num_taken == max_taken)) { + const void **new; + + new = realloc(takenarr, sizeof(*takenarr) * (max_taken+1)); + if (unlikely(!new)) { + if (allocfailfn) { + allocfail++; + allocfailfn(p); + return NULL; + } + /* Otherwise we leak p. */ + return (void *)p; + } + takenarr = new; + max_taken++; + } + takenarr[num_taken++] = p; + return (void *)p; +} + +static size_t find_taken(const void *p) +{ + size_t i; + + for (i = 0; i < num_taken; i++) { + if (takenarr[i] == p) + return i+1; + } + return 0; +} + +bool taken(const void *p) +{ + size_t i; + + if (!p && unlikely(allocfail)) { + allocfail--; + return true; + } + + i = find_taken(p); + if (!i) + return false; + + memmove(&takenarr[i-1], &takenarr[i], + (--num_taken - (i - 1))*sizeof(takenarr[0])); + return true; +} + +bool is_taken(const void *p) +{ + if (!p && unlikely(allocfail)) + return true; + + return find_taken(p) > 0; +} + +bool taken_any(void) +{ + return num_taken != 0; +} + +void take_cleanup(void) +{ + max_taken = num_taken = 0; + free(takenarr); + takenarr = NULL; +} + +void take_allocfail(void (*fn)(const void *p)) +{ + allocfailfn = fn; +}