Re: Are kqueue events "round robin"?
Re: Are kqueue events "round robin"?
- Subject: Re: Are kqueue events "round robin"?
- From: Påhl Melin <email@hidden>
- Date: Mon, 6 Apr 2009 13:12:42 +0200
2009/4/2 A.M. <email@hidden>:
> On Apr 2, 2009, at 11:07 AM, Påhl Melin wrote:
>> Hi all,
>>
>> I have a question regarding the order events are returned from a
>> kevent() call on a kqueue, if I only supply one event in the event
>> list and no events are changed? Is there a predefined order in which
>> the filters are processed and returned as events when there are
>> multiple events available at the same time?
>>
>> For example if I have two filters, one EVFILT_READ filter and one
>> EVFILT_WRITE filter and there is available room in both the read and
>> the write buffers. If I make four subsequent calls, in what order will
>> the events be returned? Will I get EVFILT_READ, EVFILT_WRITE,
>> EVFILT_READ, EVFILT_WRITE? Or will I e.g. get one of the events
>> repeatedly until that buffer is empty/full, like EVFILT_READ until I
>> have read everything in the read buffer? Or is random or some other
>> algorithm?
>>
>> What I want to do is to alternate between read and write events to get
>> good responsiveness. I suppose I could change the events in the kqueue
>> but it would be easier to rely on some guaranteed behavior.
>
> The order you receive is the order that the kernel put the events in the
> queue- that is, after all, what makes it a k*queue*. If this is socket
> communications, you will get spammed with EVFILT_WRITE events as long as the
> socket buffer is full; however, this does not imply that you will get no
> read events in between. But you should selectively enable and disable
> EVFILT_WRITE events based on whether or not you actually have stuffed the
> socket buffer (when the non-blocking socket I/O returns fewer bytes than
> what you passed in).
I'm writing a messaging framework that sends asynchronous messages
between processes on a local machine using Unix Domain Sockets and
between machines using normal TCP/IP sockets. My idea was to use a
design where I keep an open socket between two nodes and have one
"service" thread handling the communication on the socket using a
kqueue and looping around a kevent() call. When there are outgoing
commands present, the thread enables the EVFILT_WRITE filter and waits
for available space in the write buffer. When all commands are written
to the socket, the EVFILT_WRITE filter is disabled.
At the same time I also would have a EVFILT_READ enabled, receiving
incoming replies for the commands and also asynchronous incoming
messages. In a very simplified form without error checking, my loop
would look like this:
for (;;) {
numberOfEvents = kevent(kq, NULL, 0, &event, 1, NUL);
if (event.filter == EVFILT_READ) {
// handle read events
}
else if (event.filter == EVFILT_WRITE) {
// handle write events
}
}
In the read and write event handling I would read or write a few bytes
for the current command and I would then continue the loop waiting in
the kevent() statement again. When I have multiple commands and
replies I assume that the kevent() would return immediately with the
data member containing the remaining bytes to be read (or space left
in the write buffer).
I would expect the kqueue not to be filled up with EVFILT_READ and
EVFILT_WRITE events, but to have only one of each whenever the buffers
are "ready". But the question is if I'm guaranteed to have alternating
read and write events? Or if I get starvation of any kind? I don't see
anything about this matter in the man pages so I'm curious if it's
specified at all?
> I haven't experienced any event starvation situation, but in case you have,
> the best approach would be to implement an array over kqueue. Simply read
> more than one event into your own queue and you can algortithmically decide
> which events to process (and then remove them from the array- obviously it's
> no longer a queue). But don't waste time implementing this approach unless
> you are indeed experiencing starvation.
Thanks, I hadn't really considered returning multiple events and make
my own decision. But it would of course be easier if a reasonable
decision was already made by the kevent() call.
> Since one thread can only do so much, if you have lots of socket or sources,
> then you may want to break their processing into separate thread (kqueue is
> thread-safe and works well across multiple threads). Even a single socket
> read and write events could be broken out across threads.
That's interesting. I what sense is kqueue thread safe? Can I wait on
the same kqueue in two different threads, each calling kevent() or do
I make two kqueue:s, one with a read filter and the other queue with a
write event on the same socket descriptor?
> Cheers,
> M
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden