[Spice-devel,2/3] add SpiceRefcountedChunk

Submitted by Christophe Fergeau on Aug. 22, 2011, 1:39 p.m.

Details

Message ID 1313995160-11625-3-git-send-email-cfergeau@redhat.com
State New, archived
Headers show

Not browsing as part of any series.

Commit Message

Christophe Fergeau Aug. 22, 2011, 1:39 p.m.
It's a SpiceChunk with an additional reference count so that the
chunk data can be freed when the chunk is no longer needed.
---
 common/mem.c |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 common/mem.h |    7 +++++++
 2 files changed, 64 insertions(+), 0 deletions(-)

Patch hide | download patch | download mbox

diff --git a/common/mem.c b/common/mem.c
index cfc3ef1..ffb0a87 100644
--- a/common/mem.c
+++ b/common/mem.c
@@ -20,6 +20,7 @@ 
 #endif
 
 #include "mem.h"
+#include "spice_common.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -308,3 +309,59 @@  size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len)
     buffer->offset -= len;
     return len;
 }
+
+struct SpiceRefcountedChunk {
+    SpiceChunk chunk;
+    uint8_t refs;
+    spice_chunk_free_func free_chunk;
+    void *opaque;
+};
+
+SpiceRefcountedChunk *
+spice_refcounted_chunk_new(uint8_t *data, uint32_t len,
+                           spice_chunk_free_func free_chunk,
+                           void *opaque)
+{
+    SpiceRefcountedChunk *chunk;
+
+    chunk = spice_malloc0(sizeof(SpiceRefcountedChunk));
+    chunk->chunk.data = data;
+    chunk->chunk.len = len;
+    chunk->free_chunk = free_chunk;
+    chunk->refs = 1;
+    chunk->opaque = opaque;
+
+    return chunk;
+}
+
+SpiceRefcountedChunk *
+spice_refcounted_chunk_ref(SpiceRefcountedChunk *chunk)
+{
+    chunk->refs++;
+    return chunk;
+}
+
+int spice_refcounted_chunk_unref(SpiceRefcountedChunk *chunk)
+{
+    if (chunk == NULL) {
+        red_printf("chunk == NULL");
+        return 0;
+    }
+
+    if (chunk->refs == 0) {
+        red_printf("chunk->refs == 0");
+        return 0;
+    }
+
+    chunk->refs--;
+
+    if (chunk->refs == 0) {
+        if (chunk->free_chunk != NULL)
+            chunk->free_chunk(chunk->chunk.data, chunk->opaque);
+
+        return 1;
+    }
+    free(chunk);
+
+    return 0;
+}
diff --git a/common/mem.h b/common/mem.h
index 2d423a3..573452e 100644
--- a/common/mem.h
+++ b/common/mem.h
@@ -96,6 +96,13 @@  SpiceChunks *spice_chunks_new(uint32_t count) SPICE_GNUC_MALLOC;
 SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len) SPICE_GNUC_MALLOC;
 void spice_chunks_destroy(SpiceChunks *chunks);
 void spice_chunks_linearize(SpiceChunks *chunks);
+typedef struct SpiceRefcountedChunk SpiceRefcountedChunk;
+typedef void (*spice_chunk_free_func)(uint8_t *data, void *opaque);
+SpiceRefcountedChunk *spice_refcounted_chunk_new(uint8_t *data, uint32_t len,
+                                                 spice_chunk_free_func free_chunk,
+                                                 void *opaque);
+SpiceRefcountedChunk *spice_refcounted_chunk_ref(SpiceRefcountedChunk *chunk);
+int spice_refcounted_chunk_unref(SpiceRefcountedChunk *chunk);
 
 size_t spice_strnlen(const char *str, size_t max_len);