http://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html argues that multithreaded GUI frameworks are a failed dream. What about non-GUI frameworks? Does this rule of thumb extend to all event-driven frameworks?
Here is a quote from the article that caught my attention:
The problem of input event processing is that it tends to run in the opposite direction to most GUI activity. In general, GUI operations start at the top of a stack of library abstractions and go "down". I am operating on an abstract idea in my application that is expressed by some GUI objects, so I start off in my application and call into high-level GUI abstractions, that call into lower level GUI abstractions, that call into the ugly guts of the toolkit, and thence into the OS. In contrast, input events start of at the OS layer and are progressively dispatched "up" the abstraction layers, until they arrive in my application code.
Now, since we are using abstractions, we will naturally be doing locking separately within each abstraction. And unfortunately we have the classic lock ordering nightmare: we have two different kinds of activities going on that want to acquire locks in opposite orders. So deadlock is almost inevitable.
I'm wondering how much of the problem comes from the fact that multithreading is not appropriate for event-handling, and how much it is that many of the developers who build GUIs are not proficient with multithreading.
I tend to side with the later case, and also with chunkiness of some of the frameworks. For example, I find GUI code in Eclipse to be fairly annoying to write because there isn't a more convenient way to deal with heavy logic and GUI code.
In general, yes, since event driven frameworks are similar to the Reactor pattern, which stipulates a main loop which waits for events (the "event loop", and then invokes the registered callbacks for the various elements.
This is how event-driven frameworks have been traditionally defined. Here's a nice description about how Erlang processes are tied to the VM's event loop:
update: here's some interesting notes that were very influential on me at the time. Note in particular how locks and callbacks interact badly.
No. Even as a rule of thumb, it's simply saying "it's hard to make them work." But event-driven frameworks are very much like event-driven simulation and various other things; the fact that it's hard in Javaworld isn't a fact about multithreading, but about the abstractions available in Java.
In another environment, like Erlang, it's both fairly natural, are pretty robust.
Update
It still sounds like he has the wrong abstractions. I don't see anything inherent in the problem that forces a locking issue. The key, I think, come in here:
So why is deadlock almost inevitable? Because two different kinds of activities are going on that want to acquire locks in opposite orders. And that is because "we will naturally be doing locking separately within each abstractions."
In other words, he's chosen -- or had chosen for him by the environment -- abstractions that don't support his needs. It follows, he appears to claim, that thus there are no abstractions that would. I don't find this convincing. I'd start by examining two things:
In my experience, "naturally X" usually means "I haven't really looked for other options." And I very much doubt that the events want to acquire locks in opposite orders; yu get a lock, you do something, and you release it.
The point is, he appears to be presenting the fact that he finds it hard to come up with a scheme that does work as a theorem to say that no scheme can work.
Without a lot more details about the problem, it's hard to construct a counter-example, but as I said above, there are lots of examples of systems that have events going on every which way, asynchronously, from internal processes and GUIs, that manage to have many concurrent threads of control and don't deadlock. Erlang came to mind because one class of those problems, telephony, is the one for which Erlang was invented, and in fact those sorts of issues are why Erlang was invented.
This rule of thumb doesn't apply at all to non-GUI frameworks. See Welsh's SEDA architecture, see yield (code.google.com/p/yield) for a good python/c++ hybrid implemenation.
I would have to say no, with a caveat. Event driven frameworks that revolve around shared state, such as a UI, should be single threaded. Event driven frameworks that revolve around notifications, such mechanical monitoring(e.g. letting you know when the pressure in a pipe is too high), could be single threaded, but might be more appropriate to be multi threaded.
It is certainly possible to build a multi threaded UI framework, and I have done so myself. In the end I converted it to be single threaded. Part of the reason does fall under what Charlie said about "it's too hard". The problem was that with a multi-threaded UI framework, it wasn't just me that had to deal with the threading, but anyone that used the UI. The core was certainly thread safe, but then anyone that wrote a control had to make that thread safe as well. Nevermind that when making multiple changes to the UI, you had to notify the core that you were doing so so you didn't get partial updates. Since a user is generally a pretty slow thing, any performance gain was really negligible, and could be worked around with an asynchronous call if necessary for specific cases. Single threading is actually the appropriate model here.
On the other hand, in a model where there isn't(or isn't much) shared state, a multi threaded model makes eminent sense. There's no reason for one event(the reactor is on fire) to be delayed for the 30 seconds it takes for your query(Bob the operator just clocked out) to timeout because some yahoo in operations left the punch_card table locked.
Yes and No.
Event driven frameworks usually allow you to do things that usually require multiple threads with 1 thread. That's why they are usually single threaded.
However, it is not in any definition that an event driven framework cannot dispatch events to multiple threads.