]> git.ozlabs.org Git - ccan/blob - ccan/take/take.c
73e5c29d206fcf5a5cf23e7b6f8d4836a3d06fc4
[ccan] / ccan / take / take.c
1 /* CC0 (Public domain) - see LICENSE file for details */
2 #include <ccan/take/take.h>
3 #include <ccan/likely/likely.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 static const void **takenarr;
8 static size_t max_taken, num_taken;
9 static size_t allocfail;
10 static void (*allocfailfn)(const void *p);
11
12 void *take_(const void *p)
13 {
14         if (unlikely(num_taken == max_taken)) {
15                 const void **new;
16
17                 new = realloc(takenarr, sizeof(*takenarr) * (max_taken+1));
18                 if (unlikely(!new)) {
19                         if (allocfailfn) {
20                                 allocfail++;
21                                 allocfailfn(p);
22                                 return NULL;
23                         }
24                         /* Otherwise we leak p. */
25                         return (void *)p;
26                 }
27                 takenarr = new;
28                 max_taken++;
29         }
30         takenarr[num_taken++] = p;
31         return (void *)p;
32 }
33
34 static size_t find_taken(const void *p)
35 {
36         size_t i;
37
38         for (i = 0; i < num_taken; i++) {
39                 if (takenarr[i] == p)
40                         return i+1;
41         }
42         return 0;
43 }
44
45 bool taken(const void *p)
46 {
47         size_t i;
48
49         if (!p && unlikely(allocfail)) {
50                 allocfail--;
51                 return true;
52         }
53
54         i = find_taken(p);
55         if (!i)
56                 return false;
57
58         memmove(&takenarr[i-1], &takenarr[i],
59                 (--num_taken - (i - 1))*sizeof(takenarr[0]));
60         return true;
61 }
62
63 bool is_taken(const void *p)
64 {
65         if (!p && unlikely(allocfail))
66                 return true;
67
68         return find_taken(p) > 0;
69 }
70
71 bool taken_any(void)
72 {
73         return num_taken != 0;
74 }
75
76 void take_cleanup(void)
77 {
78         max_taken = num_taken = 0;
79         free(takenarr);
80         takenarr = NULL;
81 }
82
83 void take_allocfail(void (*fn)(const void *p))
84 {
85         allocfailfn = fn;
86 }