nghttp2_map: Implement hash table
This commit is contained in:
parent
1f0dfd4316
commit
a3c888d7d1
|
@ -24,227 +24,135 @@
|
||||||
*/
|
*/
|
||||||
#include "nghttp2_map.h"
|
#include "nghttp2_map.h"
|
||||||
|
|
||||||
void nghttp2_map_init(nghttp2_map *map)
|
#include <string.h>
|
||||||
|
|
||||||
|
#define INITIAL_TABLE_LENGTH 16
|
||||||
|
|
||||||
|
#define LOAD_FACTOR 75
|
||||||
|
|
||||||
|
int nghttp2_map_init(nghttp2_map *map)
|
||||||
{
|
{
|
||||||
map->root = NULL;
|
map->tablelen = INITIAL_TABLE_LENGTH;
|
||||||
|
map->table = malloc(sizeof(nghttp2_map_entry*) * map->tablelen);
|
||||||
|
if(map->table == NULL) {
|
||||||
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
memset(map->table, 0, sizeof(nghttp2_map_entry*) * map->tablelen);
|
||||||
map->size = 0;
|
map->size = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_map_free(nghttp2_map *map)
|
void nghttp2_map_free(nghttp2_map *map)
|
||||||
{
|
{
|
||||||
map->root = NULL;
|
free(map->table);
|
||||||
}
|
|
||||||
|
|
||||||
/* Find left most node, which is not necessarily a leaf. */
|
|
||||||
static nghttp2_map_entry* find_left_most(nghttp2_map_entry *entry)
|
|
||||||
{
|
|
||||||
while(entry->left) {
|
|
||||||
entry = entry->left;
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find left most leaf. */
|
|
||||||
static nghttp2_map_entry* find_left_most_leaf(nghttp2_map_entry *entry)
|
|
||||||
{
|
|
||||||
for(;;) {
|
|
||||||
entry = find_left_most(entry);
|
|
||||||
if(entry->right) {
|
|
||||||
entry = entry->right;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns next node in postorder traversal. Returns NULL if there is
|
|
||||||
no next node. */
|
|
||||||
static nghttp2_map_entry* traverse_postorder(nghttp2_map_entry *parent,
|
|
||||||
nghttp2_map_entry *entry)
|
|
||||||
{
|
|
||||||
if(!parent) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(parent->left == entry) {
|
|
||||||
if(parent->right) {
|
|
||||||
return find_left_most_leaf(parent->right);
|
|
||||||
} else {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_map_each_free(nghttp2_map *map,
|
void nghttp2_map_each_free(nghttp2_map *map,
|
||||||
int (*func)(nghttp2_map_entry *entry, void *ptr),
|
int (*func)(nghttp2_map_entry *entry, void *ptr),
|
||||||
void *ptr)
|
void *ptr)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *entry;
|
size_t i;
|
||||||
if(!map->root) {
|
for(i = 0; i < map->tablelen; ++i) {
|
||||||
return;
|
nghttp2_map_entry *entry;
|
||||||
|
for(entry = map->table[i]; entry;) {
|
||||||
|
nghttp2_map_entry *next = entry->next;
|
||||||
|
func(entry, ptr);
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
map->table[i] = NULL;
|
||||||
}
|
}
|
||||||
entry = find_left_most_leaf(map->root);
|
|
||||||
while(entry) {
|
|
||||||
nghttp2_map_entry *parent = entry->parent;
|
|
||||||
/* Ignore return value. */
|
|
||||||
func(entry, ptr);
|
|
||||||
/* entry has been deleted. */
|
|
||||||
entry = traverse_postorder(parent, entry);
|
|
||||||
}
|
|
||||||
map->root = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns next node in inorder traversal. Returns NULL if there is no
|
|
||||||
next node. */
|
|
||||||
static nghttp2_map_entry* traverse_inorder(nghttp2_map_entry *entry)
|
|
||||||
{
|
|
||||||
nghttp2_map_entry *parent;
|
|
||||||
if(entry->right) {
|
|
||||||
return find_left_most(entry->right);
|
|
||||||
}
|
|
||||||
parent = entry->parent;
|
|
||||||
while(parent && parent->right == entry) {
|
|
||||||
entry = entry->parent;
|
|
||||||
parent = parent->parent;
|
|
||||||
}
|
|
||||||
return parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_map_each(nghttp2_map *map,
|
int nghttp2_map_each(nghttp2_map *map,
|
||||||
int (*func)(nghttp2_map_entry *entry, void *ptr),
|
int (*func)(nghttp2_map_entry *entry, void *ptr),
|
||||||
void *ptr)
|
void *ptr)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *entry;
|
int rv;
|
||||||
if(!map->root) {
|
size_t i;
|
||||||
return 0;
|
for(i = 0; i < map->tablelen; ++i) {
|
||||||
}
|
nghttp2_map_entry *entry;
|
||||||
entry = find_left_most(map->root);
|
for(entry = map->table[i]; entry; entry = entry->next) {
|
||||||
while(entry) {
|
rv = func(entry, ptr);
|
||||||
int rv = func(entry, ptr);
|
if(rv != 0) {
|
||||||
if(rv != 0) {
|
return rv;
|
||||||
return rv;
|
}
|
||||||
}
|
}
|
||||||
entry = traverse_inorder(entry);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 32 bit Mix Functions by Thomas Wang
|
|
||||||
*
|
|
||||||
* http://www.concentric.net/~Ttwang/tech/inthash.htm
|
|
||||||
*/
|
|
||||||
static uint32_t hash32shift(uint32_t key)
|
|
||||||
{
|
|
||||||
key = ~key + (key << 15); /* key = (key << 15) - key - 1; */
|
|
||||||
key = key ^ (key >> 12);
|
|
||||||
key = key + (key << 2);
|
|
||||||
key = key ^ (key >> 4);
|
|
||||||
key = key * 2057; /* key = (key + (key << 3)) + (key << 11); */
|
|
||||||
key = key ^ (key >> 16);
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key)
|
void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key)
|
||||||
{
|
{
|
||||||
entry->key = key;
|
entry->key = key;
|
||||||
entry->parent = entry->left = entry->right = NULL;
|
entry->next = NULL;
|
||||||
entry->priority = hash32shift(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static nghttp2_map_entry* rotate_left(nghttp2_map_entry *entry)
|
/* Same hash function in openjdk HashMap source code. */
|
||||||
|
/* The |mod| must be power of 2 */
|
||||||
|
static int32_t hash(int32_t h, int32_t mod)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *root = entry->right;
|
h ^= (h >> 20) ^ (h >> 12);
|
||||||
entry->right = root->left;
|
return (h ^ (h >> 7) ^ (h >> 4)) & (mod - 1);
|
||||||
root->left = entry;
|
|
||||||
|
|
||||||
root->parent = entry->parent;
|
|
||||||
entry->parent = root;
|
|
||||||
if(root->parent) {
|
|
||||||
if(root->parent->left == entry) {
|
|
||||||
root->parent->left = root;
|
|
||||||
} else {
|
|
||||||
root->parent->right = root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(entry->right) {
|
|
||||||
entry->right->parent = entry;
|
|
||||||
}
|
|
||||||
return root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static nghttp2_map_entry* rotate_right(nghttp2_map_entry* entry)
|
static int insert(nghttp2_map_entry **table, size_t tablelen,
|
||||||
|
nghttp2_map_entry *entry)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *root = entry->left;
|
int32_t h = hash(entry->key, tablelen);
|
||||||
entry->left = root->right;
|
if(table[h] == NULL) {
|
||||||
root->right = entry;
|
table[h] = entry;
|
||||||
|
} else {
|
||||||
|
nghttp2_map_entry *p;
|
||||||
|
/* We won't allow duplicated key, so check it out. */
|
||||||
|
for(p = table[h]; p; p = p->next) {
|
||||||
|
if(p->key == entry->key) {
|
||||||
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry->next = table[h];
|
||||||
|
table[h] = entry;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
root->parent = entry->parent;
|
/* new_tablelen must be power of 2 */
|
||||||
entry->parent = root;
|
static int resize(nghttp2_map *map, size_t new_tablelen)
|
||||||
if(root->parent) {
|
{
|
||||||
if(root->parent->left == entry) {
|
size_t i;
|
||||||
root->parent->left = root;
|
nghttp2_map_entry **new_table;
|
||||||
} else {
|
new_table = malloc(sizeof(nghttp2_map_entry*) * new_tablelen);
|
||||||
root->parent->right = root;
|
if(new_table == NULL) {
|
||||||
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
memset(new_table, 0, sizeof(nghttp2_map_entry*) * new_tablelen);
|
||||||
|
for(i = 0; i < map->tablelen; ++i) {
|
||||||
|
nghttp2_map_entry *entry;
|
||||||
|
for(entry = map->table[i]; entry;) {
|
||||||
|
nghttp2_map_entry *next = entry->next;
|
||||||
|
entry->next = NULL;
|
||||||
|
/* This function must succeed */
|
||||||
|
insert(new_table, new_tablelen, entry);
|
||||||
|
entry = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(entry->left) {
|
free(map->table);
|
||||||
entry->left->parent = entry;
|
map->tablelen = new_tablelen;
|
||||||
}
|
map->table = new_table;
|
||||||
return root;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry)
|
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *entry = map->root, *parent = NULL;
|
int rv;
|
||||||
if(map->root == NULL) {
|
if(100 * (map->size + 1) > map->tablelen * LOAD_FACTOR) {
|
||||||
map->root = new_entry;
|
rv = resize(map, map->tablelen * 2);
|
||||||
map->size = 1;
|
if(rv != 0) {
|
||||||
return 0;
|
return rv;
|
||||||
}
|
|
||||||
/* Find position to insert. */
|
|
||||||
while(1) {
|
|
||||||
if(new_entry->key == entry->key) {
|
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
|
||||||
} else {
|
|
||||||
if(new_entry->key < entry->key) {
|
|
||||||
if(entry->left) {
|
|
||||||
entry = entry->left;
|
|
||||||
} else {
|
|
||||||
parent = entry;
|
|
||||||
parent->left = new_entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(entry->right) {
|
|
||||||
entry = entry->right;
|
|
||||||
} else {
|
|
||||||
parent = entry;
|
|
||||||
parent->right = new_entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_entry->parent = parent;
|
rv = insert(map->table, map->tablelen, new_entry);
|
||||||
|
if(rv != 0) {
|
||||||
/* Rotate tree to satisfy heap property. */
|
return rv;
|
||||||
for(entry = parent; ; entry = entry->parent) {
|
|
||||||
if(entry->left && entry->priority > entry->left->priority) {
|
|
||||||
entry = rotate_right(entry);
|
|
||||||
} else if(entry->right && entry->priority > entry->right->priority) {
|
|
||||||
entry = rotate_left(entry);
|
|
||||||
} else {
|
|
||||||
/* At this point, tree forms heap. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* If no parent is assigned, then it is a root node. */
|
|
||||||
if(!entry->parent) {
|
|
||||||
map->root = entry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++map->size;
|
++map->size;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -252,13 +160,11 @@ int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry)
|
||||||
|
|
||||||
nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key)
|
nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *entry = map->root;
|
int32_t h;
|
||||||
while(entry != NULL) {
|
nghttp2_map_entry *entry;
|
||||||
if(key < entry->key) {
|
h = hash(key, map->tablelen);
|
||||||
entry = entry->left;
|
for(entry = map->table[h]; entry; entry = entry->next) {
|
||||||
} else if(key > entry->key) {
|
if(entry->key == key) {
|
||||||
entry = entry->right;
|
|
||||||
} else {
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,67 +173,23 @@ nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key)
|
||||||
|
|
||||||
int nghttp2_map_remove(nghttp2_map *map, key_type key)
|
int nghttp2_map_remove(nghttp2_map *map, key_type key)
|
||||||
{
|
{
|
||||||
nghttp2_map_entry *entry = map->root;
|
int32_t h;
|
||||||
|
nghttp2_map_entry *entry, *prev;
|
||||||
if(map->root == NULL) {
|
h = hash(key, map->tablelen);
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
prev = NULL;
|
||||||
}
|
for(entry = map->table[h]; entry; entry = entry->next) {
|
||||||
/* Locate entry to delete. */
|
if(entry->key == key) {
|
||||||
while(entry) {
|
if(prev == NULL) {
|
||||||
if(key < entry->key) {
|
map->table[h] = entry->next;
|
||||||
entry = entry->left;
|
|
||||||
} else if(key > entry->key) {
|
|
||||||
entry = entry->right;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!entry) {
|
|
||||||
/* Not found */
|
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
/* Rotate and bubble down to satisfy heap property. */
|
|
||||||
for(;;) {
|
|
||||||
if(!entry->left) {
|
|
||||||
if(!entry->parent) {
|
|
||||||
map->root = entry->right;
|
|
||||||
} else if(entry->parent->left == entry) {
|
|
||||||
entry->parent->left = entry->right;
|
|
||||||
} else {
|
} else {
|
||||||
entry->parent->right = entry->right;
|
prev->next = entry->next;
|
||||||
}
|
}
|
||||||
if(entry->right) {
|
--map->size;
|
||||||
entry->right->parent = entry->parent;
|
return 0;
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if(!entry->right) {
|
|
||||||
if(!entry->parent) {
|
|
||||||
map->root = entry->left;
|
|
||||||
} else if(entry->parent->left == entry) {
|
|
||||||
entry->parent->left = entry->left;
|
|
||||||
} else {
|
|
||||||
entry->parent->right = entry->left;
|
|
||||||
}
|
|
||||||
if(entry->left) {
|
|
||||||
entry->left->parent = entry->parent;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else if(entry->left->priority < entry->right->priority) {
|
|
||||||
entry = rotate_right(entry);
|
|
||||||
if(!entry->parent) {
|
|
||||||
map->root = entry;
|
|
||||||
}
|
|
||||||
entry = entry->right;
|
|
||||||
} else {
|
|
||||||
entry = rotate_left(entry);
|
|
||||||
if(!entry->parent) {
|
|
||||||
map->root = entry;
|
|
||||||
}
|
|
||||||
entry = entry->left;
|
|
||||||
}
|
}
|
||||||
|
prev = entry;
|
||||||
}
|
}
|
||||||
--map->size;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nghttp2_map_size(nghttp2_map *map)
|
size_t nghttp2_map_size(nghttp2_map *map)
|
||||||
|
|
|
@ -32,26 +32,31 @@
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
#include "nghttp2_int.h"
|
#include "nghttp2_int.h"
|
||||||
|
|
||||||
/* Implementation of ordered map */
|
/* Implementation of unordered map */
|
||||||
|
|
||||||
typedef uint32_t key_type;
|
typedef uint32_t key_type;
|
||||||
typedef uint32_t pri_type;
|
|
||||||
|
|
||||||
typedef struct nghttp2_map_entry {
|
typedef struct nghttp2_map_entry {
|
||||||
key_type key;
|
key_type key;
|
||||||
struct nghttp2_map_entry *parent, *left, *right;
|
struct nghttp2_map_entry *next;
|
||||||
pri_type priority;
|
|
||||||
} nghttp2_map_entry;
|
} nghttp2_map_entry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nghttp2_map_entry *root;
|
nghttp2_map_entry **table;
|
||||||
|
size_t tablelen;
|
||||||
size_t size;
|
size_t size;
|
||||||
} nghttp2_map;
|
} nghttp2_map;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes the map |map|.
|
* Initializes the map |map|.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGHTTP2_ERR_NOMEM
|
||||||
|
* Out of memory
|
||||||
*/
|
*/
|
||||||
void nghttp2_map_init(nghttp2_map *map);
|
int nghttp2_map_init(nghttp2_map *map);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deallocates any resources allocated for |map|. The stored entries
|
* Deallocates any resources allocated for |map|. The stored entries
|
||||||
|
@ -80,10 +85,12 @@ void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key);
|
||||||
* Inserts the new |entry| with the key |entry->key| to the map |map|.
|
* Inserts the new |entry| with the key |entry->key| to the map |map|.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error code:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||||
* The item associated by |key| already exists.
|
* The item associated by |key| already exists.
|
||||||
|
* NGHTTP2_ERR_NOMEM
|
||||||
|
* Out of memory
|
||||||
*/
|
*/
|
||||||
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *entry);
|
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *entry);
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,10 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
||||||
if(r != 0) {
|
if(r != 0) {
|
||||||
goto fail_hd_inflater;
|
goto fail_hd_inflater;
|
||||||
}
|
}
|
||||||
nghttp2_map_init(&(*session_ptr)->streams);
|
r = nghttp2_map_init(&(*session_ptr)->streams);
|
||||||
|
if(r != 0) {
|
||||||
|
goto fail_map;
|
||||||
|
}
|
||||||
r = nghttp2_pq_init(&(*session_ptr)->ob_pq, nghttp2_outbound_item_compar);
|
r = nghttp2_pq_init(&(*session_ptr)->ob_pq, nghttp2_outbound_item_compar);
|
||||||
if(r != 0) {
|
if(r != 0) {
|
||||||
goto fail_ob_pq;
|
goto fail_ob_pq;
|
||||||
|
@ -294,7 +297,8 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
||||||
fail_ob_ss_pq:
|
fail_ob_ss_pq:
|
||||||
nghttp2_pq_free(&(*session_ptr)->ob_pq);
|
nghttp2_pq_free(&(*session_ptr)->ob_pq);
|
||||||
fail_ob_pq:
|
fail_ob_pq:
|
||||||
/* No need to free (*session_ptr)->streams) here. */
|
nghttp2_map_free(&(*session_ptr)->streams);
|
||||||
|
fail_map:
|
||||||
nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater);
|
nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater);
|
||||||
fail_hd_inflater:
|
fail_hd_inflater:
|
||||||
nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater);
|
nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater);
|
||||||
|
@ -389,6 +393,7 @@ void nghttp2_session_del(nghttp2_session *session)
|
||||||
free(session->inflight_iv);
|
free(session->inflight_iv);
|
||||||
nghttp2_inbound_frame_reset(session);
|
nghttp2_inbound_frame_reset(session);
|
||||||
nghttp2_map_each_free(&session->streams, nghttp2_free_streams, NULL);
|
nghttp2_map_each_free(&session->streams, nghttp2_free_streams, NULL);
|
||||||
|
nghttp2_map_free(&session->streams);
|
||||||
nghttp2_session_ob_pq_free(&session->ob_pq);
|
nghttp2_session_ob_pq_free(&session->ob_pq);
|
||||||
nghttp2_session_ob_pq_free(&session->ob_ss_pq);
|
nghttp2_session_ob_pq_free(&session->ob_ss_pq);
|
||||||
nghttp2_hd_deflate_free(&session->hd_deflater);
|
nghttp2_hd_deflate_free(&session->hd_deflater);
|
||||||
|
@ -397,7 +402,7 @@ void nghttp2_session_del(nghttp2_session *session)
|
||||||
free(session->aob.framebuf);
|
free(session->aob.framebuf);
|
||||||
free(session->nvbuf);
|
free(session->nvbuf);
|
||||||
free(session->iframe.buf);
|
free(session->iframe.buf);
|
||||||
free(session);
|
free(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int outbound_item_update_pri
|
static int outbound_item_update_pri
|
||||||
|
|
|
@ -149,6 +149,7 @@ void test_nghttp2_map_functional(void)
|
||||||
CU_ASSERT(0 == nghttp2_map_insert(&map, &arr[i].map_entry));
|
CU_ASSERT(0 == nghttp2_map_insert(&map, &arr[i].map_entry));
|
||||||
}
|
}
|
||||||
nghttp2_map_each_free(&map, eachfun, NULL);
|
nghttp2_map_each_free(&map, eachfun, NULL);
|
||||||
|
nghttp2_map_free(&map);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int entry_free(nghttp2_map_entry *entry, void *ptr)
|
static int entry_free(nghttp2_map_entry *entry, void *ptr)
|
||||||
|
@ -177,4 +178,5 @@ void test_nghttp2_map_each_free(void)
|
||||||
nghttp2_map_insert(&map, &shrubbery->map_entry);
|
nghttp2_map_insert(&map, &shrubbery->map_entry);
|
||||||
|
|
||||||
nghttp2_map_each_free(&map, entry_free, NULL);
|
nghttp2_map_each_free(&map, entry_free, NULL);
|
||||||
|
nghttp2_map_free(&map);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue