Move slice functions to vtable, implement hash

reviewable/pr8842/r1
Craig Tiller 8 years ago
parent d7f15831c6
commit 0451c3dbfc
  1. 15
      include/grpc/impl/codegen/slice.h
  2. 2
      include/grpc/slice.h
  3. 2
      src/core/ext/transport/chttp2/transport/hpack_encoder.c
  4. 6
      src/core/lib/iomgr/resource_quota.c
  5. 32
      src/core/lib/slice/slice.c
  6. 2
      src/core/lib/slice/slice_hash_table.c
  7. 25
      src/core/lib/slice/slice_intern.c
  8. 6
      src/core/lib/transport/static_metadata.c
  9. 5
      tools/codegen/core/gen_static_metadata.py

@ -39,6 +39,8 @@
#include <grpc/impl/codegen/exec_ctx_fwd.h> #include <grpc/impl/codegen/exec_ctx_fwd.h>
typedef struct grpc_slice grpc_slice;
/* Slice API /* Slice API
A slice represents a contiguous reference counted array of bytes. A slice represents a contiguous reference counted array of bytes.
@ -52,14 +54,19 @@
reference ownership semantics (who should call unref?) and mutability reference ownership semantics (who should call unref?) and mutability
constraints (is the callee allowed to modify the slice?) */ constraints (is the callee allowed to modify the slice?) */
typedef struct grpc_slice_refcount_vtable {
void (*ref)(void *);
void (*unref)(grpc_exec_ctx *exec_ctx, void *);
uint32_t (*hash)(void *, grpc_slice slice);
} grpc_slice_refcount_vtable;
/* Reference count container for grpc_slice. Contains function pointers to /* Reference count container for grpc_slice. Contains function pointers to
increment and decrement reference counts. Implementations should cleanup increment and decrement reference counts. Implementations should cleanup
when the reference count drops to zero. when the reference count drops to zero.
Typically client code should not touch this, and use grpc_slice_malloc, Typically client code should not touch this, and use grpc_slice_malloc,
grpc_slice_new, or grpc_slice_new_with_len instead. */ grpc_slice_new, or grpc_slice_new_with_len instead. */
typedef struct grpc_slice_refcount { typedef struct grpc_slice_refcount {
void (*ref)(void *); const grpc_slice_refcount_vtable *vtable;
void (*unref)(grpc_exec_ctx *exec_ctx, void *);
} grpc_slice_refcount; } grpc_slice_refcount;
#define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1) #define GRPC_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1)
@ -73,7 +80,7 @@ typedef struct grpc_slice_refcount {
If the slice does not have a refcount, it represents an inlined small piece If the slice does not have a refcount, it represents an inlined small piece
of data that is copied by value. */ of data that is copied by value. */
typedef struct grpc_slice { struct grpc_slice {
struct grpc_slice_refcount *refcount; struct grpc_slice_refcount *refcount;
union { union {
struct { struct {
@ -85,7 +92,7 @@ typedef struct grpc_slice {
uint8_t bytes[GRPC_SLICE_INLINED_SIZE]; uint8_t bytes[GRPC_SLICE_INLINED_SIZE];
} inlined; } inlined;
} data; } data;
} grpc_slice; };
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 #define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8

@ -121,6 +121,8 @@ GPRAPI grpc_slice grpc_slice_split_head(grpc_slice *s, size_t split);
GPRAPI grpc_slice grpc_empty_slice(void); GPRAPI grpc_slice grpc_empty_slice(void);
GPRAPI uint32_t grpc_slice_default_hash_impl(void *, grpc_slice s);
/* Returns <0 if a < b, ==0 if a == b, >0 if a > b /* Returns <0 if a < b, ==0 if a == b, >0 if a > b
The order is arbitrary, and is not guaranteed to be stable across different The order is arbitrary, and is not guaranteed to be stable across different
versions of the API. */ versions of the API. */

@ -64,7 +64,7 @@
/* don't consider adding anything bigger than this to the hpack table */ /* don't consider adding anything bigger than this to the hpack table */
#define MAX_DECODER_SPACE_USAGE 512 #define MAX_DECODER_SPACE_USAGE 512
static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL}; static grpc_slice_refcount terminal_slice_refcount = {NULL};
static const grpc_slice terminal_slice = {&terminal_slice_refcount, static const grpc_slice terminal_slice = {&terminal_slice_refcount,
.data.refcounted = {0, 0}}; .data.refcounted = {0, 0}};

@ -366,11 +366,13 @@ static void ru_slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
} }
} }
static const grpc_slice_refcount_vtable ru_slice_vtable = {
ru_slice_ref, ru_slice_unref, grpc_slice_default_hash_impl};
static grpc_slice ru_slice_create(grpc_resource_user *resource_user, static grpc_slice ru_slice_create(grpc_resource_user *resource_user,
size_t size) { size_t size) {
ru_slice_refcount *rc = gpr_malloc(sizeof(ru_slice_refcount) + size); ru_slice_refcount *rc = gpr_malloc(sizeof(ru_slice_refcount) + size);
rc->base.ref = ru_slice_ref; rc->base.vtable = &ru_slice_vtable;
rc->base.unref = ru_slice_unref;
gpr_ref_init(&rc->refs, 1); gpr_ref_init(&rc->refs, 1);
rc->resource_user = resource_user; rc->resource_user = resource_user;
rc->size = size; rc->size = size;

@ -50,14 +50,14 @@ grpc_slice grpc_empty_slice(void) {
grpc_slice grpc_slice_ref_internal(grpc_slice slice) { grpc_slice grpc_slice_ref_internal(grpc_slice slice) {
if (slice.refcount) { if (slice.refcount) {
slice.refcount->ref(slice.refcount); slice.refcount->vtable->ref(slice.refcount);
} }
return slice; return slice;
} }
void grpc_slice_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice slice) { void grpc_slice_unref_internal(grpc_exec_ctx *exec_ctx, grpc_slice slice) {
if (slice.refcount) { if (slice.refcount) {
slice.refcount->unref(exec_ctx, slice.refcount); slice.refcount->vtable->unref(exec_ctx, slice.refcount);
} }
} }
@ -78,7 +78,9 @@ void grpc_slice_unref(grpc_slice slice) {
static void noop_ref(void *unused) {} static void noop_ref(void *unused) {}
static void noop_unref(grpc_exec_ctx *exec_ctx, void *unused) {} static void noop_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
static grpc_slice_refcount noop_refcount = {noop_ref, noop_unref}; static const grpc_slice_refcount_vtable noop_refcount_vtable = {
noop_ref, noop_unref, grpc_slice_default_hash_impl};
static grpc_slice_refcount noop_refcount = {&noop_refcount_vtable};
grpc_slice grpc_slice_from_static_string(const char *s) { grpc_slice grpc_slice_from_static_string(const char *s) {
grpc_slice slice; grpc_slice slice;
@ -110,14 +112,16 @@ static void new_slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
} }
} }
static const grpc_slice_refcount_vtable new_slice_vtable = {
new_slice_ref, new_slice_unref, grpc_slice_default_hash_impl};
grpc_slice grpc_slice_new_with_user_data(void *p, size_t len, grpc_slice grpc_slice_new_with_user_data(void *p, size_t len,
void (*destroy)(void *), void (*destroy)(void *),
void *user_data) { void *user_data) {
grpc_slice slice; grpc_slice slice;
new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount)); new_slice_refcount *rc = gpr_malloc(sizeof(new_slice_refcount));
gpr_ref_init(&rc->refs, 1); gpr_ref_init(&rc->refs, 1);
rc->rc.ref = new_slice_ref; rc->rc.vtable = &new_slice_vtable;
rc->rc.unref = new_slice_unref;
rc->user_destroy = destroy; rc->user_destroy = destroy;
rc->user_data = user_data; rc->user_data = user_data;
@ -155,14 +159,16 @@ static void new_with_len_unref(grpc_exec_ctx *exec_ctx, void *p) {
} }
} }
static const grpc_slice_refcount_vtable new_with_len_vtable = {
new_with_len_ref, new_with_len_unref, grpc_slice_default_hash_impl};
grpc_slice grpc_slice_new_with_len(void *p, size_t len, grpc_slice grpc_slice_new_with_len(void *p, size_t len,
void (*destroy)(void *, size_t)) { void (*destroy)(void *, size_t)) {
grpc_slice slice; grpc_slice slice;
new_with_len_slice_refcount *rc = new_with_len_slice_refcount *rc =
gpr_malloc(sizeof(new_with_len_slice_refcount)); gpr_malloc(sizeof(new_with_len_slice_refcount));
gpr_ref_init(&rc->refs, 1); gpr_ref_init(&rc->refs, 1);
rc->rc.ref = new_with_len_ref; rc->rc.vtable = &new_with_len_vtable;
rc->rc.unref = new_with_len_unref;
rc->user_destroy = destroy; rc->user_destroy = destroy;
rc->user_data = p; rc->user_data = p;
rc->user_length = len; rc->user_length = len;
@ -200,6 +206,9 @@ static void malloc_unref(grpc_exec_ctx *exec_ctx, void *p) {
} }
} }
static const grpc_slice_refcount_vtable malloc_vtable = {
malloc_ref, malloc_unref, grpc_slice_default_hash_impl};
grpc_slice grpc_slice_malloc(size_t length) { grpc_slice grpc_slice_malloc(size_t length) {
grpc_slice slice; grpc_slice slice;
@ -219,8 +228,7 @@ grpc_slice grpc_slice_malloc(size_t length) {
this reference. */ this reference. */
gpr_ref_init(&rc->refs, 1); gpr_ref_init(&rc->refs, 1);
rc->base.ref = malloc_ref; rc->base.vtable = &malloc_vtable;
rc->base.unref = malloc_unref;
/* Build up the slice to be returned. */ /* Build up the slice to be returned. */
/* The slices refcount points back to the allocated block. */ /* The slices refcount points back to the allocated block. */
@ -273,7 +281,7 @@ grpc_slice grpc_slice_sub(grpc_slice source, size_t begin, size_t end) {
} else { } else {
subset = grpc_slice_sub_no_ref(source, begin, end); subset = grpc_slice_sub_no_ref(source, begin, end);
/* Bump the refcount */ /* Bump the refcount */
subset.refcount->ref(subset.refcount); subset.refcount->vtable->ref(subset.refcount);
} }
return subset; return subset;
} }
@ -302,7 +310,7 @@ grpc_slice grpc_slice_split_tail(grpc_slice *source, size_t split) {
/* Build the result */ /* Build the result */
tail.refcount = source->refcount; tail.refcount = source->refcount;
/* Bump the refcount */ /* Bump the refcount */
tail.refcount->ref(tail.refcount); tail.refcount->vtable->ref(tail.refcount);
/* Point into the source array */ /* Point into the source array */
tail.data.refcounted.bytes = source->data.refcounted.bytes + split; tail.data.refcounted.bytes = source->data.refcounted.bytes + split;
tail.data.refcounted.length = tail_length; tail.data.refcounted.length = tail_length;
@ -340,7 +348,7 @@ grpc_slice grpc_slice_split_head(grpc_slice *source, size_t split) {
/* Build the result */ /* Build the result */
head.refcount = source->refcount; head.refcount = source->refcount;
/* Bump the refcount */ /* Bump the refcount */
head.refcount->ref(head.refcount); head.refcount->vtable->ref(head.refcount);
/* Point into the source array */ /* Point into the source array */
head.data.refcounted.bytes = source->data.refcounted.bytes; head.data.refcounted.bytes = source->data.refcounted.bytes;
head.data.refcounted.length = split; head.data.refcounted.length = split;

@ -40,7 +40,7 @@
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL}; static grpc_slice_refcount terminal_slice_refcount = {NULL};
static const grpc_slice terminal_slice = {&terminal_slice_refcount, static const grpc_slice terminal_slice = {&terminal_slice_refcount,
.data.refcounted = {0, 0}}; .data.refcounted = {0, 0}};

@ -100,6 +100,18 @@ static void interned_slice_unref(grpc_exec_ctx *exec_ctx, void *p) {
} }
} }
static uint32_t interned_slice_hash(void *p, grpc_slice slice) {
interned_slice_refcount *s = p;
if (slice.data.refcounted.bytes == (uint8_t *)(s + 1) &&
slice.data.refcounted.length == s->length) {
return s->hash;
}
return grpc_slice_default_hash_impl(p, slice);
}
static const grpc_slice_refcount_vtable interned_slice_vtable = {
interned_slice_ref, interned_slice_unref, interned_slice_hash};
static void grow_shard(slice_shard *shard) { static void grow_shard(slice_shard *shard) {
size_t capacity = shard->capacity * 2; size_t capacity = shard->capacity * 2;
size_t i; size_t i;
@ -135,6 +147,16 @@ static grpc_slice materialize(interned_slice_refcount *s) {
return slice; return slice;
} }
uint32_t grpc_slice_default_hash_impl(void *unused_refcnt, grpc_slice s) {
return gpr_murmur_hash3(GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s),
g_hash_seed);
}
uint32_t grpc_slice_hash(grpc_slice s) {
return s.refcount == NULL ? grpc_slice_default_hash_impl(NULL, s)
: s.refcount->vtable->hash(s.refcount, s);
}
grpc_slice grpc_slice_intern(grpc_slice slice) { grpc_slice grpc_slice_intern(grpc_slice slice) {
interned_slice_refcount *s; interned_slice_refcount *s;
uint32_t hash = gpr_murmur_hash3(GRPC_SLICE_START_PTR(slice), uint32_t hash = gpr_murmur_hash3(GRPC_SLICE_START_PTR(slice),
@ -168,8 +190,7 @@ grpc_slice grpc_slice_intern(grpc_slice slice) {
gpr_atm_rel_store(&s->refcnt, 1); gpr_atm_rel_store(&s->refcnt, 1);
s->length = GRPC_SLICE_LENGTH(slice); s->length = GRPC_SLICE_LENGTH(slice);
s->hash = hash; s->hash = hash;
s->base.ref = interned_slice_ref; s->base.vtable = &interned_slice_vtable;
s->base.unref = interned_slice_unref;
s->bucket_next = shard->strs[idx]; s->bucket_next = shard->strs[idx];
shard->strs[idx] = s; shard->strs[idx] = s;
memcpy(s + 1, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); memcpy(s + 1, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice));

@ -114,10 +114,12 @@ static uint8_t g_raw_bytes[] = {
static void static_ref(void *unused) {} static void static_ref(void *unused) {}
static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {} static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}
static grpc_slice_refcount g_refcnt = {static_ref, static_unref}; static const grpc_slice_refcount_vtable static_vtable = {
static_ref, static_unref, grpc_slice_default_hash_impl};
static grpc_slice_refcount g_refcnt = {&static_vtable};
bool grpc_is_static_metadata_string(grpc_slice slice) { bool grpc_is_static_metadata_string(grpc_slice slice) {
return slice.refcount != NULL && slice.refcount->ref == static_ref; return slice.refcount != NULL && slice.refcount->vtable == &static_vtable;
} }
const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = { const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {

@ -310,10 +310,11 @@ print >>C, 'static uint8_t g_raw_bytes[] = {%s};' % (','.join('%d' % ord(c) for
print >>C print >>C
print >>C, 'static void static_ref(void *unused) {}' print >>C, 'static void static_ref(void *unused) {}'
print >>C, 'static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}' print >>C, 'static void static_unref(grpc_exec_ctx *exec_ctx, void *unused) {}'
print >>C, 'static grpc_slice_refcount g_refcnt = {static_ref, static_unref};' print >>C, 'static const grpc_slice_refcount_vtable static_vtable = {static_ref, static_unref, grpc_slice_default_hash_impl};';
print >>C, 'static grpc_slice_refcount g_refcnt = {&static_vtable};'
print >>C print >>C
print >>C, 'bool grpc_is_static_metadata_string(grpc_slice slice) {' print >>C, 'bool grpc_is_static_metadata_string(grpc_slice slice) {'
print >>C, ' return slice.refcount != NULL && slice.refcount->ref == static_ref;' print >>C, ' return slice.refcount != NULL && slice.refcount->vtable == &static_vtable;'
print >>C, '}' print >>C, '}'
print >>C print >>C
print >>C, 'const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {' print >>C, 'const grpc_slice grpc_static_slice_table[GRPC_STATIC_MDSTR_COUNT] = {'

Loading…
Cancel
Save