Ejemplo n.º 1
0
// 收回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);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
id_t
index_regist(struct index *idx, void *ud) {
  if (!ud) return 0;
  rwlock_wlock(&idx->lock);
  if (idx->cnt >= idx->cap * 3 / 4) {
    if (!_index_expand(idx)) {
      rwlock_wunlock(&idx->lock);
      return 0;
    }
  }
  for (;;) {
    struct slot *slot;
    id_t id = ++idx->last;
    if (id == 0) {
      id = ++idx->last;
    }
    slot = &idx->slot[HASH(id)];
    if (slot->id) continue;
    slot->id = id;
    slot->ref = 1;
    slot->ud = ud;
    ++idx->cnt;
    rwlock_wunlock(&idx->lock);
    return id;
  }
}
Ejemplo n.º 4
0
handleid
handlemap_new(struct handlemap *m, void *ud) {
	int i;
	if (ud == NULL)
		return 0;
	rwlock_wlock(&m->lock);
	if (m->n >= m->cap * 3 / 4) {
		if (expand_map(m) == NULL) {
			// memory overflow
			rwlock_wunlock(&m->lock);
			return 0;
		}
	}
	
	for (i=0;;i++) {
		struct handleslot *slot;
		handleid id = ++m->lastid;
		if (id == 0) {
			// 0 is reserved for invalid id
			id = ++m->lastid;
		}
		slot = &m->slot[id & (m->cap - 1)];
		if (slot->id)
			continue;
		slot->id = id;
		slot->ref = 1;
		slot->ud = ud;
		++m->n;

		rwlock_wunlock(&m->lock);
		return id;
	}
}
Ejemplo n.º 5
0
void *
index_release(struct index *idx, id_t id) {
  struct slot *slot;
  void *ud = 0;
  if (id == 0) return 0;
  rwlock_rlock(&idx->lock);
  slot = &idx->slot[HASH(id)];
  if (slot->id != id) {
    rwlock_runlock(&idx->lock);
    return 0;
  }
  if (atom_dec(&slot->ref) <= 0) ud = slot->ud;
  rwlock_runlock(&idx->lock);

  if (ud > 0) {
    rwlock_wlock(&idx->lock);
    slot = &idx->slot[HASH(id)];
    if (slot->id != id) {
      rwlock_wunlock(&idx->lock);
      return 0;
    }
    if (slot->ref > 0) {
      rwlock_wunlock(&idx->lock);
      return 0;
    }
    ud = slot->ud;
    slot->id = 0;
    --idx->cnt;
    rwlock_wunlock(&idx->lock);
    return ud;
  }
  return 0;
}
Ejemplo n.º 6
0
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;
				return handle;
			}
		}
		assert((s->slot_size*2 - 1) <= HANDLE_MASK);
		struct skynet_context ** new_slot = skynet_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];
		}
		skynet_free(s->slot);
		s->slot = new_slot;
		s->slot_size *= 2;
	}
}
Ejemplo n.º 7
0
//收回handle
int
server_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 server_context * ctx = s->slot[hash];

	if (ctx != NULL && server_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) {//在 name 表中 找到 handle 对应的 name free掉
				server_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);

	if (ctx) {
		server_context_release(ctx);//free server_ctx
	}

	return ret;
}
Ejemplo n.º 8
0
// name与handle绑定
// 给服务注册一个名称的时候会用到该函数
const char * 
skynet_handle_namehandle(uint32_t handle, const char *name) {
	rwlock_wlock(&H->lock);

	const char * ret = _insert_name(H, name, handle);

	rwlock_wunlock(&H->lock);

	return ret;
}
Ejemplo n.º 9
0
static void
stm_update(struct stm_object *obj, void *msg, int32_t sz) {
	struct stm_copy *copy = stm_newcopy(msg, sz);
	rwlock_wlock(&obj->lock);
	struct stm_copy *oldcopy = obj->copy;
	obj->copy = copy;
	rwlock_wunlock(&obj->lock);

	stm_releasecopy(oldcopy);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
static void
stm_release(struct stm_object *obj) {
	assert(obj->copy);
	rwlock_wlock(&obj->lock);
	// writer release the stm object, so release the last copy .
	stm_releasecopy(obj->copy);
	obj->copy = NULL;
	if (--obj->reference > 0) {
		// stm object grab by readers, reset the copy to NULL.
		rwlock_wunlock(&obj->lock);
		return;
	}
	// no one grab the stm object, no need to unlock wlock.
	skynet_free(obj);
}
Ejemplo n.º 12
0
void
skynet_mq_pushmt(struct skynet_mq *mq, struct skynet_message_package *pack) {
	struct skynet_mq expand;
	if (perpare_space(mq, &expand)) {
		rwlock_wlock(&mq->lock);
			void * ptr = mq->q;
			if (mq->head < expand.head) {
				// the head changes (some one pop in another thread) between perpare_space and rwlock_wlock
				mq->head += mq->cap;
			} 
			mq->q = expand.q;
			mq->cap = expand.cap;
			mq->tail = expand.tail;
		rwlock_wunlock(&mq->lock);
		skynet_free(ptr);
	}
	push_message(mq, pack);
}
Ejemplo n.º 13
0
// 注册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;
	}
}
Ejemplo n.º 14
0
static void *
try_delete(struct handlemap *m, handleid id) {
	struct handleslot * slot;
	void * ud;
	if (id == 0)
		return NULL;
	rwlock_wlock(&m->lock);
	slot = &m->slot[id & (m->cap - 1)];
	if (slot->id != id) {
		rwlock_wunlock(&m->lock);
		return NULL;
	}
	if (slot->ref > 0) {
		rwlock_wunlock(&m->lock);
		return NULL;
	}
	ud = slot->ud;
	slot->id = 0;
	--m->n;
	rwlock_wunlock(&m->lock);
	return ud;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
//注册ctx,将ctx存到handle_storage哈希表中,并得到一个handle
uint32_t
server_handle_register(struct server_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;//高8位清0,保留低24位
			int hash = handle & (s->slot_size-1);//保证handle不能大于slot_size,使得hash取值在[0, slot_size-1]
			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;//高8位用于存放分布式id
				return handle;
			}
		}
		assert((s->slot_size*2 - 1) <= HANDLE_MASK);//确保 扩大2倍空间后 总共handle即 slot的数量不超过 24位的限制
		//哈希表扩大2倍
		struct server_context ** new_slot = server_malloc(s->slot_size * 2 * sizeof(struct server_context *));
		memset(new_slot, 0, s->slot_size * 2 * sizeof(struct server_context *));
		//将原来的数据拷贝到新的空间
		for (i=0;i<s->slot_size;i++) {
			int hash = server_context_handle(s->slot[i]) & (s->slot_size * 2 - 1);//映射新的 hash 值
			assert(new_slot[hash] == NULL);
			new_slot[hash] = s->slot[i];
		}
		server_free(s->slot);
		s->slot = new_slot;
		s->slot_size *= 2;
	}
}
Ejemplo n.º 17
0
uint32_t
skynet_handle_register(struct skynet_context *ctx) {
	struct handle_storage *s = H;

	// 线程上锁, 保证线程安全
	rwlock_wlock(&s->lock);
	
	for (;;) {	// 注意, 这里是一个无限循环, 必须拿到一个可用的 handle
		int i;

		// 从头开始循环遍历
		for (i=0;i<s->slot_size;i++) {
			uint32_t handle = (i+s->handle_index) & HANDLE_MASK;	// 获得从右到左 3 个字节的数据, 最左的低 4 个字节(高 8 位)用来表示 harbor
			int hash = handle & (s->slot_size-1);					// 获得实际的索引, hash 的值不超出 slot_size 的范围

			// 当有可用的 slot 放入 ctx
			if (s->slot[hash] == NULL) {

				// 记录注册的 ctx
				s->slot[hash] = ctx;

				// handle_index 自增
				s->handle_index = handle + 1;

				// 已经存储了 ctx 了, 可以解锁让其他线程使用了
				rwlock_wunlock(&s->lock);

				// 新的 handle 需要使用高 8 位记录当前 handle 所属的 harbor
				handle |= s->harbor;
				return handle;
			}
		}

		// 当前进程不能超过 HANDLE_MASK 的数量
		assert((s->slot_size*2 - 1) <= HANDLE_MASK);

		// 如果没有可用的空间, 扩展容量
		// 申请新的内存空间, slot_size * 2
		struct skynet_context ** new_slot = skynet_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++) {

			// 获得在当前分配的空间中可用的索引, 注意这里是使用  (slot_size * 2 - 1) 在进行为操作.
			int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1);
			assert(new_slot[hash] == NULL);

			// 这里为什么不是直接 new_slot[i] = s->slot[i] 呢, 而要绕个弯拿到 hash, 然后 new_slot[hash] = s->slot[i]
			// 解答, 很有意思的小细节:
			// 首先说 handle_index 从 1 开始计数, 而且都是不断的增加, 返回的时候使用的是 return handle |= s->harbor; 这就决定了返回值不会为 0
			// 在上面的查询 slot, 并且分配 handle 的过程中, 索引是 hash, 返回值是 handle, handle 可以大于 slot_size.
			// 这里获得的 hash 可以是大于 slot_size 的, 那么现在可以举例: hash = 4, i = 0
			// new_slot[4] = s->slot[0], 如果使用 new_slot[i] = s->slot[i] 这种方式, 那么对于结果上来说是没有什么影响的, 但是会出现这样一种情况:
			// 例如: 原来的 slot_size 是 7, 这时 handle_index 16, 全部的 slot 正在被使用. 那么现在需要扩展空间, slot_size 扩展到 16, 那么现在来看看
			// new_slot 的分配情况是如何的:
			// 原来的 slot 是 [0, slot1, slot2, slot3, slot4, slot5, slot6, slot7]
			// 现在的 slot 是 [0, 0, 0, 0, 0, 0, 0, 0, 0, slot1, slot2, slot3, slot4, slot5, slot6, slot7]
			new_slot[hash] = s->slot[i];
		}

		// 释放之前的数据
		skynet_free(s->slot);

		// 记录新的数据
		s->slot = new_slot;
		s->slot_size *= 2;
	}
}