BeOS did this fairly well, although I would say the biggest problem is when you activate the UI and the underlying app has become unresponsive... When your app crashes, you want your UI to reflect the crashed state of the app and similarly become unresponsive.
The developers of BeOS went on to do Android and went with the single thread model, partly because BeOS had a big problems with buggy apps full of race conditions and deadlocks. Though IMO the Android API is incredibly confusing for a lot of developers. I've found very often that some devs (the more junior ones) don't understand that services and activities are just objects all hanging off a single process and event…
Multithreaded toolkits: A failed dream? (2004)
51–60 of 64 posts
Re: Multithreaded toolkits: A failed dream? (2004)
#52Earlier quoted context omitted.
The developers of BeOS went on to do Android and went with the single thread model, partly because BeOS had a big problems with buggy apps full of race conditions and deadlocks. Though IMO the Android API is incredibly confusing for a lot of developers. I've found very often that some devs (the more junior ones) don't understand that services and activities are just objects all hanging off a single process and event…
> The developers of BeOS went on to do Android I haven't heard of this before, so I went searching. The only pieces I could find are: Several ex-Be employees went to work for Danger after the company told to Palm. Some of them moved on to Android, which was co-founded by Danger co-founder Andy Rubin and acquired by Google. Others stayed on at Palm, but ended up joining Google after PalmSource (which was spun out of P…
Re: Multithreaded toolkits: A failed dream? (2004)
#53Re: Multithreaded toolkits: A failed dream? (2004)
#54Earlier quoted context omitted.
You don't need a multi-threaded GUI for that. You can have the GUI running on one thread while the task runs on another.
Sure. You put a message queue in there and create command objects for all the updates that tasks might want to make to the UI. It's not hard; in fact it's thoroughly mechanical, so it's exceedingly tedious to program. So why isn't the computer doing it for me? I'd happily sacrifice some performance if I could just write the change I wanted to make in the thread where I wanted to make it, and have the computer take ca…
An astute observer will also note that at the bottom of every Win32 program is a message loop monitoring events such as for when the window is closed.
Re: Multithreaded toolkits: A failed dream? (2004)
#55Well, its also a poorly motivated dream unless you have a sexual fetish for the Java style of abstraction where everything is completely independent. Who the heck wants multi-threaded GUIs? User interaction proceeds sequentially, so most objects don't require locks. The rare exceptions in my software is rendering or IO on a separate thread, and these don't nicely fit abstraction models, as mentioned in other posts th…
PS: I have yet to see a single threaded GUI I can't make shudder while playing video.
Re: Multithreaded toolkits: A failed dream? (2004)
#56Earlier quoted context omitted.
Anyone who has seen the responsiveness of e.g. AmigaOS under heavy load next to many modern systems might be inclined to want (more) multi-threaded GUIs. Heavy use of multi-threading to disconnect GUI updates from the actual work was essential to making that happen. AmigaOS sacrificed throughput over responsiveness all over the place (e.g. something as trivial as cut and paste from a terminal would easily involve hal…
half a dozen threads with message passing On a single-CPU no-MMU machine, message passing looks very similar to a function call.
Re: Multithreaded toolkits: A failed dream? (2004)
#57Earlier quoted context omitted.
Anyone who has seen the responsiveness of e.g. AmigaOS under heavy load next to many modern systems might be inclined to want (more) multi-threaded GUIs. Heavy use of multi-threading to disconnect GUI updates from the actual work was essential to making that happen. AmigaOS sacrificed throughput over responsiveness all over the place (e.g. something as trivial as cut and paste from a terminal would easily involve hal…
Was the UI really heavily multithreaded compared to today's systems? I thought there was a lot of events and message-passing going on in AmigaDOS much like in current GUI systems.
I mean to write this up for a blog post and do some proper diagrams, but here's a rough overview of the state transitions when handling terminal IO for AmigaOS and reimplementations of the API, like AROS (this is where I got hands on experience with it - I extended the AROS terminal handling):
Low level interrupt sources will be handled by "devices" such as "keyboard.device" and "gameport.device" (the latter handles the mouse/joystick ports). These will feed input events into "input.device".
The input.device is opened by any component that wants to handle input events. This includes the "console.device" which is responsible for providing a "raw" terminal in a specified rectangle in a window. It handles low level input processing, and turns keyboard and mouse input that are relevant to the console/terminal into higher level events which it passes on to clients, as well as take commands (such as "move cursor to position (x,y)" or "write text xyz" and render the terminal).
Above the console.device sits the console-handler (applications can, and often do open console.device directly if they want a low level interface). This is responsible for opening a window, creating a console.device that covers the window, and "cooking" low level input into higher level input and vice versa for output.
The "gadgets" (widgets; buttons etc. in the windows) will be handled directly by intuition (the GUI system) in a separate high priority thread.
If you then do cut-and-paste, there are additional complications: "conclip" needs to be running. This receives requests to cut or paste via messages, and mediates access to the clipboard.device. The clipboard.device again manages reading/writing files in the relevant clipboard volume. That will involve talking to the appropriate filesystem handler, which again may write to a device (such as trackdisk.device for the floppy drives).
Pretty much all of these components will run as their own separate threads. And most of their interaction is via messages put on a queue.
So if you choose to "cut" a section by pressing a key combination, an interrupt will be fired to keyboard.device, which will add an event via the input.device which the input handler thread ("task" in AmigaOS) will pass to the console.device thread via a message, which will pass it on to the console-handler, which will pass a message to conclip, which will pass the data on to the clipboard.device which will send a message to the relevant filesystem, which may send a message to a low level device. After sending a message to conclip, the console-handler will send a message back to the console.device if there's any rendering required.
The reason for all of this is that coupled with careful priorities (UI rendering and input is running in high priority threads), the system appears very responsive, while a lot of this happens behind the scenes.
E.g. the clipboard system on the Amiga has to deal with a system where the clipboard could have been reassigned from the ramdisk where it'd usually be, to floppy, so it really couldn't reasonably be "inline" without making the system unresponsive.
In that respect AmigaOS was more multithreaded: There's all kinds of things we consider fast enough to do "inline" now that was put behind a thread-boundary because it was either unpredictable or too slow to be done inline back then.
Re: Multithreaded toolkits: A failed dream? (2004)
#58Just throw the gui operations under a single global lock. No deadlocks, any thread can update gui.
Re: Multithreaded toolkits: A failed dream? (2004)
#59Earlier quoted context omitted.
Was the UI really heavily multithreaded compared to today's systems? I thought there was a lot of events and message-passing going on in AmigaDOS much like in current GUI systems.
Depends on what you mean by "heavily multithreaded". And yes, you're right, there were lots of events and message passing, but that message passing went between different threads. I mean to write this up for a blog post and do some proper diagrams, but here's a rough overview of the state transitions when handling terminal IO for AmigaOS and reimplementations of the API, like AROS (this is where I got hands on experi…
Today, we have single concurrent execution by enforcing a single GUI thread, at the time of the Amiga they had single concurrent execution because that was the only execution they had.
Re: Multithreaded toolkits: A failed dream? (2004)
#60Earlier quoted context omitted.
Depends on what you mean by "heavily multithreaded". And yes, you're right, there were lots of events and message passing, but that message passing went between different threads. I mean to write this up for a blog post and do some proper diagrams, but here's a rough overview of the state transitions when handling terminal IO for AmigaOS and reimplementations of the API, like AROS (this is where I got hands on experi…
But I think the thing missing is that each of these threads ran on the same CPU (right?), and thus things like torn reads and writes weren't an issue, so they didn't need to use expensive std::mutex or std::atomic everywhere. Today, we have single concurrent execution by enforcing a single GUI thread, at the time of the Amiga they had single concurrent execution because that was the only execution they had.
In fact, you'll find lots of Amiga-software being more brutal and enforcing serial-execution for critical section by using Forbid()/Permit() pairs, which will outright disable the scheduler, or even using Disable()/Enable() (disables interrupts too). Of course this is/was very much frowned upon for all but implementing atomic operations, though even this is not guaranteed to be totally atomic in an Amiga system without taking care.
The need to protect against other threads/tasks is/was one of the first things hammered into the heads of Amiga-developers exactly because it was so new to most, who would usually come at it from 8-bit home computers where the standard procedure was that you fully controlled the computer except perhaps for some very trivial interrupt handlers (which most software would take over control of anyway).
And while each of the normal threads would be running on a single CPU in a basic Amiga, any number of devices could DMA - the Amiga depended heavily on this -, and additionally both the Copper (very basic "GPU" of sorts used to set up "display lists" to manipulate various registers etc. though not really limited entirely to graphics) and the Blitter could access memory at any time too, so you very much had to at least in theory be prepared to deal with memory changing during execution of an individual instruction if working in "chip-memory" (the Amiga roughly works with two types of memory: "chip-memory" is memory where auxilliary hardware can steal bus-cycles from the CPU; "fast-memory" is memory that only the CPU can access).
Also note that while unusual, there were true multi-processor Amiga-setups: There were "bridge boards" for the A2000 which effectively were an x86 PC on a card, where the "graphics card" was a buffer in chip memory that would get displayed in a window, and which would receive input from the Amiga keyboard and mouse. There were also PPC accelerator boards (a release of AmigaOS4 for "classic" Amiga hardware with PPC accelerator boards exists; it basically runs everything it can on the PPC, just like for "new" Amiga hardware), though usually these would disable the M68k while the PPC was executing stuff (but I'm not sure if this was enforced by hardware or if it was done by the OS patches for simplicity).
I used to love to tell people of all the different CPUs in my A2000: A 68020 with the 68000 as fallback (if you soft-disabled the 68020 for compatibility) on the motherboard. A 6502-compatible core on the keyboard (the A500 and A2000 keyboards had an embedded SOC chip with a 6502 core + RAM + PROM as the keyboard controller). A Z-80 on my harddisk controller. An 80286 accelerator board + 8086 fallback on my bridge-board... Of course of the 68020/68000 and 80826/8086 pairs only one of each architecture could ever be running at once.