I have seen a lot of ideas flowing back and forth during this
discussion. I think the problem is that many of the ideas have been
kind of mixed together so it is hard to talk about them and there is a
lot of muddling going on because some people like call backs and some
like a queue and so the real ideas are being confused with those two
nearly equivalent methods of delivering events. I also think there
has been a bit much focus on the details of specific implementations
and not enough focus on the differences between the different possible
implementations. SDL has to work across at least 3 main OSes and a
bunch of others and the differences are what cause many of the design
decisions.
By the way, I’m going with the “get next event” way (AKA “the current
way”) rather than “register callbacks then call a run loop” way.
And you are quite right that they are mostly equivalent (what I call
callback-driven is still synchronous, the callbacks happen one after
the other, and so on).
I’m just going to remove the SDL event queue from the main code path
(leaving it for inter-thread communication, and a few other special
occasions). Even when not using the SDL event queue, I know there will
still be queueing, just not done by us.
Before I go on I want to make sure that people understand why there
are queues anywhere in any system. They are there to buffer the
difference in production and consumption rates between the things at
each end of the queue. Why do we stand in a queue to buy movie tickets
(Ok, the real answer is because we didn’t think to buy them online
:-)? Because the people selling tickets can process each transaction
in about the same amount of time but people show up at a random rate.
Oh, here’s an analogy I can reuse! Using the SDL queue is like
standing in a queue (the OS queue) to get a ticket with a number, then
going in a waiting room (the SDL event queue) until they call your
number (still just one at a time). My point is that events don’t mind
standing up (and in fact, the “sitting down” involves copying data,
which isn’t free), we’d be better off just dealing with them instead
of giving them a ticket.
- The current implementation of the event queue in SDL adds latency.
No. The current implementation of SDL_WaitEvent adds latency. If your
application does not use SDL_WaitEvent, then you’re safe from that
latency (and you’re probably eating all the CPU, which might be okay
if you’re writing a first-person shooter, but less so if you’re
writing a dinky action puzzle game).
- The current implementation of the event queue in SDL is based on a
10+ year old world view. The hardware and the related OS APIs have
changed since it was originally written.
It’s a bit more subtle and weird than this. The hardware and APIs are
pretty much the same as 10 years ago (NextStep/Cocoa was first
available in 1986, and programs from 1990ish still mostly compile and
run!), but game developers were still programming their games based on
a 10+ years old world view back then (assuming PIO, and asking
things like “how can I wait for the vertical retrace?”), so SDL
catered to them (which is quite the right thing to do).
I was kind of hoping that things (well, mindsets) had changed, and it
seems that it isn’t really the case. So it’s worth making the extra
effort to provide what game developers expect (and I can stack my own
callback dispatch on top if I feel like it).
- Using the newer APIs it may be possible to get rid of the SDL queue
completely and just use the platform APIs.
I.e. it may be possible to make the current event oriented SDL API
into a thin layer over existing OS/Platform APIs.
It could be possible to get rid of the SDL queue completely, but I
think it would enforce too many restrictions (basically, the
intersection of what you can put in a “user message” event on all the
supported platforms, and this could potentially shrink when adding
another platform, which would kill backward compatibility), so I’d
still keep one, but it would only used for the SDL_PushEvent messages,
so essentially, messages coming from other threads, most of the time,
or synthetic messages (pretty rare, I’d venture).
To ensure an effect similar to the condition variable that you used in
fastevents, the driver for each platform would have to supply a “wake
up SDL_WaitEvent” method, which could potentially use a "user message"
event specific to the platform that just says “hey, go look at the SDL
queue, there’s stuff for you there!”.
After that it starts getting real confusing to me… It seems some
of the APIs would are best suited to be used in a callback based event
delivery system and some are best suited to delivering events into a
queue. And, of course it is easy to use callbacks to deliver events to
a queue and equally easy to use a queue to make call backs.
It’s the last bit I disagree with. It’s not equally easy to use
callbacks to deliver events to a queue than to fetch events from a
queue to dispatch callbacks. But it’s not so ridiculously difficult
that I’m not willing to pay the small overhead so that everyone is
much happier and SDL is successful.
Basically, there’s two forces: we’d like SDL to be as close to the
metal as possible, while providing an API/behaviour that’s as
consistent as possible from one platform to the other, and we want the
API provided by SDL to be as flexible as possible so that games can be
ported to it and written for it easily. Callbacks favour the former,
and SDL_PollEvent/SDL_WaitEvent favours the latter, and I think the
little bit of “padding” between the metal and the SDL user isn’t
significant enough after all to limit the flexibility of the API so
much (remember that it’s easy to convert a queue API into a callback
API, but the reverse less so, so if we provide a callback interface,
the pain will be for the application rather than us).On Tue, Jan 13, 2009 at 1:14 PM, Bob Pendleton wrote:
–
http://pphaneuf.livejournal.com/