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; }
static void stm_grab(struct stm_object *obj) { rwlock_rlock(&obj->lock); int ref = __sync_fetch_and_add(&obj->reference,1); rwlock_runlock(&obj->lock); assert(ref > 0); }
uint32_t skynet_handle_findname(const char * name) { struct handle_storage *s = H; rwlock_rlock(&s->lock); uint32_t handle = 0; int begin = 0; int end = s->name_count - 1; while (begin<=end) { int mid = (begin+end)/2; struct handle_name *n = &s->name[mid]; int c = strcmp(n->name, name); if (c==0) { handle = n->handle; break; } if (c<0) { begin = mid + 1; } else { end = mid - 1; } } rwlock_runlock(&s->lock); return handle; }
void * index_grab(struct index *idx, id_t id) { struct slot *slot; void *ud; if (id == 0) return 0; rwlock_rlock(&idx->lock); slot = &idx->slot[HASH(id)]; if (slot->id != id) { rwlock_runlock(&idx->lock); return 0; } atom_inc(&slot->ref); ud = slot->ud; rwlock_runlock(&idx->lock); return ud; }
uint32_t skynet_handle_findname(const char * name) { struct handle_storage *s = H; rwlock_rlock(&s->lock); uint32_t handle = 0; // 从头到位遍历搜索 int begin = 0; int end = s->name_count - 1; while (begin<=end) { // 折半查询, 必须保证查询的序列是已经排序好的. int mid = (begin+end)/2; struct handle_name *n = &s->name[mid]; int c = strcmp(n->name, name); if (c==0) { handle = n->handle; break; } // 关键的就在这里了, 决定往那个方向查询 if (c<0) { begin = mid + 1; } else { end = mid - 1; } } rwlock_runlock(&s->lock); return handle; }
static void stm_grab(struct stm_object *obj) { rwlock_rlock(&obj->lock); int ref = ATOM_FINC(&obj->reference); rwlock_runlock(&obj->lock); assert(ref > 0); }
void skynet_handle_retireall() { struct handle_storage *s = H; for (;;) { // 保证所有的资源都被回收 int n = 0; int i; for (i = 0; i < s->slot_size; i++) { // 保证线程安全 rwlock_rlock(&s->lock); // 拿到 context 的 handle struct skynet_context * ctx = s->slot[i]; uint32_t handle = 0; if (ctx) handle = skynet_context_handle(ctx); rwlock_runlock(&s->lock); // 对 handle 做回收处理 if (handle != 0) { // 这就是上面说的, handle 不会使用 0. if (skynet_handle_retire(handle)) { ++n; } } } // 保证全部的 context 全部删除 if (n==0) return; } }
// 根据名称查找handle uint32_t skynet_handle_findname(const char * name) { struct handle_storage *s = H; rwlock_rlock(&s->lock); uint32_t handle = 0; int begin = 0; int end = s->name_count - 1; while (begin<=end) { int mid = (begin+end)/2; // 这里用的二分查找 听说会有整形溢出 改成减法可以避免 不清楚具体怎么搞 struct handle_name *n = &s->name[mid]; int c = strcmp(n->name, name); // // 一直在头部插入 实际上这样插入后 name 会按长度大小排好序 这样就能使用二分查找了 if (c==0) { handle = n->handle; break; } if (c<0) { begin = mid + 1; } else { end = mid - 1; } } rwlock_runlock(&s->lock); return handle; }
void * handlemap_grab(struct handlemap *m, handleid id) { struct handleslot * slot; void * ud; if (id == 0) return NULL; rwlock_rlock(&m->lock); slot = &m->slot[id & (m->cap - 1)]; if (slot->id != id) { rwlock_runlock(&m->lock); return NULL; } atom_inc(&slot->ref); ud = slot->ud; rwlock_runlock(&m->lock); return ud; }
static void * release_ref(struct handlemap *m, handleid id) { struct handleslot * slot; void * ud = NULL; if (id == 0) return NULL; rwlock_rlock(&m->lock); slot = &m->slot[id & (m->cap - 1)]; if (slot->id != id) { rwlock_runlock(&m->lock); return NULL; } if (atom_dec(&slot->ref) <= 0) { ud = slot->ud; } rwlock_runlock(&m->lock); return ud; }
static void stm_releasereader(struct stm_object *obj) { rwlock_rlock(&obj->lock); if (ATOM_DEC(&obj->reference) == 0) { // last reader, no writer. so no need to unlock assert(obj->copy == NULL); skynet_free(obj); return; } rwlock_runlock(&obj->lock); }
static struct stm_copy * stm_copy(struct stm_object *obj) { rwlock_rlock(&obj->lock); struct stm_copy * ret = obj->copy; if (ret) { int ref = ATOM_FINC(&ret->reference); assert(ref > 0); } rwlock_runlock(&obj->lock); return ret; }
static struct stm_copy * stm_copy(struct stm_object *obj) { rwlock_rlock(&obj->lock); struct stm_copy * ret = obj->copy; if (ret) { int ref = __sync_fetch_and_add(&ret->reference,1); assert(ref > 0); } rwlock_runlock(&obj->lock); return ret; }
int skynet_mq_popmt(struct skynet_mq *mq, struct skynet_message_package *pack) { if (mq->head == mq->tail) { return 0; } rwlock_rlock(&mq->lock); // only one reader, so use read lock is ok. // but we can call skynet_mq_pushmt in another thread *pack = mq->q[mq->head]; pop_message(mq); rwlock_runlock(&mq->lock); return 1; }
int index_list(struct index *idx, int n, id_t *list) { int i, cnt = 0; rwlock_rlock(&idx->lock); if (list) { for (i = 0; cnt < n && i < idx->cap; i++) { struct slot *slot = &idx->slot[i]; if (slot->id == 0) continue; list[cnt] = slot->id; ++cnt; } } cnt = idx->cnt; rwlock_runlock(&idx->lock); return cnt; }
int handlemap_list(struct handlemap *m, int n, handleid * result) { int i,t=0; rwlock_rlock(&m->lock); for (i=0;t < n && i<m->cap;i++) { struct handleslot *slot = &m->slot[i]; if (slot->id == 0) continue; result[t] = slot->id; ++t; } t=m->n; rwlock_runlock(&m->lock); return t; }
// 通过handle获取skynet_context, skynet_context的引用计数加1 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); // __sync_add_and_fetch(&ctx->ref,1); skynet_context引用计数加1 } rwlock_runlock(&s->lock); return result; }
void skynet_handle_retireall() { struct handle_storage *s = H; for (;;) { int n=0; int i; for (i=0;i<s->slot_size;i++) { rwlock_rlock(&s->lock); struct skynet_context * ctx = s->slot[i]; rwlock_runlock(&s->lock); if (ctx != NULL) { ++n; skynet_handle_retire(skynet_context_handle(ctx)); } } if (n==0) return; } }
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 // 1. 判断是否在同一个节点 // 2. 确认 handle 是没有超出 slot_size 的, 因为可能 slot_size = 8, handle = 15, skynet_context_handle(ctx) = 7 // 3. 其他线程没有修改 ctx && skynet_context_handle(ctx) == handle) { result = ctx; skynet_context_grab(result); } rwlock_runlock(&s->lock); return result; }
void skynet_handle_retireall() { struct handle_storage *s = H; for (;;) { int n=0; int i; for (i=0;i<s->slot_size;i++) { rwlock_rlock(&s->lock); struct skynet_context * ctx = s->slot[i]; uint32_t handle = 0; if (ctx) handle = skynet_context_handle(ctx); rwlock_runlock(&s->lock); if (handle != 0) { if (skynet_handle_retire(handle)) { ++n; } } } if (n==0) return; } }