コード例 #1
0
ファイル: skynet_handle.c プロジェクト: EtcDot/skynet
// 收回handle
void
skynet_handle_retire(uint32_t handle) {
	struct handle_storage *s = H;

	rwlock_wlock(&s->lock);

	uint32_t hash = handle & (s->slot_size-1); // 等价于  handle % s->slot_size
	struct skynet_context * ctx = s->slot[hash];

	if (ctx != NULL && skynet_context_handle(ctx) == handle) {
		skynet_context_release(ctx); // free skynet_ctx
		s->slot[hash] = NULL;		// 置空,哈希表腾出空间

		int i;
		int j=0,
			n=s->name_count;
		for (i=0; i<n; ++i) {
			if (s->name[i].handle == handle) { // 在 name 表中 找到 handle 对应的 name free掉
				free(s->name[i].name);
				continue;
			} else if (i!=j) {	// 说明free了一个name
				s->name[j] = s->name[i];	// 因此需要将后续元素移到前面
			}
			++j;
		}
		s->name_count = j;
	}

	rwlock_wunlock(&s->lock);
}
コード例 #2
0
ファイル: skynet_multicast.c プロジェクト: fangtong/skynet
int 
skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg) {
	combine_queue(from, group);
	int release = 0;
	if (group->number > 0) {
		uint32_t source = skynet_context_handle(from);
		skynet_multicast_copy(msg, group->number);
		int i;
		for (i=0;i<group->number;i++) {
			uint32_t p = group->data[i];
			struct skynet_context * ctx = skynet_handle_grab(p);
			if (ctx) {
				skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
				skynet_context_release(ctx);
			} else {
				skynet_multicast_leavegroup(group, p);
				++release;
			}
		}
	}
	
	skynet_multicast_copy(msg, -release);
	
	return group->number - release;
}
コード例 #3
0
ファイル: skynet_handle.c プロジェクト: Abyss116/skynet
void
skynet_handle_retire(uint32_t handle) {
	struct handle_storage *s = H;

	rwlock_wlock(&s->lock);

	uint32_t hash = handle & (s->slot_size-1);
	struct skynet_context * ctx = s->slot[hash];

	if (ctx != NULL && skynet_context_handle(ctx) == handle) {
		skynet_context_release(ctx);
		s->slot[hash] = NULL;
		int i;
		int j=0, n=s->name_count;
		for (i=0; i<n; ++i) {
			if (s->name[i].handle == handle) {
				free(s->name[i].name);
				continue;
			} else if (i!=j) {
				s->name[j] = s->name[i];
			}
			++j;
		}
		s->name_count = j;
	}

	rwlock_wunlock(&s->lock);
}
コード例 #4
0
ファイル: skynet_multicast.c プロジェクト: eguopt/skynet
int 
skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg) {
	combine_queue(from, group);
	if (group->number == 0) {
		skynet_multicast_dispatch(msg, NULL, NULL);
		return 0;
	}
	uint32_t source = skynet_context_handle(from);
	skynet_multicast_copy(msg, group->number);
	int i;
	int release = 0;
	for (i=0;i<group->number;i++) {
		struct pair * p = &group->data[i];
		skynet_context_send(p->ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
		int ref = skynet_context_ref(p->ctx);
		if (ref == 1) {
			skynet_context_release(p->ctx);
			struct skynet_context * ctx = skynet_handle_grab(p->handle);
			if (ctx == NULL) {
				p->ctx = NULL;
				skynet_multicast_leavegroup(group, p->handle);
				++release;
			}
		}
	}
	
	return group->number - release;
}
コード例 #5
0
ファイル: skynet_harbor.c プロジェクト: peerswu/Jump
void skynet_harbor_exit()
{
	struct skynet_context * ctx = REMOTE;
	REMOTE = NULL;
	if (ctx)
	{
		skynet_context_release(ctx);
	}
}
コード例 #6
0
ファイル: skynet_multicast.c プロジェクト: eguopt/skynet
void 
skynet_multicast_deletegroup(struct skynet_multicast_group * g) {
	int i;
	for (i=0;i<g->number;i++) {
		if (g->data[i].ctx) {
			skynet_context_release(g->data[i].ctx);
		}
	}
	free(g->data);
	free(g->enter_queue.data);
	free(g->leave_queue.data);
	free(g);
}
コード例 #7
0
ファイル: skynet_handle.c プロジェクト: KAndQ/skynet
int
skynet_handle_retire(uint32_t handle) {
	int ret = 0;
	struct handle_storage *s = H;

	// 其他线程不能同时写
	rwlock_wlock(&s->lock);

	// 获得索引
	uint32_t hash = handle & (s->slot_size - 1);
	struct skynet_context * ctx = s->slot[hash];

	if (ctx != NULL 
	// 1. 判断是否在同一个节点
	// 2. 确认 handle 是没有超出 slot_size 的, 因为可能 slot_size = 8, handle = 15, skynet_context_handle(ctx) = 7
	// 3. 其他线程没有修改 ctx
	&& skynet_context_handle(ctx) == handle) {
		s->slot[hash] = NULL;
		ret = 1;

		// 将关联注册的名字资源也一同释放掉
		int i;
		int j = 0, n = s->name_count;
		for (i = 0; i < n; ++i) {
			if (s->name[i].handle == handle) {	// 判断是否有注册名字
				skynet_free(s->name[i].name);	// 释放内存
				continue;						// 一个 handle 允许注册多个名字, 继续判断
			} else if (i != j) {
				// 向数组的头部移动
				s->name[j] = s->name[i];
			}
			++j;
		}

		// 更新当前注册了名字的 context 数量
		s->name_count = j;
	} else {
		ctx = NULL;
	}

	rwlock_wunlock(&s->lock);

	if (ctx) {
		// release ctx may call skynet_handle_* , so wunlock first.
		// 释放 ctx 可能会调用到 skynet_handle_* 方法, 所以先解 [写] 锁
		skynet_context_release(ctx);
	}

	return ret;
}
コード例 #8
0
ファイル: skynet_multicast.c プロジェクト: fangtong/skynet
void 
skynet_multicast_cast(struct skynet_context * from, struct skynet_multicast_message *msg, const uint32_t *dests, int n) {
	uint32_t source = skynet_context_handle(from);
	skynet_multicast_copy(msg, n);
	if (n == 0)
		return;
	int i;
	int release = 0;
	for (i=0;i<n;i++) {
		uint32_t p = dests[i];
		struct skynet_context * ctx = skynet_handle_grab(p);
		if (ctx) {
			skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
			skynet_context_release(ctx);
		} else {
			++release;
		}
	}

	skynet_multicast_copy(msg, -release);
}
コード例 #9
0
ファイル: skynet_handle.c プロジェクト: 249198000/skynet
int
skynet_handle_retire(uint32_t handle) {
	int ret = 0;
	struct handle_storage *s = H;

	rwlock_wlock(&s->lock);

	uint32_t hash = handle & (s->slot_size-1);
	struct skynet_context * ctx = s->slot[hash];

	if (ctx != NULL && skynet_context_handle(ctx) == handle) {
		s->slot[hash] = NULL;
		ret = 1;
		int i;
		int j=0, n=s->name_count;
		for (i=0; i<n; ++i) {
			if (s->name[i].handle == handle) {
				skynet_free(s->name[i].name);
				continue;
			} else if (i!=j) {
				s->name[j] = s->name[i];
			}
			++j;
		}
		s->name_count = j;
	} else {
		ctx = NULL;
	}

	rwlock_wunlock(&s->lock);

	if (ctx) {
		// release ctx may call skynet_handle_* , so wunlock first.
		skynet_context_release(ctx);
	}

	return ret;
}
コード例 #10
0
ファイル: skynet_multicast.c プロジェクト: eguopt/skynet
static void
combine_queue(struct skynet_context * from, struct skynet_multicast_group * group) {
	qsort(group->enter_queue.data, group->enter_queue.number, sizeof(uint32_t), compar_uint);
	qsort(group->leave_queue.data, group->leave_queue.number, sizeof(uint32_t), compar_uint);
	int i;
	int enter = group->enter_queue.number;
	uint32_t last = 0;

	int new_size = group->number + enter;
	if (new_size > group->cap) {
		group->data = realloc(group->data, new_size * sizeof(struct pair));
		group->cap = new_size;
	}

	// combine enter queue
	int old_index = group->number - 1;
	int new_index = new_size - 1;
	for (i= enter - 1;i >=0 ; i--) {
		uint32_t handle = group->enter_queue.data[i];
		if (handle == last)
			continue;
		last = handle;
		struct skynet_context * ctx = skynet_handle_grab(handle);
		if (ctx == NULL)
			continue;
		if (old_index < 0) {
			group->data[new_index].handle = handle;
			group->data[new_index].ctx = ctx;
		} else {
			struct pair * p = &group->data[old_index];
			if (handle == p->handle)
				continue;
			if (handle > p->handle) {
				group->data[new_index].handle = handle;
				group->data[new_index].ctx = ctx;
			} else {
				group->data[new_index] = group->data[old_index];
				--old_index;
				last = 0;
				++i;
			}
		}
		--new_index;
	}
	while (old_index >= 0) {
		group->data[new_index] = group->data[old_index];
		--old_index;
		--new_index;
	}
	group->enter_queue.number = 0;

	// remove leave queue
	old_index = new_index + 1;
	new_index = 0;

	int count = new_size - old_index;

	int leave = group->leave_queue.number;
	for (i=0;i<leave;i++) {
		if (old_index >= new_size) {
			count = 0;
			break;
		}
		uint32_t handle = group->leave_queue.data[i];
		struct pair * p = &group->data[old_index];
		if (handle == p->handle) {
			--count;
			++old_index;
			if (p->ctx) {
				skynet_context_release(p->ctx);
			}
		} else if ( handle > p->handle) {
			group->data[new_index] = group->data[old_index];
			++new_index;
			++old_index;
			--i;
		} else {
			skynet_error(from, "Try to remove a none exist handle : %x", handle);
		}
	}
	while (new_index < count) {
		group->data[new_index] = group->data[old_index];
		++new_index;
		++old_index;
	}

	group->leave_queue.number = 0;

	group->number = new_index;
}