How to handle several displays each from a different thread?

I have several concurrent threads each launching a gtk app + gtk window. This is already working.

I want to have each window acting as an LVGL display. From an API perspective, it is pretty clear how to do it, but since global structures are modified each time a new display/screen is added/removed it screams thread unsafe.

Is there a provision for an scenario like this? It would basically be equivalent to running an LVGL instance on each thread.

Approaches that may work:

  • Use thread locals instead of static globals (search and replace).
  • Guard display/screen add/removal with a mutex (normal widget handling seem to not touch globals)

Any ideas?

multiple processes instead of multiple threads. This would keep things safe form each other and you can use a variety of mechanisms to pass things between the different processes if data does need to be shared between them.

Unfortunatelly multiple processes are not allowed. Thanks for the idea though.

see now you are trying to make it complicated…

I am going to try and explain this as easy as possible. I want to get some verbage laid down.

LVGL uses timers in order to perform specific tasks. So lets call them tasks instead of “timers”
There is a task handler that needs to be checked for any tasks that have to be run. This gets done in the main loop of the program or optionally a hardware timer can trigger an interrupt and in the ISR the task handler can be checked for any tasks that need to run and run them if they do. There can only be a single task handler so that means only a single thread would be able to run LVGL. Now when I say to run LVGL I am speaking about the checking for touch input and the writing of changed information to the display, internal bits and pieces. You do have the ability to change things in the UI from a separate thread, like adding new elements or removing elements maybe changing the value of a widget. It would be up to you to put locks in place so you don’t add a widget to an object that is being destroyed at the same time.

It really depends on how you were planning on using threading.

I understand that for normal apps threads are overkill, but what I am trying to achieve is closer to a display server than a normal app. I need a thread to own the LVGL display and mediate access to it from other threads that may need to add windows/widgets. Very similar to a desktop environment where one process handles X and others connect to it to put content on screen. I need that server thread to be able to start and stop, like a service, within the same process from a REPL shell. Thread synchronization is not a problem because there is an async queue/callback mechanism in place already.

My needs are:

  • Must have: Ensure the LVGL environment reset is total so that the server thread provides an LVGL blank slate when restarted.
  • Nice to have: Be able to run concurrent LVGL environments in the same OS process to support multiple independent shell sessions.

Lets start with the first one.

What are the best practices to ensure the LVGL environment reset is total?

Is lv_deinit enough for that?

Thank you.

how about a threaded sandbox environment?

Which one do you have in mind?

I don’t have one in mind at all. Just thought it might work.