Live data from Hacker News

Multithreaded toolkits: A failed dream? (2004)

weblogs.java.net

21–30 of 64 posts

Re: Multithreaded toolkits: A failed dream? (2004)

#21

What about functional reactive programming? And what about flux pattern? Didn't these resolve this "failed dream" of multi-threaded GUI update? (I am asking real, not rhetorical, questions.)

Flux is like an event model, every change goes through a single dispatcher and in the store(s) the code is single threaded. If you use multiple stores and have multiple components subscribing to them (to paint the gui) you aren't really guaranteed any order of the events, last write wins and the components basically redraws everything inside them for every event.

If the CPU bottleneck is on the store, maybe you need some sort of transactional store, where the change is signalled to the views only after a transaction completes? Just thinking out loud.

I am not sure what exactly is the original author trying to solve here. But it seems to me that if you want to expand the single GUI thread to multiple threads, for whatever reason, flux and/or FRP may be a good start.

Re: Multithreaded toolkits: A failed dream? (2004)

#22
post #14

Earlier quoted context omitted.

You want a multi-threaded GUI when it's running a long task. Otherwise it won't update until it's finished running, there's no way to cancel the task, etc.

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 care of the bookkeeping.

Re: Multithreaded toolkits: A failed dream? (2004)

#23
post #22
post #14

Earlier 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…

You can just send a closure to the UI thread and have it executed there, provided you are using a good enough programming language.

Or start the long-running computation from the UI code in a way that returns a promise, and chain the UI update on it, in a way that causes that continuation to be scheduled on the UI thread.

Or have an UI that can be updated from any thread (but not simultaneously) and take the big UI lock.

Re: Multithreaded toolkits: A failed dream? (2004)

#24
post #22
post #14

Earlier 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…

> it's exceedingly tedious to program.

C++ programmer detected? ;)

Re: Multithreaded toolkits: A failed dream? (2004)

#25
post #20

Earlier quoted context omitted.

Locks turn out to be unnecessary for multithreaded code. A ringbuffer of messages is only slightly more complex, yet the gains are massive. Both in performance and simplicity. It's possible to manage a ringbuffer without any locks. The trick is to have a counter for the producer thread, and a counter for each consumer thread. Whenever the producer wants to know "Is it safe to add a message?" it takes the minimum of a…

I would like to read more about what you described here. Know of any good articles or open source projects where this is done?

If you like Go I have written a ringbuffer library here

https://github.com/fmstephe/flib

have a look in queues/spscq. spsc here stands for single producer, single consumer.

I gave a talk in London about these queues here

https://skillsmatter.com/skillscasts/6163-high-performance-s...

-------------------

But all of this work is based on the work, and teaching, of Martin Thomson.

Martin Thomson has published a large collection of data structures (which probably include these ringbuffers (I haven't checked specifically))

https://github.com/real-logic/Agrona

If you are near Ireland I highly recommend Martin Thomson's concurrency course

http://instil.co/courses/writing-concurrent-code-with-lock-f...

----------

I highly recommend Nitsan Wakart's blog. He covers a lot of interesting ground, all in Java. Probably best to start at the early blog posts and work your way forward.

http://psy-lob-saw.blogspot.co.uk/

Nitsan contributes to a very focused java library here

https://github.com/JCTools/JCTools

Re: Multithreaded toolkits: A failed dream? (2004)

#26
post #3

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 loop. Bizarre hacks to let services "communicate" with activities when a simple static global would have worked fine tend to abound.

Re: Multithreaded toolkits: A failed dream? (2004)

#27

Well, 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…

> Who the heck wants multi-threaded GUIs?

Widgets aren't static; presumably you want them to keep updating (spinners, size changes, status updates) when the user is interacting with other elements.

Re: Multithreaded toolkits: A failed dream? (2004)

#28
post #3

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…

Those bizarre hacks help the service don't crash when the service needs to talk back to an activity that just got replaced between request/response cycle, because the user had the strange idea to rotate the phone.

Re: Multithreaded toolkits: A failed dream? (2004)

#29
post #20

Earlier quoted context omitted.

Locks turn out to be unnecessary for multithreaded code. A ringbuffer of messages is only slightly more complex, yet the gains are massive. Both in performance and simplicity. It's possible to manage a ringbuffer without any locks. The trick is to have a counter for the producer thread, and a counter for each consumer thread. Whenever the producer wants to know "Is it safe to add a message?" it takes the minimum of a…

I would like to read more about what you described here. Know of any good articles or open source projects where this is done?

Why: https://github.com/LMAX-Exchange/disruptor/wiki/Blogs-And-Ar...

Java: https://lmax-exchange.github.io/disruptor/

.NET: https://github.com/disruptor-net/Disruptor-net

Re: Multithreaded toolkits: A failed dream? (2004)

#30

Well, 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…

You want a multi-threaded GUI when it's running a long task. Otherwise it won't update until it's finished running, there's no way to cancel the task, etc.

Uh-huh.

Typically GUI work is instantiated with the GUI toolkit on the call stack. It calls foo.onClick(), etc. Now, if one particular onClick starts long-running task, then there are three possible designs:

Either that particular onClick() starts a worker thread and returns before the worker is done.

Or the GUI toolkit delivers the onClick() in a thread of its own, e.g. from a pool of workers.

Or everything is done in one thread, and the UI blocks.

The last one seems sucky, but the insidiously sucky one is the one in the middle. That's where every user's implementation of onFocusOut() must take care to lock because all of bar.onFocusOut(), foo.onFocusIn(), foo.onMouseUp() and foo.onClick() are called concurrently in four different worker threads. The tail wags the dog.

Post reply on HN