aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar kpayson64 <kpayson@google.com>2016-07-21 17:53:29 -0700
committerGravatar GitHub <noreply@github.com>2016-07-21 17:53:29 -0700
commitd4087084f0651b36ecb19fceeda0108345aebcf5 (patch)
tree7269985178246a440854e38030408354b4eb5f82
parentb8208ff79a7bc87c5a4ba420b0f096b63e09a067 (diff)
parentfca59fb2aa4a0be093d12162c763b8563ada4087 (diff)
Merge pull request #7488 from ghemawat/slice_user_data
Add gpr_slice_new_with_user_data.
-rw-r--r--include/grpc/impl/codegen/slice.h8
-rw-r--r--src/core/lib/support/slice.c11
-rw-r--r--test/core/support/slice_test.c22
3 files changed, 39 insertions, 2 deletions
diff --git a/include/grpc/impl/codegen/slice.h b/include/grpc/impl/codegen/slice.h
index c684b7587d..dfc0a774fc 100644
--- a/include/grpc/impl/codegen/slice.h
+++ b/include/grpc/impl/codegen/slice.h
@@ -120,6 +120,14 @@ GPRAPI void gpr_slice_unref(gpr_slice s);
passed in at destruction. */
GPRAPI gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *));
+/* Equivalent to gpr_slice_new, but with a separate pointer that is
+ passed to the destroy function. This function can be useful when
+ the data is part of a larger structure that must be destroyed when
+ the data is no longer needed. */
+GPRAPI gpr_slice gpr_slice_new_with_user_data(void *p, size_t len,
+ void (*destroy)(void *),
+ void *user_data);
+
/* Equivalent to gpr_slice_new, but with a two argument destroy function that
also takes the slice length. */
GPRAPI gpr_slice gpr_slice_new_with_len(void *p, size_t len,
diff --git a/src/core/lib/support/slice.c b/src/core/lib/support/slice.c
index b9a7c77bda..8a2c0a9086 100644
--- a/src/core/lib/support/slice.c
+++ b/src/core/lib/support/slice.c
@@ -94,14 +94,16 @@ static void new_slice_unref(void *p) {
}
}
-gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
+gpr_slice gpr_slice_new_with_user_data(void *p, size_t len,
+ void (*destroy)(void *),
+ void *user_data) {
gpr_slice slice;
new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
gpr_ref_init(&rc->refs, 1);
rc->rc.ref = new_slice_ref;
rc->rc.unref = new_slice_unref;
rc->user_destroy = destroy;
- rc->user_data = p;
+ rc->user_data = user_data;
slice.refcount = &rc->rc;
slice.data.refcounted.bytes = p;
@@ -109,6 +111,11 @@ gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
return slice;
}
+gpr_slice gpr_slice_new(void *p, size_t len, void (*destroy)(void *)) {
+ /* Pass "p" to *destroy when the slice is no longer needed. */
+ return gpr_slice_new_with_user_data(p, len, destroy, p);
+}
+
/* gpr_slice_new_with_len support structures - we create a refcount object
extended with the user provided data pointer & destroy function */
typedef struct new_with_len_slice_refcount {
diff --git a/test/core/support/slice_test.c b/test/core/support/slice_test.c
index 0da483a321..06c364b368 100644
--- a/test/core/support/slice_test.c
+++ b/test/core/support/slice_test.c
@@ -85,6 +85,27 @@ static void test_slice_new_returns_something_sensible(void) {
gpr_slice_unref(slice);
}
+/* destroy function that sets a mark to indicate it was called. */
+static void set_mark(void *p) { *((int *)p) = 1; }
+
+static void test_slice_new_with_user_data(void) {
+ int marker = 0;
+ uint8_t buf[2];
+ gpr_slice slice;
+
+ buf[0] = 0;
+ buf[1] = 1;
+ slice = gpr_slice_new_with_user_data(buf, 2, set_mark, &marker);
+ GPR_ASSERT(marker == 0);
+ GPR_ASSERT(GPR_SLICE_LENGTH(slice) == 2);
+ GPR_ASSERT(GPR_SLICE_START_PTR(slice)[0] == 0);
+ GPR_ASSERT(GPR_SLICE_START_PTR(slice)[1] == 1);
+
+ /* unref should cause destroy function to run. */
+ gpr_slice_unref(slice);
+ GPR_ASSERT(marker == 1);
+}
+
static int do_nothing_with_len_1_calls = 0;
static void do_nothing_with_len_1(void *ignored, size_t len) {
@@ -232,6 +253,7 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_slice_malloc_returns_something_sensible();
test_slice_new_returns_something_sensible();
+ test_slice_new_with_user_data();
test_slice_new_with_len_returns_something_sensible();
for (length = 0; length < 128; length++) {
test_slice_sub_works(length);