|
|
|
@ -27,7 +27,7 @@ |
|
|
|
|
|
|
|
|
|
void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map* map, |
|
|
|
|
size_t initial_capacity) { |
|
|
|
|
GPR_ASSERT(initial_capacity > 1); |
|
|
|
|
GPR_DEBUG_ASSERT(initial_capacity > 1); |
|
|
|
|
map->keys = |
|
|
|
|
static_cast<uint32_t*>(gpr_malloc(sizeof(uint32_t) * initial_capacity)); |
|
|
|
|
map->values = |
|
|
|
@ -63,9 +63,17 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map* map, uint32_t key, |
|
|
|
|
uint32_t* keys = map->keys; |
|
|
|
|
void** values = map->values; |
|
|
|
|
|
|
|
|
|
// The first assertion ensures that the table is monotonically increasing.
|
|
|
|
|
GPR_ASSERT(count == 0 || keys[count - 1] < key); |
|
|
|
|
GPR_ASSERT(value); |
|
|
|
|
GPR_ASSERT(grpc_chttp2_stream_map_find(map, key) == nullptr); |
|
|
|
|
GPR_DEBUG_ASSERT(value); |
|
|
|
|
// Asserting that the key is not already in the map can be a debug assertion.
|
|
|
|
|
// Why: we're already checking that the map elements are monotonically
|
|
|
|
|
// increasing. If we re-add a key, i.e. if the key is already present, then
|
|
|
|
|
// either it is the most recently added key in the map (in which case the
|
|
|
|
|
// first assertion fails due to key == last_key) or there is a more recently
|
|
|
|
|
// added (larger) key at the end of the map: in which case the first assertion
|
|
|
|
|
// still fails due to key < last_key.
|
|
|
|
|
GPR_DEBUG_ASSERT(grpc_chttp2_stream_map_find(map, key) == nullptr); |
|
|
|
|
|
|
|
|
|
if (count == capacity) { |
|
|
|
|
if (map->free > capacity / 4) { |
|
|
|
@ -74,7 +82,7 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map* map, uint32_t key, |
|
|
|
|
} else { |
|
|
|
|
/* resize when less than 25% of the table is free, because compaction
|
|
|
|
|
won't help much */ |
|
|
|
|
map->capacity = capacity = 3 * capacity / 2; |
|
|
|
|
map->capacity = capacity = 2 * capacity; |
|
|
|
|
map->keys = keys = static_cast<uint32_t*>( |
|
|
|
|
gpr_realloc(keys, capacity * sizeof(uint32_t))); |
|
|
|
|
map->values = values = |
|
|
|
@ -87,6 +95,7 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map* map, uint32_t key, |
|
|
|
|
map->count = count + 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <bool strict_find> |
|
|
|
|
static void** find(grpc_chttp2_stream_map* map, uint32_t key) { |
|
|
|
|
size_t min_idx = 0; |
|
|
|
|
size_t max_idx = map->count; |
|
|
|
@ -95,7 +104,8 @@ static void** find(grpc_chttp2_stream_map* map, uint32_t key) { |
|
|
|
|
void** values = map->values; |
|
|
|
|
uint32_t mid_key; |
|
|
|
|
|
|
|
|
|
if (max_idx == 0) return nullptr; |
|
|
|
|
GPR_DEBUG_ASSERT(!strict_find || max_idx > 0); |
|
|
|
|
if (!strict_find && max_idx == 0) return nullptr; |
|
|
|
|
|
|
|
|
|
while (min_idx < max_idx) { |
|
|
|
|
/* find the midpoint, avoiding overflow */ |
|
|
|
@ -112,28 +122,28 @@ static void** find(grpc_chttp2_stream_map* map, uint32_t key) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
GPR_DEBUG_ASSERT(!strict_find); |
|
|
|
|
return nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void* grpc_chttp2_stream_map_delete(grpc_chttp2_stream_map* map, uint32_t key) { |
|
|
|
|
void** pvalue = find(map, key); |
|
|
|
|
void* out = nullptr; |
|
|
|
|
if (pvalue != nullptr) { |
|
|
|
|
out = *pvalue; |
|
|
|
|
*pvalue = nullptr; |
|
|
|
|
map->free += (out != nullptr); |
|
|
|
|
/* recognize complete emptyness and ensure we can skip
|
|
|
|
|
* defragmentation later */ |
|
|
|
|
if (map->free == map->count) { |
|
|
|
|
map->free = map->count = 0; |
|
|
|
|
} |
|
|
|
|
GPR_ASSERT(grpc_chttp2_stream_map_find(map, key) == nullptr); |
|
|
|
|
void** pvalue = find<true>(map, key); |
|
|
|
|
GPR_DEBUG_ASSERT(pvalue != nullptr); |
|
|
|
|
void* out = *pvalue; |
|
|
|
|
GPR_DEBUG_ASSERT(out != nullptr); |
|
|
|
|
*pvalue = nullptr; |
|
|
|
|
map->free++; |
|
|
|
|
/* recognize complete emptyness and ensure we can skip
|
|
|
|
|
defragmentation later */ |
|
|
|
|
if (map->free == map->count) { |
|
|
|
|
map->free = map->count = 0; |
|
|
|
|
} |
|
|
|
|
GPR_DEBUG_ASSERT(grpc_chttp2_stream_map_find(map, key) == nullptr); |
|
|
|
|
return out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void* grpc_chttp2_stream_map_find(grpc_chttp2_stream_map* map, uint32_t key) { |
|
|
|
|
void** pvalue = find(map, key); |
|
|
|
|
void** pvalue = find<false>(map, key); |
|
|
|
|
return pvalue != nullptr ? *pvalue : nullptr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|