On Tue, Dec 18, 2007 at 09:38:45AM +1000, Anton Umnikov <[EMAIL PROTECTED]> 
wrote:
> How to change watched events? For example I want to implement POP3-like 
> protocol. Accepted socket must watch EV_READ for command and EV _WRITE for
> reply. So I need change watched events on every state of conversation in his 
> callback.  Something like

Hi, thanks for sending in actual code. It is very close to working.

The documentation says that invoking the set or init functions is only valid
when the watcher is stopped, so you need to do exactly that, e.g.

> void my_sock_cb (ev_io *sock, int what)

(likely wrong prototype, see below)

>          my_ev_io  *my = (my_ev_io *)sock;
>          if (what & EV_ERROR)

(Checking for an error is good :)

>        if (what & EV_READ)
>       {
>   /* read and process client's command */
>                read (sock->fd, buf, my->buf_size);
>                ....
>                strcpy (my->buf, "OK\n");
>                 my->len = strlen (buf);

add here:
                 ev_io_stop (EV_A_ sock);

to stop the watcher temporarily.

>                ev_io_set (&sock, EV_WRITE);

this is a bug, you need to pass in the _address of the watcher_, not the
_address of the address_ of the watcher, i.e.:

                 ev_io_set (sock, EV_WRITE);

then add:

                 ev_io_stop (EV_A_ sock);

to start it again.

>             ev_io_set (&sock, EV_READ);

likewise here in the write path.

>       ev_io_init ((ev_io *)data,  my_io_cb, fd, EV_READ);
>       ev_io_start (ev_default_loop (0), (ev_io *)data);
> 
> Is it correct?

Almost, because your callback doesn't declare the initial loop argument.
that you need to use when using EV_MULTIPLICITY (which is typical and the
default).

To correct the prototype, use this one:

   void my_sock_cb (EV_P_ ev_io *sock, int what)

To summarise, instead of ev_io_set on an active watcher, you need to:

   ev_io_stop (EV_A_ w);
   ev_io_set (w, ...);
   ev_io_start (EV_A_ w);

otherwise your code was quite fine ignoring the loop argument problems.

Another approach that might come in handy is to use two io watchers, one
for EV_READ and another for EV_WRITE (they are relatively small), but when
"subclassing" watchers the one-watcher approach is usually better (you
still often want an ev_timer for timeout purposes, too, though).

If you have other questions, feel free to ask them. Providing source
examples is a good way to get good feedback, as it makes it clearer what
the problem might be :)

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      [EMAIL PROTECTED]
      -=====/_/_//_/\_,_/ /_/\_\

_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev

Reply via email to