nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

take.c (3051B)


      1 /* CC0 (Public domain) - see LICENSE file for details */
      2 #include "take.h"
      3 #include "likely.h"
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 
      8 static const void **takenarr;
      9 static const char **labelarr;
     10 static size_t max_taken, num_taken;
     11 static size_t allocfail;
     12 static void (*allocfailfn)(const void *p);
     13 
     14 void *take_(const void *p, const char *label)
     15 {
     16     /* Overallocate: it's better than risking calloc returning NULL! */
     17     if (unlikely(label && !labelarr))
     18         labelarr = calloc(max_taken+1, sizeof(*labelarr));
     19 
     20     if (unlikely(num_taken == max_taken)) {
     21         const void **new;
     22 
     23         new = realloc(takenarr, sizeof(*takenarr) * (max_taken+1));
     24         if (unlikely(!new)) {
     25             if (allocfailfn) {
     26                 allocfail++;
     27                 allocfailfn(p);
     28                 return NULL;
     29             }
     30             /* Otherwise we leak p. */
     31             return (void *)p;
     32         }
     33         takenarr = new;
     34         /* Once labelarr is set, we maintain it. */
     35         if (labelarr) {
     36                         const char **labelarr_new;
     37             labelarr_new = realloc(labelarr,
     38                            sizeof(*labelarr) * (max_taken+1));
     39                         if (labelarr_new) {
     40                                 labelarr = labelarr_new;
     41                         } else {
     42                                 /* num_taken will be out of sync with the size of
     43                                  * labelarr after realloc failure.
     44                                  * Just pretend that we never had labelarr allocated. */
     45                                 free(labelarr);
     46                                 labelarr = NULL;
     47                         }
     48                 }
     49         max_taken++;
     50     }
     51     if (unlikely(labelarr))
     52         labelarr[num_taken] = label;
     53     takenarr[num_taken++] = p;
     54 
     55     return (void *)p;
     56 }
     57 
     58 static size_t find_taken(const void *p)
     59 {
     60     size_t i;
     61 
     62     for (i = 0; i < num_taken; i++) {
     63         if (takenarr[i] == p)
     64             return i+1;
     65     }
     66     return 0;
     67 }
     68 
     69 bool taken(const void *p)
     70 {
     71     size_t i;
     72 
     73     if (!p && unlikely(allocfail)) {
     74         allocfail--;
     75         return true;
     76     }
     77 
     78     i = find_taken(p);
     79     if (!i)
     80         return false;
     81 
     82     memmove(&takenarr[i-1], &takenarr[i],
     83         (--num_taken - (i - 1))*sizeof(takenarr[0]));
     84     return true;
     85 }
     86 
     87 bool is_taken(const void *p)
     88 {
     89     if (!p && unlikely(allocfail))
     90         return true;
     91 
     92     return find_taken(p) > 0;
     93 }
     94 
     95 const char *taken_any(void)
     96 {
     97     static char pointer_buf[32];
     98 
     99     if (num_taken == 0)
    100         return NULL;
    101 
    102     /* We're *allowed* to have some with labels, some without. */
    103     if (labelarr) {
    104         size_t i;
    105         for (i = 0; i < num_taken; i++)
    106             if (labelarr[i])
    107                 return labelarr[i];
    108     }
    109 
    110     sprintf(pointer_buf, "%p", takenarr[0]);
    111     return pointer_buf;
    112 }
    113 
    114 void take_cleanup(void)
    115 {
    116     max_taken = num_taken = 0;
    117     free(takenarr);
    118     takenarr = NULL;
    119     free(labelarr);
    120     labelarr = NULL;
    121 }
    122 
    123 void take_allocfail(void (*fn)(const void *p))
    124 {
    125     allocfailfn = fn;
    126 }