]> code.delx.au - pulseaudio/blobdiff - polyp/memblock.c
latency calculation fix
[pulseaudio] / polyp / memblock.c
index 8f24ff22100d59c871518b1418c9008a3e590a5b..500d8b206d342b9101b8aecfef9bea6ca5221939 100644 (file)
 #include <string.h>
 
 #include "memblock.h"
+#include "xmalloc.h"
 
-static unsigned memblock_count = 0, memblock_total = 0;
+static void stat_add(struct pa_memblock*m, struct pa_memblock_stat *s) {
+    assert(m);
 
-struct pa_memblock *pa_memblock_new(size_t length) {
-    struct pa_memblock *b = malloc(sizeof(struct pa_memblock)+length);
+    m->stat = pa_memblock_stat_ref(s);
+    s->total++;
+    s->allocated++;
+    s->total_size += m->length;
+    s->allocated_size += m->length;
+}
+
+static void stat_remove(struct pa_memblock *m) {
+    assert(m);
+
+    if (!m->stat)
+        return;
+
+    m->stat->total--;
+    m->stat->total_size -= m->length;
+    
+    pa_memblock_stat_unref(m->stat);
+    m->stat = NULL;
+}
+
+struct pa_memblock *pa_memblock_new(size_t length, struct pa_memblock_stat*s) {
+    struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock)+length);
     b->type = PA_MEMBLOCK_APPENDED;
     b->ref = 1;
     b->length = length;
     b->data = b+1;
-    memblock_count++;
-    memblock_total += length;
+    b->free_cb = NULL;
+    stat_add(b, s);
     return b;
 }
 
-struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) {
-    struct pa_memblock *b = malloc(sizeof(struct pa_memblock));
+struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length, struct pa_memblock_stat*s) {
+    struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock));
     b->type = PA_MEMBLOCK_FIXED;
     b->ref = 1;
     b->length = length;
     b->data = d;
-    memblock_count++;
-    memblock_total += length;
+    b->free_cb = NULL;
+    stat_add(b, s);
     return b;
 }
 
-struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) {
-    struct pa_memblock *b = malloc(sizeof(struct pa_memblock));
+struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length, struct pa_memblock_stat*s) {
+    struct pa_memblock *b = pa_xmalloc(sizeof(struct pa_memblock));
     b->type = PA_MEMBLOCK_DYNAMIC;
     b->ref = 1;
     b->length = length;
     b->data = d;
-    memblock_count++;
-    memblock_total += length;
+    b->free_cb = NULL;
+    stat_add(b, s);
+    return b;
+}
+
+struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p), struct pa_memblock_stat*s) {
+    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;
+    stat_add(b, s);
     return b;
 }
 
@@ -73,41 +108,53 @@ 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)
-            free(b->data);
+    if ((--(b->ref)) == 0) {
+        stat_remove(b);
 
-        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);
 
-        free(b);
+        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 = malloc(b->length);
-        assert(d);
-        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--;
     }
 }
 
-unsigned pa_memblock_get_count(void) {
-    return memblock_count;
+struct pa_memblock_stat* pa_memblock_stat_new(void) {
+    struct pa_memblock_stat *s;
+
+    s = pa_xmalloc(sizeof(struct pa_memblock_stat));
+    s->ref = 1;
+    s->total = s->total_size = s->allocated = s->allocated_size = 0;
+
+    return s;
+}
+
+void pa_memblock_stat_unref(struct pa_memblock_stat *s) {
+    assert(s && s->ref >= 1);
+
+    if (!(--(s->ref))) {
+        assert(!s->total);
+        pa_xfree(s);
+    }
 }
 
-unsigned pa_memblock_get_total(void) {
-    return memblock_total;
+struct pa_memblock_stat * pa_memblock_stat_ref(struct pa_memblock_stat *s) {
+    assert(s);
+    s->ref++;
+    return s;
 }