Why Isn't X11 Thread-Safe? 44
blackcoot asks: "I've just spent a couple very frustrating days trying to figure out what 'unexpected async reply' means and fixing it. The problem is a result of the fact that X11 simply isn't designed to handle events from more than one thread at a time. Why? Given that more and more often, people are writing multi-threaded GUI applications, are there fundamental design decisions in X11 that make dealing with receiving events from multiple threads simultaneously, impossible? Or was the protocol never designed to handle concurrent updates? More to the point, is there an easy way in Qt (short of deriving a new widget for every widget and overriding it's paintEvent to lock the library first, paint, then unlock as Trolltech's docs seem to suggest) to make this problem go away?" I'm not sure if things have been done in recent revisions of XFree to fix this problem, but this message, from February of last year, might help some of you out that are suffering from this problem. Any ideas if this problem has been fixed in recent versions of XFree?
don't use threads! (Score:0, Insightful)
GUIs are naturally event driven, there is no reason to use threads at all. just use an event loop.
Re:don't use threads! (Score:3, Insightful)
Re:don't use threads! (Score:4, Insightful)
If some events should have higher priority than others, your GUI thread should schedule them properly. It would be a grave design error for the X server to have to know about threads in the client, and their relative priority. However, finding yourself implementing a priority scheduler in user-space is often an indication that you have made a wrong turn in your architecture. Scheduling is what OSes are for.
As an alternative, the client is free to open multiple connections to the X server, and operate independent UIs through them. As far as the X server is concerned, it's talking to independent clients, something it is very good at.
Why add threads to xlib? (Score:3, Insightful)
Secondly, threading a GUI program is a Bad Idea -- there's lots of interaction between threads in a GUI, and locking could turn into a nightmare. All you do in a GUI is usually check a value, paint something, and you have to lock all the values that might be shared.
Thirdly, it doesn't make sense for an event-based GUI. You have a thread that handles incoming events, maybe starts a *non-GUI* thread if you're really wedded to the idea of threading, and then gets the hell back to waiting for another event pronto so that you don't have a lot of latency on user input. Here's an example, an instance that might seem *on the surface* like a good place to do threading if X were reentrant. You have a GUI ftp program. One thread handles events, and each thread would download data and update the progress bar by repainting it. Bad idea. Now if I require a redraw, I have to sit around and wait for more data to come in. What I *really* want to have happen is have a counter for how far the progress bar is. When I require an update (periodically, and when a redraw is required), the GUI thread does it, checking the progress distance value. The non-GUI thread doing the transfer would set that value (in addition to a "dirty" flag) so that I get updates once a second or so, not 400 times a second if lots of little chunks of data are coming in. The GUI is simply a separate task from non-GUI tasks.
Re:Multi-threading is GOOD [was Re:What I do] (Score:1, Insightful)
Sure, when you're forced into a coding style out of the 1970's or earlier and have to write all the conditions, mutexes, semaphores, synchronizations, and so forth yourself.
I think the poster demonstrated quite plainly how much easier it is to write multithreaded code when the language and runtime actually supports it. I'll repeat what he said:
while (buttonisdown) followmouse()
Gets neater than that in languages that support generators. In haskell you filter out the events you want as a list comprehension over the list of events.
> There's no reason why an application needs to have a multi-threaded GUI.
There's no reason for you to have anything more than assembly code. If it makes you feel better, put a multithreaded GUI into one big synchronized block. The world is too full of people making excuses for obsolete design by saying it was meant to be that way forever.