static struct {
struct dlist *conn_cb_list;
struct dlist *disconn_cb_list;
+ enum processing_event_callback {
+ PROCESSING_NONE = 0x0,
+ PROCESSING_DISCONNECTION = 0x01,
+ PROCESSING_CONNECTION = 0x02,
+ } processing_event_callback;
} s_info = {
.conn_cb_list = NULL,
.disconn_cb_list = NULL,
+ .processing_event_callback = PROCESSING_NONE,
};
struct cbdata {
};
struct evtdata {
+ int deleted;
int (*evt_cb)(int fd, void *data);
void *data;
};
struct dlist *n;
struct evtdata *cbdata;
+ s_info.processing_event_callback |= PROCESSING_CONNECTION;
dlist_foreach_safe(s_info.conn_cb_list, l, n, cbdata) {
- if (cbdata->evt_cb(handle, cbdata->data) < 0) {
- if (dlist_find_data(s_info.conn_cb_list, cbdata)) {
- s_info.conn_cb_list = dlist_remove(s_info.conn_cb_list, l);
- free(cbdata);
- }
+ /*!
+ * \NOTE
+ * cbdata->deleted must has to be checked before call the function and
+ * return from the function call.
+ */
+ if (cbdata->deleted || cbdata->evt_cb(handle, cbdata->data) < 0 || cbdata->deleted) {
+ s_info.conn_cb_list = dlist_remove(s_info.conn_cb_list, l);
+ free(cbdata);
}
}
+ s_info.processing_event_callback &= ~PROCESSING_CONNECTION;
}
HAPI void invoke_disconn_cb_list(int handle)
struct dlist *n;
struct evtdata *cbdata;
+ s_info.processing_event_callback |= PROCESSING_DISCONNECTION;
dlist_foreach_safe(s_info.disconn_cb_list, l, n, cbdata) {
- if (cbdata->evt_cb(handle, cbdata->data) < 0) {
- if (dlist_find_data(s_info.disconn_cb_list, cbdata)) {
- s_info.disconn_cb_list = dlist_remove(s_info.disconn_cb_list, l);
- free(cbdata);
- }
+ /*!
+ * \NOTE
+ * cbdata->deleted must has to be checked before call the function and
+ * return from the function call.
+ */
+ if (cbdata->deleted || cbdata->evt_cb(handle, cbdata->data) < 0 || cbdata->deleted) {
+ s_info.disconn_cb_list = dlist_remove(s_info.disconn_cb_list, l);
+ free(cbdata);
}
}
+ s_info.processing_event_callback &= ~PROCESSING_DISCONNECTION;
}
static gboolean client_cb(GIOChannel *src, GIOCondition cond, gpointer data)
}
g_io_channel_unref(gio);
+
invoke_con_cb_list(client_fd);
return client_fd;
}
cbdata->evt_cb = evt_cb;
cbdata->data = data;
+ cbdata->deleted = 0;
if (type == CONNECTOR_CONNECTED) {
s_info.conn_cb_list = dlist_append(s_info.conn_cb_list, cbdata);
if (cbdata->evt_cb == cb && cbdata->data == data) {
void *data;
data = cbdata->data;
- dlist_remove_data(s_info.conn_cb_list, cbdata);
- free(cbdata);
+
+ if ((s_info.processing_event_callback & PROCESSING_CONNECTION) == PROCESSING_CONNECTION) {
+ cbdata->deleted = 1;
+ } else {
+ dlist_remove_data(s_info.conn_cb_list, cbdata);
+ free(cbdata);
+ }
+
return data;
}
}
if (cbdata->evt_cb == cb && cbdata->data == data) {
void *data;
data = cbdata->data;
- dlist_remove_data(s_info.disconn_cb_list, cbdata);
- free(cbdata);
+
+ if ((s_info.processing_event_callback & PROCESSING_DISCONNECTION) == PROCESSING_DISCONNECTION) {
+ cbdata->deleted = 1;
+ } else {
+ dlist_remove_data(s_info.disconn_cb_list, cbdata);
+ free(cbdata);
+ }
return data;
}
}
int (*recv_cb)(pid_t pid, int handle, const struct packet *packet, void *data);
void *data;
- int in_recv;
+ int inuse;
};
struct recv_ctx {
pid_t pid;
struct packet *packet;
double timeout;
+
+ int inuse;
};
static inline struct request_ctx *find_request_ctx(int handle, double seq)
static inline void destroy_request_ctx(struct request_ctx *ctx)
{
+ struct dlist *l;
+
+ if (ctx->inuse) {
+ return;
+ }
+
+ l = dlist_find_data(s_info.request_list, ctx);
+ if (!l) {
+ return;
+ }
+
+ s_info.request_list = dlist_remove(s_info.request_list, l);
+
packet_unref(ctx->packet);
- dlist_remove_data(s_info.request_list, ctx);
free(ctx);
}
ctx->packet = NULL;
ctx->recv_cb = NULL;
ctx->data = NULL;
- ctx->in_recv = 0;
+ ctx->inuse = 0;
s_info.request_list = dlist_append(s_info.request_list, ctx);
return ctx;
static inline void destroy_recv_ctx(struct recv_ctx *ctx)
{
- dlist_remove_data(s_info.recv_list, ctx);
+ struct dlist *l;
+
+ if (ctx->inuse) {
+ return;
+ }
+
+ l = dlist_find_data(s_info.recv_list, ctx);
+ if (!l) {
+ return;
+ }
+
+ s_info.recv_list = dlist_remove(s_info.recv_list, l);
+
packet_destroy(ctx->packet);
free(ctx);
}
ctx->handle = handle;
ctx->pid = (pid_t)-1;
ctx->timeout = timeout;
+ ctx->inuse = 0;
s_info.recv_list = dlist_append(s_info.recv_list, ctx);
return ctx;
}
-static inline int packet_ready(int handle, const struct recv_ctx *receive, struct method *table)
+static inline int packet_ready(int handle, struct recv_ctx *receive, struct method *table)
{
struct request_ctx *request;
double sequence;
}
if (request->recv_cb) {
- request->in_recv = 1;
+ request->inuse = 1;
+ receive->inuse = 1;
request->recv_cb(receive->pid, handle, receive->packet, request->data);
- request->in_recv = 0;
+ receive->inuse = 0;
+ request->inuse = 0;
}
destroy_request_ctx(request);
continue;
}
+ receive->inuse = 1;
result = table[i].handler(receive->pid, handle, receive->packet);
+ receive->inuse = 0;
if (result) {
ret = s_info.vtable.send(handle, (void *)packet_data(result), packet_size(result), DEFAULT_TIMEOUT);
if (ret < 0) {
}
packet_destroy(result);
}
+
break;
}
continue;
}
+ receive->inuse = 1;
result = table[i].handler(receive->pid, handle, receive->packet);
+ receive->inuse = 0;
if (result) {
packet_destroy(result);
}
+
+ break;
}
break;
default:
struct request_ctx *request;
struct dlist *l;
struct dlist *n;
+ int inuse_found = 0;
pid_t pid = (pid_t)-1;
- int referred = 0;
receive = find_recv_ctx(handle);
if (receive) {
continue;
}
- if (request->in_recv) {
- referred = 1;
+ if (request->inuse) {
+ inuse_found = 1;
continue;
}
destroy_request_ctx(request);
}
- if (receive && !referred) {
+ if (receive && !inuse_found) {
destroy_recv_ctx(receive);
}