uint32_t skynet_handle_register(struct skynet_context *ctx) { struct handle_storage *s = H; rwlock_wlock(&s->lock); for (;;) { int i; for (i=0;i<s->slot_size;i++) { uint32_t handle = (i+s->handle_index) & HANDLE_MASK; int hash = handle & (s->slot_size-1); if (s->slot[hash] == NULL) { s->slot[hash] = ctx; s->handle_index = handle + 1; rwlock_wunlock(&s->lock); handle |= s->harbor; skynet_context_init(ctx, handle); return handle; } } assert((s->slot_size*2 - 1) <= HANDLE_MASK); struct skynet_context ** new_slot = malloc(s->slot_size * 2 * sizeof(struct skynet_context *)); memset(new_slot, 0, s->slot_size * 2 * sizeof(struct skynet_context *)); for (i=0;i<s->slot_size;i++) { int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1); assert(new_slot[hash] == NULL); new_slot[hash] = s->slot[i]; } free(s->slot); s->slot = new_slot; s->slot_size *= 2; } }
// 注册ctx,将 ctx 存到 handle_storage 哈希表中,并得到一个handle uint32_t skynet_handle_register(struct skynet_context *ctx) { struct handle_storage *s = H; rwlock_wlock(&s->lock); for (;;) { int i; for (i=0; i<s->slot_size; i++) { uint32_t handle = (i+s->handle_index) & HANDLE_MASK; int hash = handle & (s->slot_size-1); // 等价于 handle % s->slot_size if (s->slot[hash] == NULL) { // 找到未使用的 slot 将这个 ctx 放入这个 slot 中 s->slot[hash] = ctx; s->handle_index = handle + 1; // 移动 handle_index 方便下次使用 rwlock_wunlock(&s->lock); handle |= s->harbor; // harbor 用于不同主机间的通信 handle高8位用于harbor 低24位用于本机的 所以这里需要 |= 下 skynet_context_init(ctx, handle); // 设置 ctx->handle = handle; 即这个 ctx 的 handle return handle; } } assert((s->slot_size*2 - 1) <= HANDLE_MASK); // 确保 扩大2倍空间后 总共handle即 slot的数量不超过 24位的限制 // 哈希表扩大2倍 struct skynet_context ** new_slot = malloc(s->slot_size * 2 * sizeof(struct skynet_context *)); memset(new_slot, 0, s->slot_size * 2 * sizeof(struct skynet_context *)); // 将原来的数据拷贝到新的空间 for (i=0;i<s->slot_size;i++) { int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1); // 映射新的 hash 值 assert(new_slot[hash] == NULL); new_slot[hash] = s->slot[i]; } free(s->slot); // free old mem s->slot = new_slot; s->slot_size *= 2; } }