davidleeds / hashmap Goto Github PK
View Code? Open in Web Editor NEWTemplated type-safe hashmap implementation in C using open addressing and linear probing for collision resolution.
License: MIT License
Templated type-safe hashmap implementation in C using open addressing and linear probing for collision resolution.
License: MIT License
Is random iteration over entries possible?
When I was using the test program, I added elements while traversing, and found that I always traversed to the last element each time, adding and deleting at the same time. This is my test program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <libgen.h>
#include <errno.h>
#include <pthread.h>
#include "hashmap.h"
#define ERROR(format, args...) do{printf("\033[1;31m[TEST][%s-%d]\033[m" format, basename(__FILE__), __LINE__, ##args);}while(0)
#define DEBUG(format, args...) do{printf("\033[1;32m[TEST][%s-%d]\033[m" format, basename(__FILE__), __LINE__, ##args);}while(0)
#define INFO(format, args...) do{printf("\033[1;35m[TEST][%s-%d]\033[m" format, basename(__FILE__), __LINE__, ##args);}while(0)
#define SYSERR(format, args...) do{printf("\033[1;31m[TEST][%s-%d](%s) \033[m" format, basename(__FILE__), __LINE__, strerror(errno), ##args);}while(0)
typedef struct NPU_IMAGE_ST
{
uint64_t au64PhyAddr[3]; /* RW;The physical address of the image */
uint64_t au64VirAddr[3]; /* RW;The virtual address of the image */
uint32_t au32Stride[3]; /* RW;The stride of the image */
uint32_t u32Width; /* RW;The width of the image */
uint32_t u32Height; /* RW;The height of the image */
uint32_t u32AlignHeight;
uint32_t u32Size;
void* reserve;
}NPU_IMAGE_S;
typedef struct MCV_ALGORITHM_RESULT_ST {
uint64_t frame_id;
uint32_t object_size;
uint32_t bind_size;
uint32_t cache_list_size;
// the size of the original received image
uint32_t original_width;
uint32_t original_height;
// the size of the algorithm processe image
uint32_t processed_width;
uint32_t processed_height;
// other kind result, data transmission
uint32_t meta_info_size;
void *user_data; // user data
int reserved[15]; // reserved
} MCV_ALGORITHM_RESULT_S;
typedef struct FRAME_ALGORITHM_RESULT_ST
{
NPU_IMAGE_S* npu_image;
MCV_ALGORITHM_RESULT_S* palgorithm_result;
}FRAME_ALGORITHM_RESULT_S;
typedef HASHMAP(char, FRAME_ALGORITHM_RESULT_S) algo_std_map;
typedef struct FRAME_DATA_MAP_ST{
pthread_mutex_t *map_data_result_lock;
algo_std_map *map_data_result;
}FRAME_DATA_MAP_S;
static algo_std_map g_mapFaceDataResult;
static pthread_mutex_t g_mapFaceDataResultLock = PTHREAD_MUTEX_INITIALIZER;
static void hashmap_dump(algo_std_map *map, const char *label)
{
DEBUG("Hashmap stats: %s\n", label);
DEBUG(" # entries: %zu\n", hashmap_size(map));
DEBUG(" Table size: %zu\n", map->map_base.table_size);
DEBUG(" Load factor: %.4f\n", hashmap_load_factor(map));
DEBUG(" Collisions mean: %.4f\n", hashmap_collisions_mean(map));
DEBUG(" Collisions variance: %.4f\n", hashmap_collisions_variance(map));
const char *key = NULL;
const char *temp = NULL;
FRAME_ALGORITHM_RESULT_S *p_frame_algo_result = NULL;
hashmap_foreach_safe(key, p_frame_algo_result, map, temp)
{
if (hashmap_get(map, key) != p_frame_algo_result)
{
ERROR("invalid iterator, key is %s.\n", key);
continue;
}
DEBUG("dump key is %s\n", key);
}
}
static void* send_data_thread(void *lparam)
{
uint64_t frame_id = 0;
while (1)
{
NPU_IMAGE_S *npu_image = NULL;
npu_image = (NPU_IMAGE_S *)calloc(1, sizeof(NPU_IMAGE_S));
if (NULL == npu_image)
{
SYSERR("Fail to calloc npu_image.\n");
usleep(100*1000);
continue;
}
npu_image->u32Width = frame_id * 10;
npu_image->u32Height = frame_id * 5;
int hashmap_ret = -1;
char key_str[32] = {0};
FRAME_ALGORITHM_RESULT_S *pstAlgorithmResult = NULL;
pstAlgorithmResult = (FRAME_ALGORITHM_RESULT_S *)calloc(1, sizeof(FRAME_ALGORITHM_RESULT_S));
if (pstAlgorithmResult)
{
pthread_mutex_lock(&g_mapFaceDataResultLock);
pstAlgorithmResult->npu_image = npu_image;
pstAlgorithmResult->palgorithm_result = NULL;
snprintf(key_str, sizeof(key_str), "%llu", frame_id++);
hashmap_ret = hashmap_put(&g_mapFaceDataResult, key_str, (void*)pstAlgorithmResult);
if (hashmap_ret < 0)
{
ERROR("Fail to called hashmap_put, key is %s, because of %s.\n", key_str, strerror(-hashmap_ret));
free(npu_image);
free(pstAlgorithmResult);
}
else
{
DEBUG("input: key:%s - pstAlgorithmResult:%p, npu_image:%p, map size %d.\n",
key_str, pstAlgorithmResult, pstAlgorithmResult->npu_image, hashmap_size(&g_mapFaceDataResult));
}
pthread_mutex_unlock(&g_mapFaceDataResultLock);
}
usleep(100*1000);
}
return NULL;
}
static void* recv_data_thread(void *lparam)
{
while (1)
{
pthread_mutex_lock(&g_mapFaceDataResultLock);
const void *temp = NULL;
const char *key = NULL;
void *data = NULL;
FRAME_ALGORITHM_RESULT_S *pframe_algorithm_result = NULL;
INFO("hashmap_size is %d.\n", hashmap_size(&g_mapFaceDataResult));
hashmap_foreach_safe(key, pframe_algorithm_result, &g_mapFaceDataResult, temp)
{
data = NULL;
data = hashmap_get(&g_mapFaceDataResult, key);
if (data != pframe_algorithm_result)
{
ERROR("invalid iterator, data = %p, pframe_algorithm_result=%p.\n",
data, pframe_algorithm_result);
continue;
}
printf("--------------------------------------------------------");
hashmap_dump(&g_mapFaceDataResult, __FUNCTION__);
DEBUG("found it, key is %s.\n", key);
printf("--------------------------------------------------------");
}
pthread_mutex_unlock(&g_mapFaceDataResultLock);
usleep(500*1000);
}
return NULL;
}
int main(int argc, const char *argv[])
{
pthread_t send_pid = -1;
pthread_t recv_pid = -1;
hashmap_init(&g_mapFaceDataResult, hashmap_hash_string, strcmp);
pthread_create(&send_pid, NULL, send_data_thread, NULL);
pthread_create(&recv_pid, NULL, recv_data_thread, NULL);
while(1);
return 0;
}
I need to run this lib in sgx. But sgx do not support __assert_fail. So I need to make in no debug mode.
Please help. Thanks
I'm trying to upgrade my project to the latest version of your hashmap (previously using version 2016-2018) , but after rewriting all instances to include new syntax, I'm running into multiple errors at compile time that basically seem to reduce to:
error: ‘typeof’ was not declared in this scope
Searching the internet seems to indicate that this is a GNU extension to C that doesn't work well with C++. This is a mixed C/C++ project. Is there anything I can do?
Please add
Can you provide an interface "hashmap_set" for modifying the key, the function is to add the key if it does not exist, and modify it if it exists. Thank you so much.
I have using this ~6 months now and quality is great so im asking about considering adding it to clib packages list as clib still dont have any type templated hashmap implementation yet
Because of the type of the free function this takes the most common use case of just passing 'free' produces a warning
Incompatible function pointer types initializing 'typeof (((&skined_anim_mngr.map))->map_types->t_key_free_func)' (aka 'void (*)(char *)') with an expression of type 'void (void *)'
Therefore wouldn't it make sense to change the type to void free(char *) ?
Reimplementing the library I noticed that the foreach declared int the header file discard a 'const' quilifier
warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
((key) = hashmap_iter_get_key(&__HASHMAP_UNIQUE(x, it))) &&
note: in expansion of macro ‘__HASHMAP_FOREACH’
#define hashmap_foreach(key, data, h) __HASHMAP_FOREACH(__HASHMAP_MAKE_UNIQUE(__map), (key), (data), (h))
It happens both with the normal and safe foreach, so I suppose it should happen also with those that iterate over keys and values. Does someone understand the problem better than I do?
Thanks!
When using hashmap_foreach、hashmap_foreach_safe, the compiler gives a warning,
Declaration of non-local variable in 'for' loop。
After creating a hashmap the hb->table pointer is null. Any operation will produce memory errors due to this. calling hashmap_reserve will result in a memory error due to the null pointer.
hashmap_rehash() will produce a memory error because of applying an offset to the null pointer.
Hi, I'm trying to use this hashmap as a global variable but I can't figure out how the variable can be seen outside of the scope of where it's declared. I've loaded the hashmap correctly:
(gdb) p map $499 = {map_base = {table_size_init = 128, table_size = 2048, size = 1466, table = 0x555558c909b0, hash = 0x55555556a12f <hashmap_hash_string>, compare = 0x7ffff70a9c50, key_dup = 0x0, key_free = 0x0}, map_types = 0x7fffffffb550}
But when I enter into a function, the map has a different address and is empty:
(gdb) p map $501 = (struct hashmap_base *) 0x0
The struct also seems to be different and the two maps have different addresses. I've used the macro HASHMAP in the main function because I couldn't get the program to compile using a typedef
in the header file. Any ideas on how I can get this to work?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.