skynet_handle.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include "skynet.h"
  2. #include "skynet_handle.h"
  3. #include "skynet_server.h"
  4. #include "rwlock.h"
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include <string.h>
  8. #define DEFAULT_SLOT_SIZE 4
  9. #define MAX_SLOT_SIZE 0x40000000
  10. struct handle_name {
  11. char * name;
  12. uint32_t handle;
  13. };
  14. struct handle_storage {
  15. struct rwlock lock;
  16. uint32_t harbor;
  17. uint32_t handle_index;
  18. int slot_size;
  19. struct skynet_context ** slot;
  20. int name_cap;
  21. int name_count;
  22. struct handle_name *name;
  23. };
  24. static struct handle_storage *H = NULL;
  25. uint32_t
  26. skynet_handle_register(struct skynet_context *ctx) {
  27. struct handle_storage *s = H;
  28. rwlock_wlock(&s->lock);
  29. for (;;) {
  30. int i;
  31. uint32_t handle = s->handle_index;
  32. for (i=0;i<s->slot_size;i++,handle++) {
  33. if (handle > HANDLE_MASK) {
  34. // 0 is reserved
  35. handle = 1;
  36. }
  37. int hash = handle & (s->slot_size-1);
  38. if (s->slot[hash] == NULL) {
  39. s->slot[hash] = ctx;
  40. s->handle_index = handle + 1;
  41. rwlock_wunlock(&s->lock);
  42. handle |= s->harbor;
  43. return handle;
  44. }
  45. }
  46. assert((s->slot_size*2 - 1) <= HANDLE_MASK);
  47. struct skynet_context ** new_slot = skynet_malloc(s->slot_size * 2 * sizeof(struct skynet_context *));
  48. memset(new_slot, 0, s->slot_size * 2 * sizeof(struct skynet_context *));
  49. for (i=0;i<s->slot_size;i++) {
  50. if (s->slot[i]) {
  51. int hash = skynet_context_handle(s->slot[i]) & (s->slot_size * 2 - 1);
  52. assert(new_slot[hash] == NULL);
  53. new_slot[hash] = s->slot[i];
  54. }
  55. }
  56. skynet_free(s->slot);
  57. s->slot = new_slot;
  58. s->slot_size *= 2;
  59. }
  60. }
  61. int
  62. skynet_handle_retire(uint32_t handle) {
  63. int ret = 0;
  64. struct handle_storage *s = H;
  65. rwlock_wlock(&s->lock);
  66. uint32_t hash = handle & (s->slot_size-1);
  67. struct skynet_context * ctx = s->slot[hash];
  68. if (ctx != NULL && skynet_context_handle(ctx) == handle) {
  69. s->slot[hash] = NULL;
  70. ret = 1;
  71. int i;
  72. int j=0, n=s->name_count;
  73. for (i=0; i<n; ++i) {
  74. if (s->name[i].handle == handle) {
  75. skynet_free(s->name[i].name);
  76. continue;
  77. } else if (i!=j) {
  78. s->name[j] = s->name[i];
  79. }
  80. ++j;
  81. }
  82. s->name_count = j;
  83. } else {
  84. ctx = NULL;
  85. }
  86. rwlock_wunlock(&s->lock);
  87. if (ctx) {
  88. // release ctx may call skynet_handle_* , so wunlock first.
  89. skynet_context_release(ctx);
  90. }
  91. return ret;
  92. }
  93. void
  94. skynet_handle_retireall() {
  95. struct handle_storage *s = H;
  96. for (;;) {
  97. int n=0;
  98. int i;
  99. for (i=0;i<s->slot_size;i++) {
  100. rwlock_rlock(&s->lock);
  101. struct skynet_context * ctx = s->slot[i];
  102. uint32_t handle = 0;
  103. if (ctx) {
  104. handle = skynet_context_handle(ctx);
  105. ++n;
  106. }
  107. rwlock_runlock(&s->lock);
  108. if (handle != 0) {
  109. skynet_handle_retire(handle);
  110. }
  111. }
  112. if (n==0)
  113. return;
  114. }
  115. }
  116. struct skynet_context *
  117. skynet_handle_grab(uint32_t handle) {
  118. struct handle_storage *s = H;
  119. struct skynet_context * result = NULL;
  120. rwlock_rlock(&s->lock);
  121. uint32_t hash = handle & (s->slot_size-1);
  122. struct skynet_context * ctx = s->slot[hash];
  123. if (ctx && skynet_context_handle(ctx) == handle) {
  124. result = ctx;
  125. skynet_context_grab(result);
  126. }
  127. rwlock_runlock(&s->lock);
  128. return result;
  129. }
  130. uint32_t
  131. skynet_handle_findname(const char * name) {
  132. struct handle_storage *s = H;
  133. rwlock_rlock(&s->lock);
  134. uint32_t handle = 0;
  135. int begin = 0;
  136. int end = s->name_count - 1;
  137. while (begin<=end) {
  138. int mid = (begin+end)/2;
  139. struct handle_name *n = &s->name[mid];
  140. int c = strcmp(n->name, name);
  141. if (c==0) {
  142. handle = n->handle;
  143. break;
  144. }
  145. if (c<0) {
  146. begin = mid + 1;
  147. } else {
  148. end = mid - 1;
  149. }
  150. }
  151. rwlock_runlock(&s->lock);
  152. return handle;
  153. }
  154. static void
  155. _insert_name_before(struct handle_storage *s, char *name, uint32_t handle, int before) {
  156. if (s->name_count >= s->name_cap) {
  157. s->name_cap *= 2;
  158. assert(s->name_cap <= MAX_SLOT_SIZE);
  159. struct handle_name * n = skynet_malloc(s->name_cap * sizeof(struct handle_name));
  160. int i;
  161. for (i=0;i<before;i++) {
  162. n[i] = s->name[i];
  163. }
  164. for (i=before;i<s->name_count;i++) {
  165. n[i+1] = s->name[i];
  166. }
  167. skynet_free(s->name);
  168. s->name = n;
  169. } else {
  170. int i;
  171. for (i=s->name_count;i>before;i--) {
  172. s->name[i] = s->name[i-1];
  173. }
  174. }
  175. s->name[before].name = name;
  176. s->name[before].handle = handle;
  177. s->name_count ++;
  178. }
  179. static const char *
  180. _insert_name(struct handle_storage *s, const char * name, uint32_t handle) {
  181. int begin = 0;
  182. int end = s->name_count - 1;
  183. while (begin<=end) {
  184. int mid = (begin+end)/2;
  185. struct handle_name *n = &s->name[mid];
  186. int c = strcmp(n->name, name);
  187. if (c==0) {
  188. return NULL;
  189. }
  190. if (c<0) {
  191. begin = mid + 1;
  192. } else {
  193. end = mid - 1;
  194. }
  195. }
  196. char * result = skynet_strdup(name);
  197. _insert_name_before(s, result, handle, begin);
  198. return result;
  199. }
  200. const char *
  201. skynet_handle_namehandle(uint32_t handle, const char *name) {
  202. rwlock_wlock(&H->lock);
  203. const char * ret = _insert_name(H, name, handle);
  204. rwlock_wunlock(&H->lock);
  205. return ret;
  206. }
  207. void
  208. skynet_handle_init(int harbor) {
  209. assert(H==NULL);
  210. struct handle_storage * s = skynet_malloc(sizeof(*H));
  211. s->slot_size = DEFAULT_SLOT_SIZE;
  212. s->slot = skynet_malloc(s->slot_size * sizeof(struct skynet_context *));
  213. memset(s->slot, 0, s->slot_size * sizeof(struct skynet_context *));
  214. rwlock_init(&s->lock);
  215. // reserve 0 for system
  216. s->harbor = (uint32_t) (harbor & 0xff) << HANDLE_REMOTE_SHIFT;
  217. s->handle_index = 1;
  218. s->name_cap = 2;
  219. s->name_count = 0;
  220. s->name = skynet_malloc(s->name_cap * sizeof(struct handle_name));
  221. H = s;
  222. // Don't need to free H
  223. }