views:

28

answers:

1

Hi everyone,

I'm using kqueue for socket synchronization in OS X. I can register an event of interest like the following:

struct kevent change;
EV_SET(&change, connected_socket, EVFILT_READ, EV_ADD, 0, NULL, NULL);
kevent(k_queue_, &change, 1, NULL, 0, NULL);

And the question is, is there a way to trigger this event by force so that the waiting kevent call would return?

+1  A: 

Some possibilities aside from natural writing of data to the other side of the socket :)

  • shutdown(2) the read side of that socket - you'll get EV_EOF in flags (silly),
  • Use the timeout argument and call the same handling function,
  • Use the self-pipe trick when you need to break the wait.

My question though: why do you need this?

Edit:

If I understand your comments correctly you are looking for a way to get around edge-triggered behavior (EV_CLEAR) for write events. I believe that the proper way of doing this is to un-register your socket from EVFILT_WRITE when you don't have anything in the outgoing queue, then re-register it again when there's data to send. It's a bit more work, but that's how it works, and you don't need any additional system calls since kevent(2) accepts both changes and results. Take a look into libevent and see how it handles this sort of stuff. And you are using non-blocking sockets, right?

Nikolai N Fetissov
Thanks for the answer, Nikolai. I'm writing an application server, and I don't want to block any thread for reading/writing to the socket. Reading is simple. There's one io thread and whenever something comes in to the sockets, it will wake up from kevent and read the data so that other worker threads could handle it.
Kay
But writing is more complicated since even if the io thread wakes up because there's some space available on the socket, there might not be anything to write in the outgoing data queue. So I'd like to make the io thread return from kevent by force whenever we write something to the outgoing data queue. Does this make sense?
Kay
@Kay, I added some more to the answer.
Nikolai N Fetissov
Oh you're right. And I'm a little bit confused. Is EVFILT_WRITE edge-triggered or level-triggered by default? If I understand your comment correctly, it's level-triggered by default and it will keep waking up and consume the CPU when the socket is empty and the outgoing queue is empty too, so I should explicitly make it edge-triggered by setting the EV_CLEAR flag and do the trick you said. Is this correct?
Kay
Yes, correct. Everything is level-triggered by default, as in `select(2)` and `poll(2)`. Good luck!
Nikolai N Fetissov