Add void* arguments to request_new and reply_new evrpc hooks

This makes evprc setup more extensible, and helps with Shuo Chen's
work on implementing Google protocol buffers rpc on top of Libevent 2
evrpc.

This patch breaks binary compatibility with previous versions of
Libevent, since it changes struct evrpc and the signature of
evrpc_register_generic().  Since all compliant code should be calling
evrpc_register_generic via EVRPC_REGISTER, it shouldn't break source
compatibility.

(Code by Shuo Chen; commit message by Nick)
This commit is contained in:
Shuo Chen 2010-04-14 14:27:29 -04:00 committed by Nick Mathewson
parent 07edf784fa
commit 755fbf16c3
4 changed files with 26 additions and 15 deletions

View File

@ -117,6 +117,7 @@ class StructCCode(Struct):
print >>file, \ print >>file, \
"""struct %(name)s *%(name)s_new(void); """struct %(name)s *%(name)s_new(void);
struct %(name)s *%(name)s_new_with_arg(void *);
void %(name)s_free(struct %(name)s *); void %(name)s_free(struct %(name)s *);
void %(name)s_clear(struct %(name)s *); void %(name)s_clear(struct %(name)s *);
void %(name)s_marshal(struct evbuffer *, const struct %(name)s *); void %(name)s_marshal(struct evbuffer *, const struct %(name)s *);
@ -157,6 +158,12 @@ int evtag_unmarshal_%(name)s(struct evbuffer *, ev_uint32_t,
'struct %(name)s *\n' 'struct %(name)s *\n'
'%(name)s_new(void)\n' '%(name)s_new(void)\n'
'{\n' '{\n'
' return %(name)s_new_with_arg(NULL);\n'
'}\n'
'\n'
'struct %(name)s *\n'
'%(name)s_new_with_arg(void *unused)\n'
'{\n'
' struct %(name)s *tmp;\n' ' struct %(name)s *tmp;\n'
' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n' ' if ((tmp = malloc(sizeof(struct %(name)s))) == NULL) {\n'
' event_warn("%%s: malloc", __func__);\n' ' event_warn("%%s: malloc", __func__);\n'

18
evrpc.c
View File

@ -339,7 +339,7 @@ evrpc_request_cb_closure(void *arg, enum EVRPC_HOOK_RESULT hook_res)
goto error; goto error;
/* let's check that we can parse the request */ /* let's check that we can parse the request */
rpc_state->request = rpc->request_new(); rpc_state->request = rpc->request_new(rpc->request_new_arg);
if (rpc_state->request == NULL) if (rpc_state->request == NULL)
goto error; goto error;
@ -351,7 +351,7 @@ evrpc_request_cb_closure(void *arg, enum EVRPC_HOOK_RESULT hook_res)
/* at this point, we have a well formed request, prepare the reply */ /* at this point, we have a well formed request, prepare the reply */
rpc_state->reply = rpc->reply_new(); rpc_state->reply = rpc->reply_new(rpc->reply_new_arg);
if (rpc_state->reply == NULL) if (rpc_state->reply == NULL)
goto error; goto error;
@ -1081,9 +1081,9 @@ error:
/** Takes a request object and fills it in with the right magic */ /** Takes a request object and fills it in with the right magic */
static struct evrpc * static struct evrpc *
evrpc_register_object(const char *name, evrpc_register_object(const char *name,
void *(*req_new)(void), void (*req_free)(void *), void *(*req_new)(void*), void *req_new_arg, void (*req_free)(void *),
int (*req_unmarshal)(void *, struct evbuffer *), int (*req_unmarshal)(void *, struct evbuffer *),
void *(*rpl_new)(void), void (*rpl_free)(void *), void *(*rpl_new)(void*), void *rpl_new_arg, void (*rpl_free)(void *),
int (*rpl_complete)(void *), int (*rpl_complete)(void *),
void (*rpl_marshal)(struct evbuffer *, void *)) void (*rpl_marshal)(struct evbuffer *, void *))
{ {
@ -1096,9 +1096,11 @@ evrpc_register_object(const char *name,
return (NULL); return (NULL);
} }
rpc->request_new = req_new; rpc->request_new = req_new;
rpc->request_new_arg = req_new_arg;
rpc->request_free = req_free; rpc->request_free = req_free;
rpc->request_unmarshal = req_unmarshal; rpc->request_unmarshal = req_unmarshal;
rpc->reply_new = rpl_new; rpc->reply_new = rpl_new;
rpc->reply_new_arg = rpl_new_arg;
rpc->reply_free = rpl_free; rpc->reply_free = rpl_free;
rpc->reply_complete = rpl_complete; rpc->reply_complete = rpl_complete;
rpc->reply_marshal = rpl_marshal; rpc->reply_marshal = rpl_marshal;
@ -1108,15 +1110,15 @@ evrpc_register_object(const char *name,
int int
evrpc_register_generic(struct evrpc_base *base, const char *name, evrpc_register_generic(struct evrpc_base *base, const char *name,
void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
void *(*req_new)(void), void (*req_free)(void *), void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
int (*req_unmarshal)(void *, struct evbuffer *), int (*req_unmarshal)(void *, struct evbuffer *),
void *(*rpl_new)(void), void (*rpl_free)(void *), void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *),
int (*rpl_complete)(void *), int (*rpl_complete)(void *),
void (*rpl_marshal)(struct evbuffer *, void *)) void (*rpl_marshal)(struct evbuffer *, void *))
{ {
struct evrpc* rpc = struct evrpc* rpc =
evrpc_register_object(name, req_new, req_free, req_unmarshal, evrpc_register_object(name, req_new, req_new_arg, req_free, req_unmarshal,
rpl_new, rpl_free, rpl_complete, rpl_marshal); rpl_new, rpl_new_arg, rpl_free, rpl_complete, rpl_marshal);
if (rpc == NULL) if (rpc == NULL)
return (-1); return (-1);
evrpc_register_rpc(base, rpc, evrpc_register_rpc(base, rpc,

View File

@ -319,10 +319,10 @@ void evrpc_free(struct evrpc_base *base);
#define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \ #define EVRPC_REGISTER(base, name, request, reply, callback, cbarg) \
evrpc_register_generic(base, #name, \ evrpc_register_generic(base, #name, \
(void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \ (void (*)(struct evrpc_req_generic *, void *))callback, cbarg, \
(void *(*)(void))request##_new, \ (void *(*)(void *))request##_new, NULL, \
(void (*)(void *))request##_free, \ (void (*)(void *))request##_free, \
(int (*)(void *, struct evbuffer *))request##_unmarshal, \ (int (*)(void *, struct evbuffer *))request##_unmarshal, \
(void *(*)(void))reply##_new, \ (void *(*)(void *))reply##_new, NULL, \
(void (*)(void *))reply##_free, \ (void (*)(void *))reply##_free, \
(int (*)(void *))reply##_complete, \ (int (*)(void *))reply##_complete, \
(void (*)(struct evbuffer *, void *))reply##_marshal) (void (*)(struct evbuffer *, void *))reply##_marshal)
@ -575,9 +575,9 @@ int evrpc_send_request_generic(struct evrpc_pool *pool,
int int
evrpc_register_generic(struct evrpc_base *base, const char *name, evrpc_register_generic(struct evrpc_base *base, const char *name,
void (*callback)(struct evrpc_req_generic *, void *), void *cbarg, void (*callback)(struct evrpc_req_generic *, void *), void *cbarg,
void *(*req_new)(void), void (*req_free)(void *), void *(*req_new)(void *), void *req_new_arg, void (*req_free)(void *),
int (*req_unmarshal)(void *, struct evbuffer *), int (*req_unmarshal)(void *, struct evbuffer *),
void *(*rpl_new)(void), void (*rpl_free)(void *), void *(*rpl_new)(void *), void *rpl_new_arg, void (*rpl_free)(void *),
int (*rpl_complete)(void *), int (*rpl_complete)(void *),
void (*rpl_marshal)(struct evbuffer *, void *)); void (*rpl_marshal)(struct evbuffer *, void *));

View File

@ -63,7 +63,8 @@ struct evrpc {
const char* uri; const char* uri;
/* creates a new request structure */ /* creates a new request structure */
void *(*request_new)(void); void *(*request_new)(void *);
void *request_new_arg;
/* frees the request structure */ /* frees the request structure */
void (*request_free)(void *); void (*request_free)(void *);
@ -72,9 +73,10 @@ struct evrpc {
int (*request_unmarshal)(void *, struct evbuffer *); int (*request_unmarshal)(void *, struct evbuffer *);
/* creates a new reply structure */ /* creates a new reply structure */
void *(*reply_new)(void); void *(*reply_new)(void *);
void *reply_new_arg;
/* creates a new reply structure */ /* frees the reply structure */
void (*reply_free)(void *); void (*reply_free)(void *);
/* verifies that the reply is valid */ /* verifies that the reply is valid */