[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: about RunLoop, joystick support and so on

From: Richard Frith-Macdonald
Subject: Re: about RunLoop, joystick support and so on
Date: Tue, 13 Feb 2007 21:19:19 +0000

On 13 Feb 2007, at 19:53, Xavier Glattard wrote:

I posted here some days ago more details about this opengl program.
If you need more, just ask. Did you launch it ?
It behaves as if the runLoop would block waiting for event from the gui while some performers or user events are waiting. Under x11 only windows with non retain backing store are faulty with 'Performers', 'Events&Perf'
and 'Events&Timer' methods.

I ran it on gnu/linux and it looked very good but the menu and the controls on the window stopped operating ... I haven't had time to really look at the code and figure out why.

Under w32 i just remember than the program
doesnt work properly in many more cases. You can select the backing store
in the menu.

I tried building under win32, but failed with a lot of link errors. I'm probably missing an essential library.

The  only difference I see is that GWRLWatcher handles _blocks_ of
bytes while
NSStream handles _streams_ of bytes.

No, a watcher does not handle bytes at all.  It detects whether an
event has occurred (eg a file descriptor becoming readable) and
informs its delegate so that the delegate can handle any data transfer.

But it does handle data under w32 since it returns the message as
the 'extra' argument of receivedEvent. Another weird behavior of the w32

Yeah ... the windows operating system APIs do not fit easily with the OpenStep system ... but in a way the watcher isn't handling data (it doesn't read or write any bytes), it's just passing on a pointer to the message in the windows message queue (analagous to passing the file descriptor for a unix file event) and leaving its delegate to actually process the message and retrieve information from it.

What you seem to be describing here is either a blocking or an
actively polling model ...
the app asks the server for an event,
the server checks the windows or X queue and if there is an event,
parses and returns it.
If there is NOT an event, then either
1. (polling) a nil event is returned and the app asks again or
2. (blocking) the server waits until an event arrives, then returns that

Is there an other way ?
That what the runLoop does : polls/selects for a limited period of time,
until a timer has to be fired.

The runloop uses a poll() or select() or WaitForMultipleObjects() call to perform an idle wait for *all* events the program is currently interested in. That means that it does not do a busy poll using up the CPU with repeated calls, and it does not block waiting for a single event source, preventing other events from being received.

If you look at the API and documentation you will find that it *has*
an event queue.  Sure, the whole system could be designed and
implemented differently, but that's what the design of the OpenStep/
MacOS-X/GNUstep AppKit/GUI library happens to be.

I can't see any event _in_ the NSApplication. NSApp gets events from a
queue, post event to a queue, but we dont know where is this queue. I
think it should be in the server. And it is!

The point was, that we have to have an event queue, and it has to have certain characteristics. I wasn't saying *where* the queue is implemented (for instance you could argue that it's implemented in the base library since it's an instance of the NSMutableArray class, but that would be irrelevant).

From the point of view of the main public API it's in the NSApplication instance and is accessible using NSApplication methods like -nextEventMatchingMask:untilDate:inMode:dequeue: which have certain implications such as the ability to extract events from within the queue rather than just from the end. The characteristics that the queue has to have (picking items out of the queue rather than just from the front, and accessing items in the queue without necessarily removing them from it) are not those typical of a stream.

One problem is that the different queues (gui events, performers,
socket events...) are not handled by one only object.
When GSDisplay is asked for an event by the NSApp it returns one
from its queue or, if none is available, calls the runLoop. So the
runLoop doesn't manage the gui event queue and so has not all the

That's perhaps a bug ... as I understand it the code it supposed to return an X or windows event if it has already been received, and if no event has been received, call the runloop to wait for more events. As long as that is working it's fine, but if the attempt to check for an event already received also does a read to get new events, then there is indeed the problem you describe of the runloop never being called. If this is happening, it's not a bug in the runloop, just a subtle bug in the backend (in that it is failing to run the runloop when it should). Such a bug ought to be fairly easy to fix ... a crude fix would be to run the runloop once before fetching each item from the windows message queue or X event queue. A more efficient option might be to use different calls to examine the windows/X event queues (ones that don't read in new events), or to count the events available each time the runloop signals event availability, and re-run therunloop after the count of events has been processed.

I thought of NSStream as a way to include gui event management
in the runLoop, at the same level as performers, NSPort and so on.
At present if for any reason the server event queue is always filled
up (by a user loop : select 'events(pure)' in my tool), the runLoop
is _never_ run.

I think that may be the 'correct' behavior (by 'correct' I mean what the documentation says and MacOS-X does). The programming model seems to expect that you should empty the queue before trying to receive any more events. So if you call the -postEvent:... method of NSApplication, you add an event to the application event queue, and if the code to handle that event then posts a new one then obviously you never empty the event queue and you just loop forever. Could that be what's happening?

MacOS is unix based. So everything come from file descriptors.
Also Mach messages and system-V IPC I think.
And a
NSStream is a tiny layer over that. Under unix, GNUstep use 'select'
on some file descriptors. So why not using NSStream ?

But really, it's not that important.

I dont want to hide the windows stuff. I only suggest to _reduce_ the
windows stuff. Then you'd not need many windows programmers : GNUstep
programmers would do the job. :-)

Sounds reasonable.

Furthermore it would be easier to create a new backend if it hasn't
to do so much : DirectFB, Opie/Qtopia, SDL, ...

The runloop can't manage X event messages (because it knows nothing
about X), so I guess you mean that the NSStream subclass would manage

That what i have in mind at first. But in the diagram i posted all
the system stuff is in the server.

That really just means that you are taking all the code for handling
incoming events from the GSDisplayServer subclass and putting it in a
different class (a subclass of NSStream).  Of course, in order to
convert from X events to NSEvents that stream subclass will also need
to know something about the state of requested made by the GUI to the
backend,  and will need other internals of GSDisplayServer (eg to
convert from X window coordinates to NSWindow coordinates), so the
code still in the GSDisplayServer subclass will have to be tightly
coupled with the code in the NSStream subclass.  And the  NSStream
subclass will not be usable except in conjunction with the GSDisplay
server subclass ... so all that has been achieved is to split the
GSDisplayServer into two slightly more complex parts.

You're right, that was stupid. So i change my mind... ;-)
In the diagram i posted this morning the GSEventStream is not system

IMO it is legitmate for the backend code to make use of the public
APIs of the frontend.

I doesn't agree. Having two libraries referencing each other is bad ;-)

If we were talking about two normal libraries, I'd agree, but we are really talking about one library (the AppKit in Cocoa) which happens to be built as a main part (gnustep-gui) with alternative modules (gnustep-back).

In a perfect world, the backend could be use without Appkit. It should
be a black box with a given interface and any program that knows this
interface should be able to use it. The backend should even never
include any AppKit header... For instance NSEvent should be based on
(or should use) a GSEvent class (i'm a fundamentalist ;-)

That's OK ... but there is no practical pressure to be able to use the backend indepedently of the gui, so I don't think you *have* to take that view. I'm perfectly happy with avoiding calls from back to gui methods ... but that does involve changing the interface to pass more information in both directions, and since nobody (afaik) wants to use back standalone, there seems little to be gained by adding to the interface rather than using existing gui api.

identifying places where the behaviors of the backends differ, and
trying to make them consistet would be really good.

At first : determining what _is_ a good behavior : what a
displayServer should do, what it should not. It would be easy to
take the common part, then exclude what can be done elsewhere
(if any). Then clean up the code.

Looking at the Quartz API that Apple did may be a good guide ... I don't really know though.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]