From f8d53635e4aadb4ca5d2cc759590f6cefbe4ab30 Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Sat, 25 Jan 2020 15:29:25 +0000 Subject: [PATCH] Create a reference counted buffer --- include/rcbuf.h | 32 ++++++++++++++++++++++ meson.build | 1 + src/rcbuf.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 include/rcbuf.h create mode 100644 src/rcbuf.c diff --git a/include/rcbuf.h b/include/rcbuf.h new file mode 100644 index 0000000..cabd488 --- /dev/null +++ b/include/rcbuf.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include + +struct rcbuf { + void* payload; + size_t size; + int ref; +}; + +struct rcbuf* rcbuf_new(void* payload, size_t size); +struct rcbuf* rcbuf_from_string(const char* str); +struct rcbuf* rcbuf_from_mem(const void* addr, size_t size); + +void rcbuf_ref(struct rcbuf* self); +void rcbuf_unref(struct rcbuf* self); diff --git a/meson.build b/meson.build index eb0d4d9..b1773ba 100644 --- a/meson.build +++ b/meson.build @@ -48,6 +48,7 @@ sources = [ 'src/pixels.c', 'src/damage.c', 'src/fb.c', + 'src/rcbuf.c', 'contrib/miniz/miniz.c', ] diff --git a/src/rcbuf.c b/src/rcbuf.c new file mode 100644 index 0000000..80862ee --- /dev/null +++ b/src/rcbuf.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "rcbuf.h" + +#include +#include +#include + +struct rcbuf* rcbuf_new(void* payload, size_t size) +{ + struct rcbuf* self = calloc(1, sizeof(*self)); + if (!self) + return NULL; + + self->ref = 1; + self->payload = payload; + self->size = size; + + return self; +} + +struct rcbuf* rcbuf_from_string(const char* str) +{ + char* value = strdup(str); + return value ? rcbuf_new(value, strlen(str)) : NULL; +} + +struct rcbuf* rcbuf_from_mem(const void* addr, size_t size) +{ + void* mem = malloc(size); + if (!mem) + return NULL; + + memcpy(mem, addr, size); + + struct rcbuf* rcbuf = rcbuf_new(mem, size); + if (!rcbuf) + free(mem); + + return rcbuf; +} + +void rcbuf_ref(struct rcbuf* self) +{ + self->ref++; +} + +void rcbuf_unref(struct rcbuf* self) +{ + assert(self->ref > 0); + + if (--self->ref > 0) + return; + + free(self->payload); + free(self); +}