[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
NSRunLoop Tidying
From: |
David Chisnall |
Subject: |
NSRunLoop Tidying |
Date: |
Fri, 8 Oct 2010 13:24:41 +0100 |
Hi Everyone,
One of the things that has been on my to-do list for a long time is tidying up
NSRunLoop. The current implementation predates modern event delivery
mechanisms and tries to shoe-horn the UNIX approach everywhere.
Modern systems include a unified mechanism for event delivery, and a lot of the
hacks to work around the fact that older *NIX systems didn't have these are
complicating the code a lot on these platforms.
My main motivation for doing this is to support the KQueue APIs on *BSD. This
provides a single function for waiting on every kind of event. Windows has had
something similar forever, Linux can do the same thing with timerfd in recent
versions, and Solaris has completion ports, which provide similar functionality.
As I understand it, there are four kinds of things that a runloop has to handle:
1) Events on a file descriptor (read / write).
2) Timers expiring.
3) Timeout expiring (e.g. -runMode:beforeDate:)
4) Messages from threads.
Of these, (3) is trivial. All wait mechanisms support this, so implementing it
is trivial with any underlying mechanism. Similarly, (1) is the default case
for pretty much all of the event-waiting calls, so it's simple.
Currently, (2) is implemented in terms of (3). This is quite untidy. It means
that we need to maintain an ordered list of timers in the runloop code, find
the one closest to the present, and then use this as the timeout. This is
required with traditional select() and poll(), but Win32 has SetTimer, Linux
has timerfd(), and *BSD has kevent(), all of which allow you to schedule timer
events and wait on them just like fd events.
(4) is trivial on Windows, via PostThreadMessage(), which allows you to deliver
a message to a specific thread. Kqueue has a EVFILT_USER, which allows you to
deliver events to other threads, and Solaris 10 event ports have something
similar.
To properly support efficient native APIs, we should move the handling of all
of these into the per-platform code and remove anything platform-specific from
the general code in -base. There are lots of random #ifdefs scattered about
the place currently.
My overall plan is:
- Move -addTimer:forMode: into the platform-specific code.
- Tidy up the GSRunLoopCtx stuff so it isn't quite so full of #ifdefs.
- Make the NSObject methods in NSThread.m call (private) runloop methods that
delegate to the platform-specific code.
- Remove classes like GSPerformHolder from the generic code.
- Implement a kqueue back end for *BSD.
- Make the win32 back end use SetTimer() and PostThreadMessage().
Comments / suggestions?
David
- NSRunLoop Tidying,
David Chisnall <=