@ -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 ;
}