今天學(xué)習(xí)skynet_handle文件。
這個(gè)文件是管理句柄的。建立skynet_context與skynet_handle之間的唯一映射關(guān)系。
即一個(gè)sc對應(yīng)一個(gè)唯一的handle。
先看初始化:
void skynet_handle_init(int harbor) { assert(H==NULL); struct handle_storage * s = skynet_malloc(sizeof(*H)); s->slot_size = DEFAULT_SLOT_SIZE; s->slot = skynet_malloc(s->slot_size * sizeof(struct skynet_context *)); memset(s->slot, 0, s->slot_size * sizeof(struct skynet_context *)); rwlock_init(&s->lock); // reserve 0 for system s->harbor = (uint32_t) (harbor & 0xff) << HANDLE_REMOTE_SHIFT; s->handle_index = 1; s->name_cap = 2; s->name_count = 0; s->name = skynet_malloc(s->name_cap * sizeof(struct handle_name)); H = s; // Don't need to free H}生成一個(gè)handle_storage對象即句柄倉庫結(jié)構(gòu)體。初始化分配DEFAULT_SLOT_SIZE個(gè)元素的slot數(shù)組。
生成harbor的ID,只能占用高8位。
初始化name數(shù)組,暫時(shí)不清楚用處,猜測可能是建立一個(gè)字符串名與handle之間的映射方便查詢吧。
sc被存放在一個(gè)數(shù)組中,數(shù)組的下標(biāo)選取是通過hash來計(jì)算的。
uint32_tskynet_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;//HANDLE_MASK用于取低24位,高8位是遠(yuǎn)程節(jié)點(diǎn)ID int hash = handle & (s->slot_size-1);//保證下標(biāo)不會(huì)超過孔位數(shù)量??孜粩?shù)量始終是2的N次方。 if (s->slot[hash] == NULL) { s->slot[hash] = ctx; s->handle_index = handle + 1;//單調(diào)遞增,假設(shè)了最多不會(huì)超過0xffffff個(gè)。 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 *));//雙倍擴(kuò)充容量 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; }}存儲好后,其他業(yè)務(wù)就可以用handle來尋找sc了。
struct skynet_context * skynet_handle_grab(uint32_t handle) { struct handle_storage *s = H; struct skynet_context * result = NULL; rwlock_rlock(&s->lock); uint32_t hash = handle & (s->slot_size-1); struct skynet_context * ctx = s->slot[hash]; if (ctx && skynet_context_handle(ctx) == handle) { result = ctx; skynet_context_grab(result); } rwlock_runlock(&s->lock); return result;}當(dāng)然,還有回收釋放handle的intskynet_handle_retire(uint32_t handle)每個(gè)sc在生成的時(shí)候,都會(huì)調(diào)用skynet_handle_register來進(jìn)行注冊。
新聞熱點(diǎn)
疑難解答