ZBLOG

redis太大了,请使用C语言给出一个性能好、稳定性高,稍微简单一点的缓存代码。需求是存储变长的数据,支持多线程,即需要支持多线程安全耽误进行读写操作

当然可以!下面是一个使用 C 语言实现的简单线程安全的缓存库示例。这个实现利用了互斥锁来确保多线程环境下的安全性,支持变长数据存储。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define CACHE_SIZE 1024

typedef struct CacheItem {
    char *key;
    char *value;
    size_t value_len;
    struct CacheItem *next;
} CacheItem;

typedef struct {
    CacheItem **items;
    size_t size;
    pthread_mutex_t lock;
} Cache;

Cache* create_cache(size_t size) {
    Cache *cache = (Cache *)malloc(sizeof(Cache));
    cache->size = size;
    cache->items = (CacheItem **)calloc(size, sizeof(CacheItem *));
    pthread_mutex_init(&cache->lock, NULL);
    return cache;
}

unsigned long hash(const char *key) {
    unsigned long hash = 5381;
    int c;

    while ((c = *key++)) {
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }
    
    return hash;
}

void cache_set(Cache *cache, const char *key, const char *value, size_t value_len) {
    unsigned long index = hash(key) % cache->size;

    pthread_mutex_lock(&cache->lock);

    // Create a new item
    CacheItem *new_item = (CacheItem *)malloc(sizeof(CacheItem));
    new_item->key = strdup(key);
    new_item->value_len = value_len;
    
	// Allocate memory for the variable-length data
	new_item->value = (char *)malloc(value_len);
	memcpy(new_item->value, value, value_len);
	
	// Insert it into the linked list at this index
	new_item->next = cache->items[index];
	cache->items[index] = new_item;

	pthread_mutex_unlock(&cache->lock);
}

char* cache_get(Cache *cache, const char *key, size_t *out_value_len) {
	unsigned long index = hash(key) % cache->size;

	pthread_mutex_lock(&cache->lock);

	CacheItem *item = cache->items[index];
	while (item != NULL) {
        if (strcmp(item->key, key) == 0) {
            pthread_mutex_unlock(&cache->lock);
            if(out_value_len)
                *out_value_len=item->value_len; // Return the length of the value
            return item->value; // Return the found value
        }
        item = item->next;
	}

	pthread_mutex_unlock(&cache->lock);
	return NULL; // Not found
}

// Free allocated memory in the cache and its items.
void free_cache(Cache* cache){
	for(size_t i=0;i<cache->size;i++){
		CacheItem* item=cache->items[i];
		while(item!=NULL){
			CacheItem* tmp=item;
			item=item->next;
			free(tmp -> key); // free the key string
			free(tmp -> value); // free the variable-length data
			free(tmp); 
		}
	}
	free(cache -> items);
	pthread_mutex_destroy(&cache -> lock); 
	free(cache);  
}

int main() {
   Cache* my_cache=create_cache(CACHE_SIZE);

   const char* key="test_key";
   const char* value="Hello World!";
   
   printf("Setting key: %s with value: %s\n", key,value);
   cache_set(my_cache,key,value,strlen(value)+1); 

   size_t len=0; 
   char* result=cache_get(my_cache,key,&len); 

   if(result){
	   printf("Retrieved from cache: %s\n",result); 
       printf("Length of retrieved data is: %zu\n", len-1 );// Subtracting one to exclude null terminator 
   }else{
	   printf("Key not found.\n"); 
   }

   free_cache(my_cache);

   return 0;  
}

功能说明:

  • create_cache: 创建一个缓存,初始化大小和互斥锁。
  • hash: 简单的哈希函数,用于计算键值对在数组中的索引。
  • cache_set: 设置缓存项,并保证多线程安全。
  • cache_get: 从缓存中获取项,同样保证多线程安全。
  • free_cache: 清理内存,以防止内存泄漏。

注意事项:

  1. 使用时请确保适当管理内存,避免内存泄漏。
  2. 实际应用中可能需要更复杂的错误处理逻辑。
  3. 根据需要可扩展功能,例如添加过期时间等特性。

这是一个简单的示例,如果需要更复杂或特定功能,可以根据需求进行进一步扩展。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=20308

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?