帮朋友写的, 很简单...
还是贴出来, 希望能对看客有所帮助, 也希望看客能对我有所帮助...
谢谢.
#include <stdio.h>
#include <stdlib.h>
/**
* author: selfimpr
* blog: http://blog.csdn.net/lgg201
* mail: lgg860911@yahoo.com.cn
*/
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));
}