Wimp threads
Julie Stamp (8365) 474 posts |
I’m looking at Dan Ellis’ work from around 2001 on Wimp threads. It allows you to have several Wimp tasks sharing the same app slot. A parent and child can both be ‘desktop’ tasks, and communicate via Wimp messages and their shared app slot. Or the child can be a task window, using fwrite(stdout) and fread(stdin) to talk to the parent which sends and receives TaskWindow_Input and TaskWindow_Output messages, as well as the shared app slot. To start a child thread, the parent calls Wimp_StartTask with R0 = 0 (rather than pointing to a command string). In Dan’s own words:
We should add that the child will have the same OS environment the parent A C program requires some extra code to use this (c.start_thread, s.thread_init). Maybe we should put that in the SharedCLibrary as a new _kernel routine? |
Jeffrey Lee (213) 6048 posts |
That’s a tricky one. We should aim to implement a standard threading API in the SCL (or in a library which can be used with the SCL). But are standard APIs sufficient, or should the SCL also provide RISC OS-specific ones? Currently I’m working on an implementation of the C11 threads API which will allow use of threads from within C applications. Initially it’s only going to work via the SMP module, but I’m also planning on implementing a non-SMP version, probably by implementing a callback-based thread scheduler inside the library, similar to how UnixLib handles pthreads. Both of these implementations could then be put in the SCL, with it automatically choosing which one to use based on whether the SMP module is present. Compared to callback-based schedulers, and the current SMP module, Dan’s approach of using one Wimp task per thread does have the advantage that if an app is sleeping in Wimp_Poll, the other threads can continue to run. But is it a sensible approach to solving that problem, compared to other potential solutions? |
Julie Stamp (8365) 474 posts |
I’d expect Wimp_StartTask (or the _kernel equivalent) to be used much as it is now, palming off a long process to TaskWindow. At the moment, if you use a library function that takes a long time, you have to hope that it lets you split the job up to poll in between. The new option means you can pre-empt it instead. I suppose you’ll say that rather than using TaskWindow I should call the function in a new thread, and then poll idle to keep the thread running? The parent task taking on the role of the TaskWindow module.
That sounds tantalising. |
Jeffrey Lee (213) 6048 posts |
No, I’d say that we should improve things so that if one thread is sat waiting in Wimp_Poll, the other threads in the task can continue to run, with the Wimp pre-empting the task at will. So like the TaskWindow approach, but hopefully a less hacky implementation ;-) |
Jean-Michel BRUCK (3009) 362 posts |
Bonjour, |
Julie Stamp (8365) 474 posts |
You can get a copy of the Wimp with threads that builds using recent OS sources from here. |
Jean-Michel BRUCK (3009) 362 posts |
Indeed it is more recent, thank you. |
Julie Stamp (8365) 474 posts |
What I would say firstly is that rather than padding the task window output like that, you can force it to flush the buffer with sleep() (basically SYS “OS_UpCall”,6,0). The diagram makes complete sense using R0 = 0. The main difference is that, if you wish, you can have the C code for loading, sorting and saving in the application rather than in a separate module. I didn’t try running the compiled version, because it’s not 32-bit compatible. Take a look at Wimp.Test.Thread.!ThreadTes and Wimp.Test.Thread.!ThreadTes2 to see Dan Ellis’ example code. |
Julie Stamp (8365) 474 posts |
How should we show threads in the task manager?
The parent is ThreadBA and the children are Thread 0 etc. All the bars are green, and the task’s names are chosen by the application as usual. Here are some possbile alternatives that I thought of (all bars next to “Thread 0” etc. intended to be grey). Option 1
Option 2
Option 3
Option 4
Note that currently the task manager will list the tasks in whatever order they Also in principle you can quit the parent with the children still being active, Another (probably rare) situation is that the parent and children can all be |
Rick Murray (539) 13850 posts |
This is weird. Doesn’t C or C++ mandate that all resources (memory claims, threads, etc) are released when main() exits? Terminating the parent task should automatically terminate all threads. Otherwise you aren’t creating threads, you’re creating tasklets.
If this is the case, then the pieces of code aren’t threads. They’re… well… tasks. And ought to be listed in TaskManager separately. If there is a clear dependency between the parent task and threads it owns, then the indented but tidy option 4 looks best to me. It is worth remembering that Switcher has an option to send a message to terminate tasks. What happens if this is invoked on a thread? (a proper thread, not a tasklet) Should the parent be terminated? Should it be disallowed, only letting one terminate the parent? |
Jeffrey Lee (213) 6048 posts |
We shouldn’t. The tasks are being used to implement threads, and by convention task managers only show tasks/processes, not the many threads within those tasks. This also means that the Task Manager’s “Quit” option should terminate all the tasks in the group.
Yes. Returning from main() is equivalent to calling exit(), and exit() should terminate the process (calling atexit handlers, terminating any remaining threads, closing files, etc.). However you can use thrd_exit() (or equivalent) to terminate the main thread without terminating the process. If all threads exit via thrd_exit (or returning from the thread function), the process exits as if exit(0) was called. |