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; }
void skynet_service_release(address_t id) { if (id == 0) return; struct service_node *sn = &G->s[id % MAX_SERVICE]; assert(sn->id == id); assert(skynet_service_id(sn->svc) == id); atom_dec(&sn->ref); }
struct skynet_service * skynet_service_grab(address_t id) { if (id == 0) return NULL; struct service_node *sn = &G->s[id % MAX_SERVICE]; if (sn->exit || sn->id != id) return NULL; atom_inc(&sn->ref); if (sn->exit) { // double check, service may exit after inc ref // .ref never inc after .exit set atom_dec(&sn->ref); return NULL; } // the ref is great than 1, so .svc is safe now if (skynet_service_id(sn->svc) != id) { atom_dec(&sn->ref); return NULL; } return sn->svc; }
void skynet_message_release(struct skynet_message *msg) { if (msg == NULL) return; if (atom_dec(&msg->ref) == 0) { if (msg->type == MESSAGE_USER) { struct skynet_message_user *umsg = (struct skynet_message_user *)msg; umsg->userfree(umsg->buffer); } else { assert(msg->type == MESSAGE_SKYNET); } skynet_free(msg); } }
static inline void rwlock_rlock(struct rwlock *lock) { for (;;) { while(lock->write) { atom_sync(); } atom_inc(&lock->read); if (lock->write) { atom_dec(&lock->read); } else { break; } } }
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 inline void rwlock_runlock(struct rwlock *lock) { atom_dec(&lock->read); }
static inline void service_total_dec(void) { atom_dec(&g.total); }