mirror of
https://github.com/bkthomps/Containers.git
synced 2025-12-05 15:15:49 +00:00
Reduce calls to malloc in unordered_map (#96)
Reduce the number of malloc calls in unordered_map. Improves efficiency by 50% (meaning it takes half the time that it used to).
This commit is contained in:
@@ -47,7 +47,7 @@ unordered_map unordered_map_init(size_t key_size,
|
|||||||
|
|
||||||
/* Utility */
|
/* Utility */
|
||||||
int unordered_map_rehash(unordered_map me);
|
int unordered_map_rehash(unordered_map me);
|
||||||
int unordered_map_size(unordered_map me);
|
size_t unordered_map_size(unordered_map me);
|
||||||
int unordered_map_is_empty(unordered_map me);
|
int unordered_map_is_empty(unordered_map me);
|
||||||
|
|
||||||
/* Accessing */
|
/* Accessing */
|
||||||
@@ -116,12 +116,12 @@ unordered_multiset_init(size_t key_size,
|
|||||||
|
|
||||||
/* Utility */
|
/* Utility */
|
||||||
int unordered_multiset_rehash(unordered_multiset me);
|
int unordered_multiset_rehash(unordered_multiset me);
|
||||||
int unordered_multiset_size(unordered_multiset me);
|
size_t unordered_multiset_size(unordered_multiset me);
|
||||||
int unordered_multiset_is_empty(unordered_multiset me);
|
int unordered_multiset_is_empty(unordered_multiset me);
|
||||||
|
|
||||||
/* Accessing */
|
/* Accessing */
|
||||||
int unordered_multiset_put(unordered_multiset me, void *key);
|
int unordered_multiset_put(unordered_multiset me, void *key);
|
||||||
int unordered_multiset_count(unordered_multiset me, void *key);
|
size_t unordered_multiset_count(unordered_multiset me, void *key);
|
||||||
int unordered_multiset_contains(unordered_multiset me, void *key);
|
int unordered_multiset_contains(unordered_multiset me, void *key);
|
||||||
int unordered_multiset_remove(unordered_multiset me, void *key);
|
int unordered_multiset_remove(unordered_multiset me, void *key);
|
||||||
int unordered_multiset_remove_all(unordered_multiset me, void *key);
|
int unordered_multiset_remove_all(unordered_multiset me, void *key);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019 Bailey Thompson
|
* Copyright (c) 2017-2020 Bailey Thompson
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -40,7 +40,7 @@ unordered_map unordered_map_init(size_t key_size,
|
|||||||
|
|
||||||
/* Utility */
|
/* Utility */
|
||||||
int unordered_map_rehash(unordered_map me);
|
int unordered_map_rehash(unordered_map me);
|
||||||
int unordered_map_size(unordered_map me);
|
size_t unordered_map_size(unordered_map me);
|
||||||
int unordered_map_is_empty(unordered_map me);
|
int unordered_map_is_empty(unordered_map me);
|
||||||
|
|
||||||
/* Accessing */
|
/* Accessing */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019 Bailey Thompson
|
* Copyright (c) 2017-2020 Bailey Thompson
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -24,26 +24,26 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "include/unordered_map.h"
|
#include "include/unordered_map.h"
|
||||||
|
|
||||||
static const int STARTING_BUCKETS = 8;
|
#define STARTING_BUCKETS 16
|
||||||
static const double RESIZE_AT = 0.75;
|
#define RESIZE_AT 0.75
|
||||||
static const double RESIZE_RATIO = 1.5;
|
#define RESIZE_RATIO 2
|
||||||
|
|
||||||
struct internal_unordered_map {
|
struct internal_unordered_map {
|
||||||
size_t key_size;
|
size_t key_size;
|
||||||
size_t value_size;
|
size_t value_size;
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
unsigned long (*hash)(const void *const key);
|
unsigned long (*hash)(const void *const key);
|
||||||
int (*comparator)(const void *const one, const void *const two);
|
int (*comparator)(const void *const one, const void *const two);
|
||||||
int size;
|
char **buckets;
|
||||||
int capacity;
|
|
||||||
struct node **buckets;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node {
|
static const size_t ptr_size = sizeof(char *);
|
||||||
void *key;
|
static const size_t hash_size = sizeof(unsigned long);
|
||||||
void *value;
|
static const size_t node_next_offset = 0;
|
||||||
unsigned long hash;
|
static const size_t node_hash_offset = sizeof(char *);
|
||||||
struct node *next;
|
static const size_t node_key_offset = sizeof(char *) + sizeof(unsigned long);
|
||||||
};
|
/* Assume the value starts right after the key ends. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets the hash by first calling the user-defined hash, and then using a
|
* Gets the hash by first calling the user-defined hash, and then using a
|
||||||
@@ -94,7 +94,7 @@ unordered_map unordered_map_init(const size_t key_size,
|
|||||||
init->comparator = comparator;
|
init->comparator = comparator;
|
||||||
init->size = 0;
|
init->size = 0;
|
||||||
init->capacity = STARTING_BUCKETS;
|
init->capacity = STARTING_BUCKETS;
|
||||||
init->buckets = calloc(STARTING_BUCKETS, sizeof(struct node *));
|
init->buckets = calloc(STARTING_BUCKETS, ptr_size);
|
||||||
if (!init->buckets) {
|
if (!init->buckets) {
|
||||||
free(init);
|
free(init);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -105,20 +105,26 @@ unordered_map unordered_map_init(const size_t key_size,
|
|||||||
/*
|
/*
|
||||||
* Adds the specified node to the map.
|
* Adds the specified node to the map.
|
||||||
*/
|
*/
|
||||||
static void unordered_map_add_item(unordered_map me, struct node *const add)
|
static void unordered_map_add_item(unordered_map me, char *const add)
|
||||||
{
|
{
|
||||||
struct node *traverse;
|
char *traverse;
|
||||||
const int index = (int) (add->hash % me->capacity);
|
char *traverse_next;
|
||||||
add->next = NULL;
|
unsigned long hash;
|
||||||
|
size_t index;
|
||||||
|
memcpy(&hash, add + node_hash_offset, hash_size);
|
||||||
|
index = hash % me->capacity;
|
||||||
|
memset(add + node_next_offset, 0, ptr_size);
|
||||||
if (!me->buckets[index]) {
|
if (!me->buckets[index]) {
|
||||||
me->buckets[index] = add;
|
me->buckets[index] = add;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
traverse = me->buckets[index];
|
traverse = me->buckets[index];
|
||||||
while (traverse->next) {
|
memcpy(&traverse_next, traverse + node_next_offset, ptr_size);
|
||||||
traverse = traverse->next;
|
while (traverse_next) {
|
||||||
|
traverse = traverse_next;
|
||||||
|
memcpy(&traverse_next, traverse + node_next_offset, ptr_size);
|
||||||
}
|
}
|
||||||
traverse->next = add;
|
memcpy(traverse + node_next_offset, &add, ptr_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,18 +138,21 @@ static void unordered_map_add_item(unordered_map me, struct node *const add)
|
|||||||
*/
|
*/
|
||||||
int unordered_map_rehash(unordered_map me)
|
int unordered_map_rehash(unordered_map me)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
struct node **old_buckets = me->buckets;
|
char **old_buckets = me->buckets;
|
||||||
me->buckets = calloc((size_t) me->capacity, sizeof(struct node *));
|
me->buckets = calloc(me->capacity, ptr_size);
|
||||||
if (!me->buckets) {
|
if (!me->buckets) {
|
||||||
me->buckets = old_buckets;
|
me->buckets = old_buckets;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
for (i = 0; i < me->capacity; i++) {
|
for (i = 0; i < me->capacity; i++) {
|
||||||
struct node *traverse = old_buckets[i];
|
char *traverse = old_buckets[i];
|
||||||
while (traverse) {
|
while (traverse) {
|
||||||
struct node *const backup = traverse->next;
|
char *backup;
|
||||||
traverse->hash = unordered_map_hash(me, traverse->key);
|
unsigned long hash;
|
||||||
|
memcpy(&backup, traverse + node_next_offset, ptr_size);
|
||||||
|
hash = unordered_map_hash(me, traverse + node_key_offset);
|
||||||
|
memcpy(traverse + node_hash_offset, &hash, hash_size);
|
||||||
unordered_map_add_item(me, traverse);
|
unordered_map_add_item(me, traverse);
|
||||||
traverse = backup;
|
traverse = backup;
|
||||||
}
|
}
|
||||||
@@ -159,7 +168,7 @@ int unordered_map_rehash(unordered_map me)
|
|||||||
*
|
*
|
||||||
* @return the size of the unordered map
|
* @return the size of the unordered map
|
||||||
*/
|
*/
|
||||||
int unordered_map_size(unordered_map me)
|
size_t unordered_map_size(unordered_map me)
|
||||||
{
|
{
|
||||||
return me->size;
|
return me->size;
|
||||||
}
|
}
|
||||||
@@ -181,20 +190,21 @@ int unordered_map_is_empty(unordered_map me)
|
|||||||
*/
|
*/
|
||||||
static int unordered_map_resize(unordered_map me)
|
static int unordered_map_resize(unordered_map me)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
const int old_capacity = me->capacity;
|
const size_t old_capacity = me->capacity;
|
||||||
const int new_capacity = (int) (me->capacity * RESIZE_RATIO);
|
const size_t new_capacity = me->capacity * RESIZE_RATIO;
|
||||||
struct node **old_buckets = me->buckets;
|
char **old_buckets = me->buckets;
|
||||||
me->buckets = calloc((size_t) new_capacity, sizeof(struct node *));
|
me->buckets = calloc(new_capacity, ptr_size);
|
||||||
if (!me->buckets) {
|
if (!me->buckets) {
|
||||||
me->buckets = old_buckets;
|
me->buckets = old_buckets;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
me->capacity = new_capacity;
|
me->capacity = new_capacity;
|
||||||
for (i = 0; i < old_capacity; i++) {
|
for (i = 0; i < old_capacity; i++) {
|
||||||
struct node *traverse = old_buckets[i];
|
char *traverse = old_buckets[i];
|
||||||
while (traverse) {
|
while (traverse) {
|
||||||
struct node *const backup = traverse->next;
|
char *backup;
|
||||||
|
memcpy(&backup, traverse + node_next_offset, ptr_size);
|
||||||
unordered_map_add_item(me, traverse);
|
unordered_map_add_item(me, traverse);
|
||||||
traverse = backup;
|
traverse = backup;
|
||||||
}
|
}
|
||||||
@@ -206,41 +216,32 @@ static int unordered_map_resize(unordered_map me)
|
|||||||
/*
|
/*
|
||||||
* Determines if an element is equal to the key.
|
* Determines if an element is equal to the key.
|
||||||
*/
|
*/
|
||||||
static int unordered_map_is_equal(unordered_map me,
|
static int unordered_map_is_equal(unordered_map me, char *const item,
|
||||||
const struct node *const item,
|
|
||||||
const unsigned long hash,
|
const unsigned long hash,
|
||||||
const void *const key)
|
const void *const key)
|
||||||
{
|
{
|
||||||
return item->hash == hash && me->comparator(item->key, key) == 0;
|
unsigned long item_hash;
|
||||||
|
memcpy(&item_hash, item + node_hash_offset, hash_size);
|
||||||
|
return item_hash == hash &&
|
||||||
|
me->comparator(item + node_key_offset, key) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates an element to add.
|
* Creates an element to add.
|
||||||
*/
|
*/
|
||||||
static struct node *unordered_map_create_element(unordered_map me,
|
static char *unordered_map_create_element(unordered_map me,
|
||||||
const unsigned long hash,
|
const unsigned long hash,
|
||||||
const void *const key,
|
const void *const key,
|
||||||
const void *const value)
|
const void *const value)
|
||||||
{
|
{
|
||||||
struct node *const init = malloc(sizeof(struct node));
|
char *init = malloc(ptr_size + hash_size + me->key_size);
|
||||||
if (!init) {
|
if (!init) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
init->key = malloc(me->key_size);
|
memset(init + node_next_offset, 0, ptr_size);
|
||||||
if (!init->key) {
|
memcpy(init + node_hash_offset, &hash, hash_size);
|
||||||
free(init);
|
memcpy(init + node_key_offset, key, me->key_size);
|
||||||
return NULL;
|
memcpy(init + node_key_offset + me->key_size, value, me->value_size);
|
||||||
}
|
|
||||||
memcpy(init->key, key, me->key_size);
|
|
||||||
init->value = malloc(me->value_size);
|
|
||||||
if (!init->value) {
|
|
||||||
free(init->key);
|
|
||||||
free(init);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(init->value, value, me->value_size);
|
|
||||||
init->hash = hash;
|
|
||||||
init->next = NULL;
|
|
||||||
return init;
|
return init;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,35 +265,41 @@ int unordered_map_put(unordered_map me, void *const key, void *const value)
|
|||||||
{
|
{
|
||||||
const unsigned long hash = unordered_map_hash(me, key);
|
const unsigned long hash = unordered_map_hash(me, key);
|
||||||
int index;
|
int index;
|
||||||
if (me->size + 1 >= RESIZE_AT * me->capacity) {
|
if (me->size + 1 >= (size_t) (RESIZE_AT * me->capacity)) {
|
||||||
const int rc = unordered_map_resize(me);
|
const int rc = unordered_map_resize(me);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index = (int) (hash % me->capacity);
|
index = (size_t) (hash % me->capacity);
|
||||||
if (!me->buckets[index]) {
|
if (!me->buckets[index]) {
|
||||||
me->buckets[index] = unordered_map_create_element(me, hash, key, value);
|
me->buckets[index] = unordered_map_create_element(me, hash, key, value);
|
||||||
if (!me->buckets[index]) {
|
if (!me->buckets[index]) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct node *traverse = me->buckets[index];
|
char *traverse = me->buckets[index];
|
||||||
|
char *traverse_next;
|
||||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||||
memcpy(traverse->value, value, me->value_size);
|
memcpy(traverse + node_key_offset + me->key_size, value,
|
||||||
|
me->value_size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (traverse->next) {
|
memcpy(&traverse_next, traverse + node_next_offset, ptr_size);
|
||||||
traverse = traverse->next;
|
while (traverse_next) {
|
||||||
|
traverse = traverse_next;
|
||||||
|
memcpy(&traverse_next, traverse + node_next_offset, ptr_size);
|
||||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||||
memcpy(traverse->value, value, me->value_size);
|
memcpy(traverse + node_key_offset + me->key_size, value,
|
||||||
|
me->value_size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traverse->next = unordered_map_create_element(me, hash, key, value);
|
traverse_next = unordered_map_create_element(me, hash, key, value);
|
||||||
if (!traverse->next) {
|
if (!traverse_next) {
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
memcpy(traverse + node_next_offset, &traverse_next, ptr_size);
|
||||||
}
|
}
|
||||||
me->size++;
|
me->size++;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -315,14 +322,14 @@ int unordered_map_put(unordered_map me, void *const key, void *const value)
|
|||||||
int unordered_map_get(void *const value, unordered_map me, void *const key)
|
int unordered_map_get(void *const value, unordered_map me, void *const key)
|
||||||
{
|
{
|
||||||
const unsigned long hash = unordered_map_hash(me, key);
|
const unsigned long hash = unordered_map_hash(me, key);
|
||||||
const int index = (int) (hash % me->capacity);
|
char *traverse = me->buckets[hash % me->capacity];
|
||||||
struct node *traverse = me->buckets[index];
|
|
||||||
while (traverse) {
|
while (traverse) {
|
||||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||||
memcpy(value, traverse->value, me->value_size);
|
memcpy(value, traverse + node_key_offset + me->key_size,
|
||||||
|
me->value_size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
traverse = traverse->next;
|
memcpy(&traverse, traverse + node_next_offset, ptr_size);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -342,13 +349,12 @@ int unordered_map_get(void *const value, unordered_map me, void *const key)
|
|||||||
int unordered_map_contains(unordered_map me, void *const key)
|
int unordered_map_contains(unordered_map me, void *const key)
|
||||||
{
|
{
|
||||||
const unsigned long hash = unordered_map_hash(me, key);
|
const unsigned long hash = unordered_map_hash(me, key);
|
||||||
const int index = (int) (hash % me->capacity);
|
char *traverse = me->buckets[hash % me->capacity];
|
||||||
const struct node *traverse = me->buckets[index];
|
|
||||||
while (traverse) {
|
while (traverse) {
|
||||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
traverse = traverse->next;
|
memcpy(&traverse, traverse + node_next_offset, ptr_size);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -367,32 +373,31 @@ int unordered_map_contains(unordered_map me, void *const key)
|
|||||||
*/
|
*/
|
||||||
int unordered_map_remove(unordered_map me, void *const key)
|
int unordered_map_remove(unordered_map me, void *const key)
|
||||||
{
|
{
|
||||||
struct node *traverse;
|
char *traverse;
|
||||||
|
char *traverse_next;
|
||||||
const unsigned long hash = unordered_map_hash(me, key);
|
const unsigned long hash = unordered_map_hash(me, key);
|
||||||
const int index = (int) (hash % me->capacity);
|
const size_t index = hash % me->capacity;
|
||||||
if (!me->buckets[index]) {
|
if (!me->buckets[index]) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
traverse = me->buckets[index];
|
traverse = me->buckets[index];
|
||||||
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
if (unordered_map_is_equal(me, traverse, hash, key)) {
|
||||||
me->buckets[index] = traverse->next;
|
memcpy(me->buckets + index, traverse + node_next_offset, ptr_size);
|
||||||
free(traverse->key);
|
|
||||||
free(traverse->value);
|
|
||||||
free(traverse);
|
free(traverse);
|
||||||
me->size--;
|
me->size--;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
while (traverse->next) {
|
memcpy(&traverse_next, traverse + node_next_offset, ptr_size);
|
||||||
if (unordered_map_is_equal(me, traverse->next, hash, key)) {
|
while (traverse_next) {
|
||||||
struct node *const backup = traverse->next;
|
if (unordered_map_is_equal(me, traverse_next, hash, key)) {
|
||||||
traverse->next = traverse->next->next;
|
memcpy(traverse + node_next_offset,
|
||||||
free(backup->key);
|
traverse_next + node_next_offset, ptr_size);
|
||||||
free(backup->value);
|
free(traverse_next);
|
||||||
free(backup);
|
|
||||||
me->size--;
|
me->size--;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
traverse = traverse->next;
|
traverse = traverse_next;
|
||||||
|
memcpy(&traverse_next, traverse + node_next_offset, ptr_size);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -407,27 +412,22 @@ int unordered_map_remove(unordered_map me, void *const key)
|
|||||||
*/
|
*/
|
||||||
int unordered_map_clear(unordered_map me)
|
int unordered_map_clear(unordered_map me)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
struct node **temp =
|
char **updated_buckets = calloc(STARTING_BUCKETS, ptr_size);
|
||||||
calloc((size_t) STARTING_BUCKETS, sizeof(struct node *));
|
if (!updated_buckets) {
|
||||||
if (!temp) {
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
for (i = 0; i < me->capacity; i++) {
|
for (i = 0; i < me->capacity; i++) {
|
||||||
struct node *traverse = me->buckets[i];
|
char *traverse = me->buckets[i];
|
||||||
while (traverse) {
|
while (traverse) {
|
||||||
struct node *const backup = traverse;
|
char *backup = traverse;
|
||||||
traverse = traverse->next;
|
memcpy(&traverse, traverse + node_next_offset, ptr_size);
|
||||||
free(backup->key);
|
|
||||||
free(backup->value);
|
|
||||||
free(backup);
|
free(backup);
|
||||||
}
|
}
|
||||||
me->buckets[i] = NULL;
|
|
||||||
}
|
}
|
||||||
me->size = 0;
|
me->size = 0;
|
||||||
me->capacity = STARTING_BUCKETS;
|
me->capacity = STARTING_BUCKETS;
|
||||||
free(me->buckets);
|
me->buckets = updated_buckets;
|
||||||
me->buckets = temp;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -243,22 +243,10 @@ static void test_put_out_of_memory(void)
|
|||||||
assert(me);
|
assert(me);
|
||||||
fail_malloc = 1;
|
fail_malloc = 1;
|
||||||
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
||||||
fail_malloc = 1;
|
|
||||||
delay_fail_malloc = 1;
|
|
||||||
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
|
||||||
fail_malloc = 1;
|
|
||||||
delay_fail_malloc = 2;
|
|
||||||
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
|
||||||
assert(unordered_map_put(me, &key, &value) == 0);
|
assert(unordered_map_put(me, &key, &value) == 0);
|
||||||
key = 7;
|
key = 7;
|
||||||
fail_malloc = 1;
|
fail_malloc = 1;
|
||||||
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
||||||
fail_malloc = 1;
|
|
||||||
delay_fail_malloc = 1;
|
|
||||||
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
|
||||||
fail_malloc = 1;
|
|
||||||
delay_fail_malloc = 2;
|
|
||||||
assert(unordered_map_put(me, &key, &value) == -ENOMEM);
|
|
||||||
assert(!unordered_map_destroy(me));
|
assert(!unordered_map_destroy(me));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -269,15 +257,15 @@ static void test_resize_out_of_memory(void)
|
|||||||
int i;
|
int i;
|
||||||
unordered_map me = unordered_map_init(sizeof(int), sizeof(int), hash_int,
|
unordered_map me = unordered_map_init(sizeof(int), sizeof(int), hash_int,
|
||||||
compare_int);
|
compare_int);
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 11; i++) {
|
||||||
assert(unordered_map_put(me, &i, &i) == 0);
|
assert(unordered_map_put(me, &i, &i) == 0);
|
||||||
}
|
}
|
||||||
assert(unordered_map_size(me) == 5);
|
assert(unordered_map_size(me) == 11);
|
||||||
i++;
|
i++;
|
||||||
fail_calloc = 1;
|
fail_calloc = 1;
|
||||||
assert(unordered_map_put(me, &i, &i) == -ENOMEM);
|
assert(unordered_map_put(me, &i, &i) == -ENOMEM);
|
||||||
assert(unordered_map_size(me) == 5);
|
assert(unordered_map_size(me) == 11);
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 11; i++) {
|
||||||
assert(unordered_map_contains(me, &i));
|
assert(unordered_map_contains(me, &i));
|
||||||
}
|
}
|
||||||
assert(!unordered_map_destroy(me));
|
assert(!unordered_map_destroy(me));
|
||||||
|
|||||||
Reference in New Issue
Block a user