123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- #include "skynet.h"
- #include "skynet_handle.h"
- #include "skynet_server.h"
- #include "rwlock.h"
- #include <stdlib.h>
- #include <assert.h>
- #include <string.h>
- #define DEFAULT_SLOT_SIZE 4
- #define MAX_SLOT_SIZE 0x40000000
- struct handle_name {
- char * name;
- uint32_t handle;
- };
- struct handle_storage {
- struct rwlock lock;
- uint32_t harbor;
- uint32_t handle_index;
- int slot_size;
- struct skynet_context ** slot;
-
- int name_cap;
- int name_count;
- struct handle_name *name;
- };
- static struct handle_storage *H = NULL;
- uint32_t
- skynet_handle_register(struct skynet_context *ctx) {
- struct handle_storage *s = H;
- rwlock_wlock(&s->lock);
-
- for (;;) {
- int i;
- uint32_t handle = s->handle_index;
- for (i=0;i<s->slot_size;i++,handle++) {
- if (handle > HANDLE_MASK) {
- // 0 is reserved
- handle = 1;
- }
- 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++) {
- if (s->slot[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;
- }
- }
- 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;
- }
- 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);
- ++n;
- }
- rwlock_runlock(&s->lock);
- if (handle != 0) {
- skynet_handle_retire(handle);
- }
- }
- 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 && skynet_context_handle(ctx) == handle) {
- result = ctx;
- skynet_context_grab(result);
- }
- rwlock_runlock(&s->lock);
- return result;
- }
- 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
- _insert_name_before(struct handle_storage *s, char *name, uint32_t handle, int before) {
- if (s->name_count >= s->name_cap) {
- s->name_cap *= 2;
- assert(s->name_cap <= MAX_SLOT_SIZE);
- struct handle_name * n = skynet_malloc(s->name_cap * sizeof(struct handle_name));
- int i;
- for (i=0;i<before;i++) {
- n[i] = s->name[i];
- }
- for (i=before;i<s->name_count;i++) {
- n[i+1] = s->name[i];
- }
- skynet_free(s->name);
- s->name = n;
- } else {
- int i;
- for (i=s->name_count;i>before;i--) {
- s->name[i] = s->name[i-1];
- }
- }
- s->name[before].name = name;
- s->name[before].handle = handle;
- s->name_count ++;
- }
- static const char *
- _insert_name(struct handle_storage *s, const char * name, uint32_t handle) {
- 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) {
- return NULL;
- }
- if (c<0) {
- begin = mid + 1;
- } else {
- end = mid - 1;
- }
- }
- char * result = skynet_strdup(name);
- _insert_name_before(s, result, handle, begin);
- return result;
- }
- 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;
- }
- 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
- }
|