帮朋友写的, 很简单...
还是贴出来, 希望能对看客有所帮助, 也希望看客能对我有所帮助...
谢谢.
#include <stdio.h> #include <stdlib.h> /** * author: selfimpr * blog: http://blog.csdn.net/lgg201 * mail: [email protected] */ struct UserPool { struct User *head; /* 所分配存储空间首指针 */ struct User *useable; /* 当前未使用的存储空间首指针 */ struct User *free; /* 空闲链表首指针 */ int used; /* 内存池中已在线的用户数 */ int alloced; /* 分配的内存池大小 */ }; /* 用户内存池 */ struct User { int uid; /* 用户标识 */ int fd; /* 文件描述符 */ struct Map *map_p; /* 所在地图 */ int map_i; /* 在所在地图用户数组中的下标 */ struct User *next; /* 作为内存池空闲链表时的构造指针 */ struct UserPool *pool; /* 所在内存池 */ int isfree; /* 是否空闲(1表示用户已离线, 空间可重用) */ int pool_i; /* 在内存池中的下标 */ }; /* 用户 */ struct Map { struct User **users; /* 用户数组 */ int alloced; /* 已分配用户数组大小 */ int used; /* 已使用用户数组大小 */ }; /* 地图 */ struct HashTableElement { unsigned int key; /* 键 */ void *value; /* 值 */ struct HashTableElement *next; /* 下一个节点 */ }; /* 哈希表元素 */ struct HashTable { struct HashTableElement *elements; /* 存储数据的链表数组 */ unsigned int size; /* 哈希表大小 */ }; /* 哈希表 */ /* 创建哈希表 */ struct HashTable *hash_table_create(unsigned int size) { struct HashTable *ht; ht = (struct HashTable *)malloc(sizeof(struct HashTable)); if ( ht == NULL ) goto failed; ht->size = size; ht->elements = (struct HashTableElement *)calloc(size, sizeof(struct HashTableElement)); if ( ht->elements == NULL ) goto failed; return ht; failed: printf("hash_table_create failed\n"); if ( ht != NULL ) { if ( ht->elements != NULL ) free(ht->elements); free(ht); } return NULL; } /* 向哈希表中写入或更新数据 */ int hash_table_add_or_update(struct HashTable *ht, unsigned int k, void *value) { struct HashTableElement *h, *e, *n; h = &(ht->elements[k % ht->size]); e = h->next; if ( e == NULL ) { e = h; goto insert; } do { if ( e->key == k ) goto update; else e = e->next; } while ( e->next != NULL ); insert: n = (struct HashTableElement *)calloc(1, sizeof(struct HashTableElement)); n->key = k; n->value = value; e->next = n; return (0); update: e->value = value; return (0); } /* 在哈希表中查找数据 */ struct HashTableElement *hash_table_find(struct HashTable *ht, unsigned int k) { struct HashTableElement *h, *e; h = &(ht->elements[k % ht->size]); e = h->next; if ( e == NULL ) goto failed; do { if ( e->key == k ) return e; else e = e->next; } while ( e != NULL ); failed: return NULL; } /* 从哈希表中删除数据 */ int hash_table_delete(struct HashTable *ht, unsigned int k) { struct HashTableElement *p, *e; p = &(ht->elements[k % ht->size]); e = p->next; if ( e == NULL ) goto failed; do { if ( e->key == k ) { p->next = e->next; free(e); return (0); } else { p = e; e = e->next; } } while ( e != NULL ); failed: return (-1); } /* 输出哈希表数据 */ void hash_table_dump(struct HashTable *ht, char *(*to_string)(void *)) { int i; struct HashTableElement *h, *e; for ( i = 0; i < ht->size; i ++ ) { h = &(ht->elements[i]); e = h->next; while ( e != NULL ) { printf("%d: %s\n", e->key, to_string(e->value)); e = e->next; } } } /* 用于哈希表测试用例的字符串转换函数 */ char *empty_to_string(void *v) { return (char *)v; } /* 哈希表测试用例 */ void hash_table_test() { struct HashTable *ht; ht = hash_table_create((unsigned int)30); hash_table_add_or_update(ht, 1, (void *)"one"); hash_table_add_or_update(ht, 2, (void *)"two"); hash_table_add_or_update(ht, 3, (void *)"three"); hash_table_add_or_update(ht, 4, (void *)"four"); hash_table_add_or_update(ht, 1, (void *)"first-one"); hash_table_add_or_update(ht, 2, (void *)"second-two"); hash_table_add_or_update(ht, 3, (void *)"third-three"); hash_table_add_or_update(ht, 4, (void *)"forth-four"); hash_table_delete(ht, 3); hash_table_dump(ht, empty_to_string); } /* 地图创建 */ struct Map *map_create(int num) { struct Map *map; map = (struct Map *) malloc(sizeof(struct Map)); if ( map == NULL ) goto failed; map->users = (struct User **) calloc(num, sizeof(struct User *)); map->alloced = num; map->used = 0; return map; failed: if ( map != NULL ) free(map); return NULL; } /* 用户进入地图 */ int map_user_enter(struct Map *map, struct User *user) { int i; for ( i = 0; i < map->alloced; i ++ ) { if ( map->users[i] == NULL ) { map->users[i] = user; user->map_p = map; user->map_i = i; map->used ++; return (0); } } return (-1); } /* 用户离开地图 */ int map_user_leave(struct User *user) { user->map_p->users[user->map_i] = NULL; user->map_p->used --; user->map_i = 0; user->map_p = NULL; } /* 创建用户内存池 */ struct UserPool *user_pool_create(int size) { struct UserPool *pool; pool = (struct UserPool *)malloc(sizeof(struct UserPool)); pool->head = (struct User *)calloc(size, sizeof(struct User)); pool->useable = pool->head; pool->free = NULL; pool->alloced = size; pool->used = 0; return (pool); failed: if ( pool != NULL ) { if ( pool->head != NULL ) free(pool->head); free(pool); } return (NULL); } /* 从内存池分配一个用户的空间 */ struct User *user_pool_alloc_user(struct UserPool *pool) { struct User *u; /* TODO 此处应该是内存池扩展逻辑, 比较复杂, 未实现 */ /* 从空闲链表中分配 */ if ( pool->free != NULL ) { u = pool->free; u->isfree = 0; pool->free = pool->free->next; pool->used ++; return u; } /* 从未使用空间中分配 */ u = pool->useable; u->pool = pool; u->pool_i = pool->useable - pool->head; pool->useable ++; pool->used ++; return u; } /* 从内存池中释放一个用户 */ void user_pool_free_user(struct User *user) { struct UserPool *pool; pool = user->pool; user->isfree = 1; /* 将被释放的空间放入空闲链表 */ user->next = pool->free; pool->free = user; /* 更新用户计数 */ pool->used --; } struct Map **maps; /* 所有的地图 */ struct HashTable *user_ht; /* 用户哈希表 */ struct UserPool *user_pool; /* 用户内存池 */ /* 地图数量 */ int map_num = 1; /* 地图最大人数 */ int map_user_num = 10; /* 总人数上限 */ int user_num = 100; /* 游戏初始化 */ int game_init() { int i; /* 地图初始化 */ maps = (struct Map **)calloc(map_num, sizeof(struct Map *)); for ( i = 0; i < map_num; i ++ ) { maps[i] = map_create(map_user_num); } /* 用户存储初始化 */ user_pool = user_pool_create(user_num); /* 用户哈希表初始化 */ user_ht = hash_table_create(user_num); } /* 用户登入 */ void user_login(int uid, int fd) { struct User *user; /* 在内存池中为用户分配空间 */ user = user_pool_alloc_user(user_pool); /* 初始化用户基本信息 */ user->uid = uid; user->fd = fd; /* 用户进入地图 */ map_user_enter(maps[0], user); /* 将用户放入哈希表便于查找 */ hash_table_add_or_update(user_ht, uid, (void *)user); } /* 用户登出 */ void user_logout(int uid) { struct HashTableElement *e; struct User *user; /* 从哈希表中查找用户 */ e = (struct HashTableElement *)hash_table_find(user_ht, uid); user = (struct User *)e->value; /* 用户离开地图 */ map_user_leave(user); /* 从内存池中释放用户 */ user_pool_free_user(user); /* 从哈希表中移除用户 */ hash_table_delete(user_ht, uid); } /* 将用户转换为字符串 */ char *user_to_string(void *value) { static char buffer[1024]; struct User *user; user = (struct User *)value; sprintf(buffer, "uid: %d, fd: %d, map_p: %p, map_i: %d, pool: %p, pool_i: %d, ptr: %p, next: %p", user->uid, user->fd, user->map_p, user->map_i, user->pool, user->pool_i, user, user->next); return buffer; } int main(int argc, char *argv[]) { /* 初始化游戏 */ game_init(); int i; struct User *tmp; /* 登入十个用户 */ for ( i = 1; i <= 10; i ++ ) user_login(i, i); /* 登出三个用户 */ user_logout(2); user_logout(3); user_logout(4); /* 打印在线用户信息 */ hash_table_dump(user_ht, user_to_string); /* 打印用户内存池的空闲链表 */ printf("\nfree elements:\n"); for ( tmp = user_pool->free; tmp != NULL; tmp = tmp->next ) printf("%s\n", user_to_string((void *)tmp)); }