-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
eliminate czmq dependency in public api #219
Conversation
Wow, large amount of work for a weekend! Before a thorough review, a couple things come to mind:
|
Sorry, it looks like more work that it was because I didn't squash down the small commits. Memory management is changed: send takes a const flux_msg_t and does not destroy it. My goal is to eliminate that destroy-on-send behavior as I think we agreed was better. I haven't yet made it to the reactor message handler function prototype though, which is sort of based on that. I renamed |
I had thought I should take care of the reactor prototypes in this PR as well, but that is shaping up to be a big job, so I think it might be better to carry that over into another PR. Here are some todos for this PR.
|
Argh, it seems that
I noticed that in a function defined like this:
I can pass
and change all those I advocated for this style in RFC 7. Any thoughts? |
heh. I personally prefer the first answer in that post and tend to just pass I'm not fond of the change to typedef struct _zmsg_t flux_msg_t because it doesn't seem consistent with other things we've done (though there is already the odd case of In this case my personal preference would be to keep Again, I'm just expressing my thoughts here and could easily be swayed |
I personally agree with the stackoverflow post for the reasons stated. But I'm an even bigger fan of consistency. So, given that you're basing flux_msg_t off zmsg_t, I would agree that flux_msg_t probably should match zmsg_t. You can then update RFC 7. |
For the record, I think I hate to sacrifice
and then making arguments |
@garlick, that seems reasonable to me. I would just be a little careful about having some typedef types ( |
We can use |
probably getting out of bounds here, but could you declare a second type typedef const struct flux_msg_struct * flux_msg_const_t; To use in reactor callbacks where I don't know, just another idea to throw out there for enforcing const-ness for API users (I like your idea above internally) note: Uhhh, I didn't even try this before I proposed it, so it may not work |
btw, on why this doesn't "just work" as expected with |
|
Just pushed some changes for Have a look and see what you think. We can certainly change it. I may be over-valuing the const protection since I anticipate converting a lot of code from the destroy-on-send idiom, which will all be over soon, and then we'll be stuck with people using this. |
One preemptive comment re: the casts to (zmsg_t *) in message.c: these are not the droids you're looking for, that's an artifact of transition. |
I just saw this significant number of posts, what is the reasoning for preferring a typedef that looks like a struct but is actually a pointer over passing pointers to actual structs? Just as a personal preference, I tend to want any pointer to be visibly a pointer and get rid of the unnecessary Is there a quantifiable benefit to hiding the pointer? |
Just to be clear, you are arguing for something like: typedef struct flux_msg_struct flux_msg_t; and arguments of |
Correct. It's the way all of the czmq types are handled, and while I On 9 Jun 2015, at 15:40, Jim Garlick wrote:
|
To be honest I hadn't considered that obscuring the pointer would cause confusion, but you make some good points, and the |
Hm, as previously stated I tend to agree about not hiding pointers. I think hiding the If you are already using In this case, I kind of dislike As an aside, I would more strongly argue for not using |
No reason not to drop the typedef on The |
Sorry, yeah good points. I kind of realize my last comment was a bit more strongly worded than I intended. I meant to give my personal preference, and I'm fine with |
Yeah me too after the rude awakening on const. OK, lets not hide the pointer but keep the typedef. We're not consistent with some other flux_foo_t types but we can circle back and fix that to be consistent. I'll update the RFC also. Thanks everybody for the input, I was in the weeds on this one, sadly. |
I just forced an update on this PR with the following changes:
The interface proposed for reactor message handlers is implemented along side the old one (actually the old is implemented in terms of the new). Here's the gist of the interface: typedef struct flux_actor flux_actor_t;
typedef void (*flux_msg_f)(flux_t h, const flux_actor_t *actor,
const flux_msg_t *msg, void *arg);
flux_actor_t *flux_actor_add (flux_t h, struct flux_match match,
flux_msg_f cb, void *arg);
void flux_actor_remove (flux_t h, flux_actor_t *actor); The changes from FluxMsgHandler are:
I'm not attached to the naming. To avoid upheaval I needed to leave the existing registration functions alone and needed to invent a name for the thing to be used as a handle for the registration, and actor seemed to fit the role of a message handler. This is just a first cut - I haven't really used this yet anywhere. |
I think "actor" probably implies an agent operating in its own thread so I'm looking for a different word here besides "msghandler". |
I would agree that actor has implications of concurrency. Maybe "responder?" That has some baggage too, but it seems apt somehow. |
The message callbacks might also be handling a response message or an event message, so "responder" seems too specific to me. What about just naming it a callback or "cb" -- I also think it would be helpful to look at the reactor interface as a whole, instead of just message handling. I'm assuming there will be replacements for fd and timeout handlers as well? (for each of these, "callback" might work as well. I would feel better if we had a plan for whole reactor api. Is there some idiom of construction and naming that we could borrow from libev? |
might also want to review dicussion in #124 |
I was thinking we could repeat the same design for fd's, zeromq sockets, and timers. Callbacks would have a similar signature, e.g. say we go with the "cb" idea, typedef void (*flux_msg_cb_f)(flux_t h, flux_msg_cb_t *r,
const flux_msg_t *msg, void *arg);
typedef void (*flux_fd_cb_f)(flux_t h, flux_fd_cb_t *r,
int fd, int revents, void *arg);
typedef void (*flux_zmq_cb_f)(flux_t h, flux_zmq_cb_t *r,
void *zmq_socket, int revents, void *arg);
typedef void (*flux_timer_cb_f)(flux_t h, flux_timer_cb_t *,
void *arg); Reg/unreg functions would follow suit flux_msg_cb_t *flux_msg_cb_add (flux_t h, struct flux_match match,
flux_msg_cb_f cb, void *arg);
void flux_msg_cb_remove (flux_t h, flux_msg_cb_t *r);
flux_fd_cb_t *flux_fd_cb_add (flux_t h, int fd, int events,
flux_fd_cb_f cb, void *arg);
void flux_fd_cb_remove (flux_t h, flux_fd_cb_t *r);
flux_zmq_cb_t *flux_zmq_cb_add (flux_t h, void *zsock, int events,
flux_zmq_cb_f cb, void *arg);
void flux_zmq_cb_remove (flux_t h, flux_zmq_cb_t *r);
flux_timer_cb_t *flux_timer_cb_add (flux_t h, double seconds,
flux_timer_cb_f cb, void *arg);
void flux_timer_cb_remove (flux_t h, flux_zmq_timer_t *r); This is fairly similar to the libev "watchers", in that there is a different (though similar) callback signature for each watcher type, and a type specific handle that is passed to the callback and can be used for cancellation. There are two aspects of libev that I sort of like that aren't used here and maybe should be considered?
|
Instead of (zctx_t *) use (struct _zctx *) with struct _zctx, an incomplete type.
Rename these types: red_t -> flux_red_t FluxRedFn -> flux_red_f FluxSinkFn -> flux_sink_f Add a new type as the arg to flux_red_f instead of zlist_t flux_redstack_t Add simple stack interface for flux_redstack_t flux_redstack_push() flux_redstack_pop() flux_redstack_count()
Also drop unnecessary (FluxFreeFn) cast from cmd/flux-jstat modules/api modules/kvs modules/libjstat modules/live modules/barrier modules/wreck test/* libflux/flux_log This seemed better than changing the cast to the new name.
define flux_msg_t in terms of incomplete struct _zmsg_t. Convert all public libflux headers to use flux_msg_t not (zmsg_t *) and drop <czmq.h>. Add flux_msg_destroy().
Replace flux_putmsg() and flux_pushmsg() with flux_requeue(). Also replace the corresponding handle implemention methods. Update users in: libflux/rpc libflux/reactor connectors/loop connectors/local broker/modhandle test/request
Update users in connectors/local modules/api test/tenc
flux_send(), which does not destroy the message on success, will replace flux_sendmsg(). (flux_sendmsg() will be available during transition). Define corresponding handle implementation methods. Update these users: connectors/local connectors/loop broker broker/modhandle libflux/response libflux/rpc
Add flux_recv(), which will replace flux_recvmsg(). The main difference is it accets flags rather than a boolean 'nonblock' argument. flux_recvmsg() remains during transition, implemented in terms of flux_recv(). Add corresponding handle implementation methods. Define FLUX_O_NONBLOCK flag. Update the following users broker/modhandle connectors/loop connectors/local libflux/rpc flux/reactor
Flags supplied to flux_open() at handle creation are logical or'ed with flags supplied to flux_send() and flux_recv().
Rather than defining the flux_msg_t type as a pointer to an incomplete struct, define it directly to the incomplete struct. This allows const to work properly and avoids obscuring the fact that we are dealing with a pointer. Add const qualifier to function parameters where appropriate, especially in message.[ch], request.[ch], response.[ch], event.[ch]. Update users: broker module handle, and connectors.
Use 'struct flux_match' directly instead. Update various users.
We had some code that enables the reactor code to be split out of handle.c that crept into the public API. * drop flux_ prefix and move function prototypes to non-installed reactor_impl.h: reactor_create(), reactor_destroy(), reactor_get() * drop unnecessary abstract reactor_t type for "struct reactor". * rearrange function order in reactor.h for clarity, and drop "tmout" prototypes for functions long ago removed
I think this is probably mergable (my $0.02). |
Ok, I'll merge this. Is there a corresponding update for flux-sched as well? (Or is that not needed in this case?) |
Wasn't supposed to need one, but it turns out a minor one is needed since FluxFreeFn was renamed to flux_free_f and it is used in a cast. I'll submit a PR on that. |
Ok, then merging this one so your flux-sched PR passes travis |
eliminate czmq dependency in public api
Thanks @grondo I should comment that actually we will want to do a flux-sched PR to update its API usage. However since json-c stuff remains in |
How much use of |
There is not a large amount of API usage in there. The bigger problem is reliance on convenience stuff in libutil and libjsonc if I recall. |
As discussed in #168, this PR replaces
zmsg_t *
in the Flux public API withflux_msg_t
. This PR is for feedback not for merging.Right now,
flux_msg_t
andzmsg_t *
are interchangeable, both defined in terms of the same incomplete typestruct _zmsg_t
. This makes transitioning a bit easier. Although internally there are still a lot of zmsgs, I believe after this PR libflux-core should no longer require users to link against czmq/zeromq.Freed from following czmq's API design so much, some public Flux interfaces were also changed (improved?)
There is one new message function:
There are new low-level send/recv functions:
These replace the following functions (still available during transition):