multicast bugfix: don't hold context any more

This commit is contained in:
云风
2012-10-12 12:15:10 +08:00
parent 4fb7fec2fa
commit a93e6b8868
4 changed files with 51 additions and 55 deletions

View File

@@ -23,9 +23,13 @@ skynet_multicast_create(const void * msg, size_t sz, uint32_t source) {
return mc;
}
void
void
skynet_multicast_copy(struct skynet_multicast_message *mc, int copy) {
__sync_fetch_and_add(&mc->ref, copy);
int r = __sync_add_and_fetch(&mc->ref, copy);
if (r == 0) {
free((void *)mc->msg);
free(mc);
}
}
void
@@ -46,17 +50,12 @@ struct array {
uint32_t *data;
};
struct pair {
uint32_t handle;
struct skynet_context * ctx;
};
struct skynet_multicast_group {
struct array enter_queue;
struct array leave_queue;
int cap;
int number;
struct pair * data;
uint32_t * data;
};
struct skynet_multicast_group *
@@ -68,12 +67,6 @@ skynet_multicast_newgroup() {
void
skynet_multicast_deletegroup(struct skynet_multicast_group * g) {
int i;
for (i=0;i<g->number;i++) {
if (g->data[i].ctx) {
skynet_context_release(g->data[i].ctx);
}
}
free(g->data);
free(g->enter_queue.data);
free(g->leave_queue.data);
@@ -120,7 +113,7 @@ combine_queue(struct skynet_context * from, struct skynet_multicast_group * grou
int new_size = group->number + enter;
if (new_size > group->cap) {
group->data = realloc(group->data, new_size * sizeof(struct pair));
group->data = realloc(group->data, new_size * sizeof(uint32_t));
group->cap = new_size;
}
@@ -132,19 +125,14 @@ combine_queue(struct skynet_context * from, struct skynet_multicast_group * grou
if (handle == last)
continue;
last = handle;
struct skynet_context * ctx = skynet_handle_grab(handle);
if (ctx == NULL)
continue;
if (old_index < 0) {
group->data[new_index].handle = handle;
group->data[new_index].ctx = ctx;
group->data[new_index] = handle;
} else {
struct pair * p = &group->data[old_index];
if (handle == p->handle)
uint32_t p = group->data[old_index];
if (handle == p)
continue;
if (handle > p->handle) {
group->data[new_index].handle = handle;
group->data[new_index].ctx = ctx;
if (handle > p) {
group->data[new_index] = handle;
} else {
group->data[new_index] = group->data[old_index];
--old_index;
@@ -174,14 +162,11 @@ combine_queue(struct skynet_context * from, struct skynet_multicast_group * grou
break;
}
uint32_t handle = group->leave_queue.data[i];
struct pair * p = &group->data[old_index];
if (handle == p->handle) {
uint32_t p = group->data[old_index];
if (handle == p) {
--count;
++old_index;
if (p->ctx) {
skynet_context_release(p->ctx);
}
} else if ( handle > p->handle) {
} else if ( handle > p) {
group->data[new_index] = group->data[old_index];
++new_index;
++old_index;
@@ -204,28 +189,45 @@ combine_queue(struct skynet_context * from, struct skynet_multicast_group * grou
int
skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg) {
combine_queue(from, group);
if (group->number == 0) {
skynet_multicast_dispatch(msg, NULL, NULL);
return 0;
}
uint32_t source = skynet_context_handle(from);
skynet_multicast_copy(msg, group->number);
int i;
int release = 0;
for (i=0;i<group->number;i++) {
struct pair * p = &group->data[i];
skynet_context_send(p->ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
int ref = skynet_context_ref(p->ctx);
if (ref == 1) {
skynet_context_release(p->ctx);
struct skynet_context * ctx = skynet_handle_grab(p->handle);
if (ctx == NULL) {
p->ctx = NULL;
skynet_multicast_leavegroup(group, p->handle);
if (group->number > 0) {
uint32_t source = skynet_context_handle(from);
skynet_multicast_copy(msg, group->number);
int i;
for (i=0;i<group->number;i++) {
uint32_t p = group->data[i];
struct skynet_context * ctx = skynet_handle_grab(p);
if (ctx) {
skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
skynet_context_release(ctx);
} else {
skynet_multicast_leavegroup(group, p);
++release;
}
}
}
skynet_multicast_copy(msg, -release);
return group->number - release;
}
void
skynet_multicast_cast(struct skynet_context * from, struct skynet_multicast_message *msg, uint32_t *dests, int n) {
uint32_t source = skynet_context_handle(from);
skynet_multicast_copy(msg, n);
int i;
int release = 0;
for (i=0;i<n;i++) {
uint32_t p = dests[i];
struct skynet_context * ctx = skynet_handle_grab(p);
if (ctx) {
skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0);
skynet_context_release(ctx);
} else {
++release;
}
}
skynet_multicast_copy(msg, -release);
}

View File

@@ -13,6 +13,7 @@ typedef void (*skynet_multicast_func)(void *ud, uint32_t source, const void * ms
struct skynet_multicast_message * skynet_multicast_create(const void * msg, size_t sz, uint32_t source);
void skynet_multicast_copy(struct skynet_multicast_message *, int copy);
void skynet_multicast_dispatch(struct skynet_multicast_message * msg, void * ud, skynet_multicast_func func);
void skynet_multicast_cast(struct skynet_context * from, struct skynet_multicast_message *msg, uint32_t *dests, int n);
struct skynet_multicast_group * skynet_multicast_newgroup();
void skynet_multicast_deletegroup(struct skynet_multicast_group * group);

View File

@@ -132,12 +132,6 @@ skynet_context_release(struct skynet_context *ctx) {
return ctx;
}
int
skynet_context_ref(struct skynet_context *ctx) {
return ctx->ref;
}
int
skynet_context_push(uint32_t handle, struct skynet_message *message) {
struct skynet_context * ctx = skynet_handle_grab(handle);

View File

@@ -11,7 +11,6 @@ struct skynet_monitor;
struct skynet_context * skynet_context_new(const char * name, const char * parm);
void skynet_context_grab(struct skynet_context *);
struct skynet_context * skynet_context_release(struct skynet_context *);
int skynet_context_ref(struct skynet_context *);
uint32_t skynet_context_handle(struct skynet_context *);
void skynet_context_init(struct skynet_context *, uint32_t handle);
int skynet_context_push(uint32_t handle, struct skynet_message *message);