ConcurrentHashMap provided by FAST Kit is specifically designed for key-value data management in high-concurrency scenarios. It is primarily designed for secure storage, fast access, and efficient updates in a multithreaded environment. It is suitable for create, read, update, and delete (CRUD) operations that require high concurrent throughput and data consistency. Typical scenarios include single-point insertion, deletion, query, and concurrent modifications.
For details about the APIs, please refer to the API Reference.
| API | Description |
|---|---|
| FAST_ErrorCode HMS_FAST_ConcurrentHashmap_Create (FAST_ConcurrentHashmapHandle* handle, HMS_FAST_ConcurrentHashmap_HashFunc hasher, HMS_FAST_ConcurrentHashmap_KeyEqualFunc equaler, float maxLoadFac, size_t numShards) | Creates a ConcurrentHashMap with the given configuration. |
| void HMS_FAST_ConcurrentHashmap_Destroy (FAST_ConcurrentHashmapHandle* handle) | Destroys a specified ConcurrentHashMap. |
| FAST_ErrorCode HMS_FAST_ConcurrentHashmap_Insert (FAST_ConcurrentHashmapHandle* handle, const FAST_ConcurrentHashmapKeyPtr key, const FAST_ConcurrentHashmapValuePtr value, FAST_ConcurrentHashmapValuePtr* originValue) | Inserts a given key-value pair into a ConcurrentHashMap. If the key already exists, the existing value is overwritten with value, and the address of the original value is stored in originValue. |
| FAST_ErrorCode HMS_FAST_ConcurrentHashmap_Find (FAST_ConcurrentHashmapHandle* handle, const FAST_ConcurrentHashmapKeyPtr key, FAST_ConcurrentHashmapValuePtr* value) | Searches for the input key in a given ConcurrentHashMap and saves the corresponding value into value. |
| FAST_ErrorCode HMS_FAST_ConcurrentHashmap_Erase (FAST_ConcurrentHashmapHandle* handle, const FAST_ConcurrentHashmapKeyPtr key, FAST_ConcurrentHashmapKeyPtr* originKey, FAST_ConcurrentHashmapValuePtr* originValue) | Deletes the input key from the given HashMap and saves the addresses of the corresponding key and value into originKey and originValue, respectively. |
| FAST_ErrorCode HMS_FAST_ConcurrentHashmap_TryInsert (FAST_ConcurrentHashmapHandle* handle, const FAST_ConcurrentHashmapKeyPtr key, const FAST_ConcurrentHashmapValuePtr value) | Inserts a given key-value pair into a ConcurrentHashMap. If the key already exists, no operation is performed. |
| size_t HMS_FAST_ConcurrentHashmap_Size (FAST_ConcurrentHashmapHandle* handle) | Returns the number of elements in a given HashMap. |
| void HMS_FAST_ConcurrentHashmap_Clear (FAST_ConcurrentHashmapHandle* handle) | Clears all elements maintained in a given HashMap. |
| size_t HMS_FAST_ConcurrentHashmap_EraseIf (FAST_ConcurrentHashmapHandle* handle, HMS_FAST_ConcurrentHashmap_HookFunc condFunc, void* condCtx, HMS_FAST_ConcurrentHashmap_HookFunc freeFunc, void* freeCtx) | Deletes all elements that meet the developer-defined conditions from the HashMap and releases the memory in the developer-defined manner. |
| void HMS_FAST_ConcurrentHashmap_Traverse (FAST_ConcurrentHashmapHandle* handle, HMS_FAST_ConcurrentHashmap_HookFunc condFunc, void* condCtx, HMS_FAST_ConcurrentHashmap_HookFunc workFunc, void* workCtx) | Traverses the HashMap and modifies all key-value pairs that meet the developer-defined conditions in the developer-defined manner. |
Link the related dynamic library in the CMake script.
find_library(
lib_fast_ads
NAMES fast_ads
)
target_link_libraries(entry PRIVATE ${lib_fast_ads}) Call related APIs to manage key-value information.
#include "FASTKit/fast_ads_concurrent_hashmap.h"
// Define how to calculate hash values and compare keys.
uint64_t custom_hash_int(const FAST_ConcurrentHashmapKeyPtr key) {
static std::hash<int> hasher;
int* intKey = (int*)key;
return hasher(*intKey);
}
int32_t custom_equal_int(const FAST_ConcurrentHashmapKeyPtr key1, const FAST_ConcurrentHashmapKeyPtr key2) {
int* intKey1 = (int*)key1;
int* intKey2 = (int*)key2;
return (*intKey1) == (*intKey2);
}
// Customize the deletion condition.
int32_t custom_erase_cond(FAST_ConcurrentHashmapKeyPtr key, FAST_ConcurrentHashmapValuePtr val, void* context) {
return 1;
}
// Free the memory held by the key and value pointers.
int32_t custom_free(FAST_ConcurrentHashmapKeyPtr key, FAST_ConcurrentHashmapValuePtr val, void* context) {
int* intKey = (int*)key;
int* intVal = (int*)val;
delete intKey;
delete intVal;
return 0;
}
// Customize the modification condition. You can also pass nullptr to modify all elements.
int32_t custom_modify_cond(FAST_ConcurrentHashmapKeyPtr key, FAST_ConcurrentHashmapValuePtr val, void* context) {
return 1;
}
int32_t custom_work(FAST_ConcurrentHashmapKeyPtr key, FAST_ConcurrentHashmapValuePtr val, void* context) {
int* intVal = (int*)val;
int* intCtx = (int*)context;
*intVal += (*intCtx);
return 1;
}
static napi_value RunConcurrentHashmap(napi_env env, napi_callback_info info)
{
// Create a ConcurrentHashMap with proper configurations. The typical values of the load factor (loadfac) and the number of segments (numShards) are 0.8 and 64, respectively.
// The load factor mainly affects operations within each segment. A larger load factor usually results in lower memory consumption but higher operational overhead.
// The number of segments mainly affects the ConcurrentHashMap as a whole. A larger number of segments generally means better concurrency performance but greater memory consumption.
FAST_ConcurrentHashmapHandle handle;
HMS_FAST_ConcurrentHashmap_HashFunc hasher = &custom_hash_int;
HMS_FAST_ConcurrentHashmap_KeyEqualFunc equaler = &custom_equal_int;
float loadfac = 0.8;
size_t numShards = 64;
int ret = HMS_FAST_ConcurrentHashmap_Create(&handle, hasher, equaler, loadfac, numShards);
// Initialize an empty HashMap and insert elements into it.
const int size = 10;
int keys[size] = {1,2,3,4,5,6,7,8,9,10};
int vals[size] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < size; ++i) {
ret = HMS_FAST_ConcurrentHashmap_Insert(
handle,
(FAST_ConcurrentHashmapKeyPtr)&(keys[i]),
(FAST_ConcurrentHashmapValuePtr)&(vals[i]),
nullptr
);
} // After the insertion, the HashMap should contain {1: 1, 2: 2, ..., 10: 10}.
// Use insert to overwrite the existing key. If tryInsert is used, the existing key will not be overwritten.
int key2 = 1;
int val2 = 2;
int* originVal0;
ret = HMS_FAST_ConcurrentHashmap_Insert(
handle,
(FAST_ConcurrentHashmapKeyPtr)&key2,
(FAST_ConcurrentHashmapValuePtr)&val2,
(FAST_ConcurrentHashmapValuePtr*)&originVal0
); // {1: 2, ...}, and originVal0 == &vals[0]
// Use the key to search for the corresponding value and save the result in the input pointer. When using this API, you need to verify the return value ret.
// If the value of ret is not FAST_ERROR_CODE_SUCCESS, the value obtained by res is invalid.
int targetKey = 1;
int* res;
ret = HMS_FAST_ConcurrentHashmap_Find(
handle,
(FAST_ConcurrentHashmapKeyPtr)&targetKey,
(FAST_ConcurrentHashmapValuePtr*)&res
); // (*res) == 2
// Remove the key-value pair associated with the key from the ConcurrentHashMap and retrieve the associated memory addresses.
// You can use originKey/Val to obtain the address of the pre-inserted element for memory management. You can also use nullptr as the input parameter.
int* originKey1;
int* originVal1;
int deleteKey = 1;
ret = HMS_FAST_ConcurrentHashmap_Erase(
handle,
(FAST_ConcurrentHashmapKeyPtr)&deleteKey,
(FAST_ConcurrentHashmapKeyPtr*)&originKey1,
(FAST_ConcurrentHashmapValuePtr*)&originVal1
); // originKey1 == &keys[0] && originVal1 == &val2
// Query the number of elements in the ConcurrentHashMap.
size_t curSize = HMS_FAST_ConcurrentHashmap_Size(handle); // curSize == 9
// Clear all elements in the ConcurrentHashMap.
HMS_FAST_ConcurrentHashmap_Clear(handle);
curSize = HMS_FAST_ConcurrentHashmap_Size(handle); // curSize == 0
for (int i = 0; i < 6; i++) {
int* key = new int{i};
int* val = new int{i};
ret = HMS_FAST_ConcurrentHashmap_Insert(
handle,
(FAST_ConcurrentHashmapKeyPtr)key,
(FAST_ConcurrentHashmapValuePtr)val,
nullptr
);
} // {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
// Use the Traverse API to perform the custom_work operation on the elements that meet the custom_modify_cond condition.
int context = 10;
HMS_FAST_ConcurrentHashmap_Traverse(
handle,
(HMS_FAST_ConcurrentHashmap_HookFunc)&custom_modify_cond,
nullptr,
(HMS_FAST_ConcurrentHashmap_HookFunc)&custom_work,
(void*)&context
); // {0: 10, 1: 11, 2: 12, 3: 13, 4: 14, 5: 15}
// Use the EraseIf API to delete all key-value pairs that meet the custom_erase_cond condition and use custom_free to clear the corresponding memory.
ret = HMS_FAST_ConcurrentHashmap_EraseIf(
handle,
(HMS_FAST_ConcurrentHashmap_HookFunc)&custom_erase_cond,
nullptr,
(HMS_FAST_ConcurrentHashmap_HookFunc)&custom_free,
nullptr
); // size == 0 && ret == 6
// Destroy the ConcurrentHashMap.
HMS_FAST_ConcurrentHashmap_Destroy(handle);
return 0;
}