>> I now need to finish the test/example application. >> When that's done, I'll upload. Might even be this weekend.
I've been working away. Got a wierd bug which is holding things up. >> Prototypes >> ========== >> 1. int socket_iocp_new( void **socket_iocp_state, size_t >> read_buffer_size, void (*accept_callback_function)(SOCKET socket, struct >> sockaddr *local_address, struct sockaddr *remote_address, void >> *listen_socket_user_state, void **per_socket_user_state), void >> (*recv_callback_function)(SOCKET socket, void *read_buffer, DWORD byte_count, void *per_socket_user_state), void >> (*send_callback_function)( SOCKET socket, void *per_socket_user_state, void *per_write_user_state ), void (*error_callback_function)(SOCKET socket, void *per_socket_user_state) ); > It looks to me like all your callbacks are asynchronous. Yes. > Is that the case? If so you're probably working off the standard iocp example code which spawns num_cpus/2 or num_cpus*2 or > f(num_cpus) threads, Yup, CPU count * 2. > however that's the sort of choice that > I think should be left to user, exposing instead an interface > int iocp_wait(long timeout) which calls the callbacks. Do you mean that the user goes off in his code, does his stuff, and when he's ready to deal with IOCP stuff, he calls iocp_wait() and the API is then free to call the callbacks, but it will be using the users thread to do this, and after "long timeout" has expired, iocp_wait() returns and the user continues with his code till he next calls iocp_wait()? > This > lets the user choose the "asynchronicity" of their app, > i.e. they can write singlethreaded mutex-less iocp code. Would it be possible to have a single threaded app which is trying to do C10K? > As an interface socket_iocp_new is a tiny bit "busy" as it > wraps almost every function that iocps understand. Yes. In fact, it's the longest prototype I've ever written. OTOH, when you actually write it, it's only six arguments. > A bit of > factoring might make it more friendly. A control-block style > interface could also help as it cuts down the argument list > and makes the "per socket user state" implicit (it actually > makes it per iocp operation user state). It also gives you > two way communication (user -> iocp library -> user in callback) > > typedef struct { > SOCKET s; /* <- */ > char* buf; /* <-, -> */ > long nbytes; /* <-, -> */ > void (*iocp_read_callback)(iocp_state* st, iocp_read* control_block); /* > <- */ > } iocp_read; > > The user can piggy back per operation data like so: > typedef struct { > iocp_read control_block; > /* extra stuff here */ > }my_iocp_read; > > void > my_iocp_read_callback)(iocp_state* st, iocp_read* control_block) { > my_iocp_read* my_cb = (my_iocp_read*)control_block; > /* respond, requeue, whatever */ > } This converts a large one-off complexity in the new() function into a smaller complexity which is required for every function call. Separately, ould it be useful to have per read state in the way that per write state exists? it seems to me since that reads are serial (only one read at a time per socket) that state will be kept by the user in the per socket state. _______________________________________________ Libevent-users mailing list Libevent-users@monkey.org http://monkey.org/mailman/listinfo/libevent-users