summaryrefslogtreecommitdiffstats
path: root/polyp/memblock.c
diff options
context:
space:
mode:
Diffstat (limited to 'polyp/memblock.c')
-rw-r--r--polyp/memblock.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/polyp/memblock.c b/polyp/memblock.c
index 0571f5da..a4452efa 100644
--- a/polyp/memblock.c
+++ b/polyp/memblock.c
@@ -39,6 +39,7 @@ struct pa_memblock *pa_memblock_new(size_t length) {
b->ref = 1;
b->length = length;
b->data = b+1;
+ b->free_cb = NULL;
memblock_count++;
memblock_total += length;
return b;
@@ -50,6 +51,7 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) {
b->ref = 1;
b->length = length;
b->data = d;
+ b->free_cb = NULL;
memblock_count++;
memblock_total += length;
return b;
@@ -61,6 +63,21 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) {
b->ref = 1;
b->length = length;
b->data = d;
+ b->free_cb = NULL;
+ memblock_count++;
+ memblock_total += length;
+ return b;
+}
+
+struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p)) {
+ struct pa_memblock *b;
+ assert(d && length && free_cb);
+ b = pa_xmalloc(sizeof(struct pa_memblock));
+ b->type = PA_MEMBLOCK_USER;
+ b->ref = 1;
+ b->length = length;
+ b->data = d;
+ b->free_cb = free_cb;
memblock_count++;
memblock_total += length;
return b;
@@ -74,31 +91,28 @@ struct pa_memblock* pa_memblock_ref(struct pa_memblock*b) {
void pa_memblock_unref(struct pa_memblock*b) {
assert(b && b->ref >= 1);
- b->ref--;
-
- if (b->ref == 0) {
- if (b->type == PA_MEMBLOCK_DYNAMIC)
- pa_xfree(b->data);
+ if ((--(b->ref)) == 0) {
memblock_count--;
memblock_total -= b->length;
+ if (b->type == PA_MEMBLOCK_USER) {
+ assert(b->free_cb);
+ b->free_cb(b->data);
+ } else if (b->type == PA_MEMBLOCK_DYNAMIC)
+ pa_xfree(b->data);
+
pa_xfree(b);
}
}
void pa_memblock_unref_fixed(struct pa_memblock *b) {
- void *d;
-
- assert(b && b->ref >= 1);
+ assert(b && b->ref >= 1 && b->type == PA_MEMBLOCK_FIXED);
- if (b->ref == 1) {
+ if (b->ref == 1)
pa_memblock_unref(b);
- return;
- } else {
- d = pa_xmalloc(b->length);
- memcpy(d, b->data, b->length);
- b->data = d;
+ else {
+ b->data = pa_xmemdup(b->data, b->length);
b->type = PA_MEMBLOCK_DYNAMIC;
b->ref--;
}