1
votes

if i create a GUI and each widget is controlled by a thread, will a thread deadlock the GUI ?

i understand that if it was a GUI that displays only one number at a certain time and that number is determined by a thread(say t0) then all the other threads(t1...tN) will wait for this one's process to end thus if an error occurs to t0 it will deadlock the hole GUI.
so can it be solved with independent widgets ?

can it be done in c using pthread library ?

2
What GUI library are you using? It very much depends on the underlying structure; however, I generally advise you against this, as that means you will have a lot of threads fighting for resources while you don't actually gain anything (Usually, speed is negligible here because most of the time you'll be waiting for the user to do something anyway). - Ben Steffan
That design doesn't make any sense at all. What is the benefit of independent widgets? Most (probably all) GUI toolkits are event based, there is a main loop and it consumes events and calls handlers, no need for multiple threads at all. If you don't want the main loop to be slow or to even freeze for some time, then you do create a worker thread to perform calculations and return the result back to the main loop. - Iharob Al Asimi

2 Answers

1
votes

Unless you are very good or very lucky you are likely to thread deadlock at some point.

Having each widget in its own thread sounds like a faster idea than single threading but it is terribly complex. Typically user input and painting the widget are not going to be a bottleneck so having each widget in a different thread buys you a lot of complexity that really isn't worth it.

A GUI typically has a main loop that processes events such as mouse movement, mouse clicks, button pressing, system events, etc. If you have time consuming operations that you need to perform then you would run those in a worker thread but not process the widget events or any GUI related events in that worker thread.

If you do want to try it you will need to synchronize all over the place and I think you will soon decide it isn't worth the effort since each thread will be trying to process events for its widget. Definitely something only an expert should try.

0
votes

Don't panic.

Follow these rules/guidelines:

1) Stick to one thread for the GUI system, handling messages and calling events. Ths is enforced my most GUI frameworks anyway.

2) Never, ever wait in a GUI event-handler, in any way, for any thread signal or state. Use your framework messaging system, (signals/slots, Windows messages, whatever), to communicate data to/from other threads.

3) Do not continually create/terminate/destroy/join threads. Never do this. If your 'Intro to multithreading' site says that you must always use use join() to wait for thread termination, remove all references to the site from your browser and its history. Use app-lifetime threads that are pooled, or dedidated to one task, and loop around some blocking input queue mechanism and process input messages until the app is terminated. Don't try to termiante them yourself unless you have absolutely no choice or you enjoy pain.

4) 'i decided to open a thread for each new client. the received data will be displayed on the GUI'. Fine, sounds like a plan. For each widget group that represents a single client, start a thread to handle the comms and pass, as part of the thread creation, the instance of the widget group to which is is bound so that it can direct messages back to the correct widget, and some kind of queue event/whatever that the thread can wait on for queued input request struct.

5) Do not write from the GUI thread to any data/fields/whatever of the client threads directly. If you want to communicate something from the GUI thread, use your framework and/or OS API to queue a request struct to the thread.

6) Do not write from the client threads to any data/fields/whatever of the GUI thread. If you want to communicate something to the GUI thread, use your framework and/or OS API to queue a request struct message to the thread, so firing an event handler with the message to perform the GUI actions/s.

7) Take some care with message lifetimes - if you intend to queue up a message struct pointer to another thread, it's useless allocating the struct with auto storage - it will likely be gone by the time the receiving thread gets it. One method: malloc it, queue it to the other thread, receive it, free it in the other thread. Other, ore controlled inter-thread, inter-GUI comms mechanisms are possible, eg. using message pools, but I suspect that is beyond you ATM.

7) If at all possible, design to avoid the 'clean and graceful termination' of app -lifetime and pooled threads. User code cannot reliably stop threads running on other cores, (without messy and wasteful polling). The OS can easily stop all threads at process termination - let it do its job.

8) Forget many of those 'must do' rules from those who have only ever written single-threaded command-line apps. For instance, it's grossly unrealistic for your code to always release all memory that was allocated during your program run at termination time. In a complex app, with multiple cores reading/writing messages etc, any attempt to write user code to close it down is hugely likely to create far more problems that it is worth in terms of testing/debugging. If you allocate some thing once and you need it for the whole run, do just that - don't try to free it, there's no point at best. If multiple threads are reading/writing/calling through it, there is a massive quiz-show-full of points in absolutely not freeing it with user code, (the OS can easily free it on termination - it stops all threads first before dealocating process memory).

If you only queue up requests/messages, don't wait in event handlers and don't make any suicide-calls like join(), you should get no deadlocks:)