Author: dcreager
Date: Sat Oct 15 13:36:40 2011
New Revision: 1183637
URL: http://svn.apache.org/viewvc?rev=1183637&view=rev
Log:
AVRO-921. C: Default wrapped buffer implementation is zero-copy
The avro_wrapped_buffer_new_copy function creates a default
implementation of the wrapped buffer interface. It creates a copy of
the data pointer that's passed in, which the wrapped buffer has full
control over. Before, the wrapped buffer implementation would create
futher copies of the underlying buffer whenever the copy() method was
called. Now, the wrapped buffer's copy is reference counted, and the
copy() and free() methods avoid making extra copies.
Modified:
avro/trunk/CHANGES.txt
avro/trunk/lang/c/src/avro/data.h
avro/trunk/lang/c/src/wrapped-buffer.c
Modified: avro/trunk/CHANGES.txt
URL:
http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1183637&r1=1183636&r2=1183637&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Sat Oct 15 13:36:40 2011
@@ -30,6 +30,9 @@ Avro 1.6.0 (unreleased)
AVRO-920. C: Memory readers and writers are now reusable. (dcreager)
+ AVRO-921. C: Default wrapped buffer implementation is zero-copy.
+ (dcreager)
+
AVRO-890: Java: Add Maven archetype for creating Avro service
projects. (Stephen Gargan via cutting)
Modified: avro/trunk/lang/c/src/avro/data.h
URL:
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro/data.h?rev=1183637&r1=1183636&r2=1183637&view=diff
==============================================================================
--- avro/trunk/lang/c/src/avro/data.h (original)
+++ avro/trunk/lang/c/src/avro/data.h Sat Oct 15 13:36:40 2011
@@ -329,8 +329,11 @@ avro_wrapped_buffer_slice(avro_wrapped_b
size_t offset, size_t length);
/**
- * Creates a new wrapped buffer wrapping the given memory region. The
- * wrapped buffer's copy method will create an actual copy.
+ * Creates a new wrapped buffer wrapping the given memory region. You
+ * have to ensure that buf stays around for as long as you need to new
+ * wrapped buffer. If you copy the wrapped buffer (using
+ * avro_wrapped_buffer_copy), this will create a copy of the data.
+ * Additional copies will reuse this new copy.
*/
int
@@ -346,7 +349,9 @@ avro_wrapped_buffer_new(avro_wrapped_buf
/**
* Creates a new wrapped buffer containing a copy of the given memory
- * region. The wrapped buffer's copy method will create further copies.
+ * region. This new copy will be reference counted; if you copy it
+ * further (using avro_wrapped_buffer_copy), the new copies will share a
+ * single underlying buffer.
*/
int
Modified: avro/trunk/lang/c/src/wrapped-buffer.c
URL:
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/wrapped-buffer.c?rev=1183637&r1=1183636&r2=1183637&view=diff
==============================================================================
--- avro/trunk/lang/c/src/wrapped-buffer.c (original)
+++ avro/trunk/lang/c/src/wrapped-buffer.c Sat Oct 15 13:36:40 2011
@@ -22,8 +22,10 @@
#include "avro_private.h"
#include "avro/allocation.h"
#include "avro/data.h"
+#include "avro/refcount.h"
struct avro_wrapped_copy {
+ volatile int refcount;
size_t allocated_size;
};
@@ -31,7 +33,25 @@ static void
avro_wrapped_copy_free(avro_wrapped_buffer_t *self)
{
struct avro_wrapped_copy *copy = self->user_data;
- avro_free(copy, copy->allocated_size);
+ if (avro_refcount_dec(©->refcount)) {
+ avro_free(copy, copy->allocated_size);
+ }
+}
+
+static int
+avro_wrapped_copy_copy(avro_wrapped_buffer_t *dest,
+ const avro_wrapped_buffer_t *src,
+ size_t offset, size_t length)
+{
+ struct avro_wrapped_copy *copy = src->user_data;
+ avro_refcount_inc(©->refcount);
+ dest->buf = src->buf + offset;
+ dest->size = length;
+ dest->user_data = copy;
+ dest->free = avro_wrapped_copy_free;
+ dest->copy = avro_wrapped_copy_copy;
+ dest->slice = NULL;
+ return 0;
}
int
@@ -48,9 +68,10 @@ avro_wrapped_buffer_new_copy(avro_wrappe
dest->size = length;
dest->user_data = copy;
dest->free = avro_wrapped_copy_free;
- dest->copy = NULL;
+ dest->copy = avro_wrapped_copy_copy;
dest->slice = NULL;
+ avro_refcount_set(©->refcount, 1);
copy->allocated_size = allocated_size;
memcpy((void *) dest->buf, buf, length);
return 0;
@@ -83,7 +104,7 @@ avro_wrapped_buffer_copy(avro_wrapped_bu
const avro_wrapped_buffer_t *src,
size_t offset, size_t length)
{
- if (offset >= src->size) {
+ if (offset > src->size) {
avro_set_error("Invalid offset when slicing buffer");
return EINVAL;
}
@@ -104,7 +125,7 @@ int
avro_wrapped_buffer_slice(avro_wrapped_buffer_t *self,
size_t offset, size_t length)
{
- if (offset >= self->size) {
+ if (offset > self->size) {
avro_set_error("Invalid offset when slicing buffer");
return EINVAL;
}