diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib/memarea.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/lib/memarea.c b/src/lib/memarea.c new file mode 100644 index 0000000..747ea8b --- /dev/null +++ b/src/lib/memarea.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "memarea.h" + +struct memarea { + const void *data; + size_t size; + + memarea_free_callback_t *callback; + void *context; + + int refcount; +}; + +static struct memarea memarea_empty = { + .refcount = 1, +}; + +#undef memarea_init +struct memarea * +memarea_init(const void *data, size_t size, + memarea_free_callback_t *callback, void *context) +{ + struct memarea *area; + + i_assert(callback != NULL); + + area = i_new(struct memarea, 1); + area->data = data; + area->size = size; + area->callback = callback; + area->context = context; + area->refcount = 1; + return area; +} + +struct memarea *memarea_init_empty(void) +{ + i_assert(memarea_empty.refcount > 0); + memarea_empty.refcount++; + return &memarea_empty; +} + +void memarea_ref(struct memarea *area) +{ + i_assert(area->refcount > 0); + area->refcount++; +} + +void memarea_unref(struct memarea **_area) +{ + struct memarea *area = *_area; + + *_area = NULL; + i_assert(area->refcount > 0); + + if (--area->refcount > 0) + return; + i_assert(area != &memarea_empty); + area->callback(area->context); + i_free(area); +} + +void memarea_free_without_callback(struct memarea **_area) +{ + struct memarea *area = *_area; + + *_area = NULL; + i_assert(memarea_get_refcount(area) == 1); + i_free(area); +} + +unsigned int memarea_get_refcount(struct memarea *area) +{ + i_assert(area->refcount > 0); + return area->refcount; +} + +const void *memarea_get(struct memarea *area, size_t *size_r) +{ + *size_r = area->size; + return area->data; +} + +size_t memarea_get_size(struct memarea *area) +{ + return area->size; +} + +void memarea_free_callback_noop(void *context ATTR_UNUSED) +{ +} |