コード例 #1
0
ファイル: skynet_handle.c プロジェクト: Abyss116/skynet
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;
	}
}
コード例 #2
0
ファイル: skynet_handle.c プロジェクト: EtcDot/skynet
// 注册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;
	}
}