Hello,
I'd like to write some reusabel code module to handle e.g. UART ports. Therefore I'd like to create a variable number (based on some kind of define...) of threads dealing with UART port 1,2,3 ... since it is possible to declare CMSIS-RTOS threads with a variable number of instances it could look like this:
#define UART_PORT_NUM 3 osThreadDef(uart_thread, osPriorityNormal, UART_PORT_NUM, 0)
my problem: If I need any kind of inter-thread communication (ITC) object, like mutexes or mail queues, for each of this threads I don't know how to declare them, since osMailQDef, osMutexDef and so on, are not designed with a "variable" number of instances...
Any suggestions?
If you make a terminal server, for example handling a number of serially connected RFID readers, then you have a situation where each reader - i.e. each UART - produces identical data.
Then it would be meaningful to use identical code to process the actual data. But each thread would need to know exactly what interface it is associated with, so it would need to know exactly what mutex to use or what queue to listen to. So the threads wouldn't be anonymous and there would still not really be a need for a pool of mutex objects or queue objects.
And in the above case, each RFID reader would also be expected to have the same priority. So no need to control that per thread or per port or per queue.
In the other diretion, you can find many examples where there is a need for a pool of anonymous threads. Each taking input from the same queue. Each producing an output to place into another queue. Each with the same priority. The code implemented as a thread pool just because the input data requires some processing that involves a delay (possibly slow hardware like having to wait for a file operation) or because the processor has multiple cores. So multiple, symmetrical threads, are used to get higher concurrency.
But back to you - can you show any single situation where there would be a need for multiple, anonymous, mutex objects? Or multiple, anonymous, queues?
Start looking for this functionality first after you have a design that would actually work better with this type of functionality - I have never seen such a concept really needed. The closest thing would be a load balancer taking input requests and forwarding them to multiple stupid work units that aren't able to pickup requests from a single queue but has to be tricked into thinking they are alone. But such a situation still really don't need a pool of anonymous queues, since the balancer would like to actually look at queue lengths or response times to figure out which of the output queues that is best suited to get more work.
Symmetrical thread pools are a very common design concept, as an alternative to multiplexed code which requires less resources but instead adds more complexity. But symmetrical means same priority and same input/output.
Ok, last try:
Think of a device driver, e.g. to control a pump connected over a fieldbus. Depending on the complexity of such a driver module, it could even consist of multiple threads. You don't know in which project this driver will be included, but there could be multiple pumps, with different priorities (e.g. because the application knows that one pump has to be adjusted more frequently). Each driver instance would need its own message/mail queues to get input data from the application (for example a superordinate synchronization thread) and to send its output back. And as I said: If this module realy consists of multiple threads, it could be possible that it needs internally hidden, anonymous ITC objects.
About your own example: if you have such a terminal server and you know that there is one client talking a lot more than the others, it could be usefull to increase its priority
Perhaps we are talking past each other, but when I ask "I have a problem xy, any suggestions how to fix it?", aswers like "I can't imagine why you need this" are not really helpfull.
If I have such a terminal server, I wouldn't want it to increase the priority, since I would want each connection to be fair.
If your advanced pump driver needs multiple threads, then it is a very, very low probability that you would talk about identical threads. So you would want to set up multiple, specific, threads. And you each thread would want to know what specific input/output/synchronization objects to use.
So I would normally do:
create_thread(id_pump1,pump1_addr,pump1_event,pump1_prio,pump1_listener); create_thread(id_pump2,pump2_addr,pump2_event,pump2_prio,pump2_listener); ...
and would not have a need for multiple, identical, threads operating in an anonymous way on some anonymous pool of other ITC objects.
If a user wants to increase the speed of pump 5, the user needs to be able to address pump 5. So the user needs to have a specific pump 5 control object.
Same if the user wants to get an alarm because pump 2 fails to keep the intended rpm - then the user needs the thread operating pump 2 to know exactly where to send the reports.
That is why you would normally not see a need for an anonymous group of mutex objects. Or of event objects. Or of mail boxes. But while there is regularly a need for an anonymous group of threads.
You are constantly trying to invent some random system that would need a mutex pool. But you aren't managing to move from an invented system to instead describe a real, existing, usage case. While it's trivial to list thousands upon thousands of existing implementations needing a thread pool.
And look back one more time on osThreadDef().
It takes the parameters:
name name of the thread function. priority initial priority of the thread function. instances number of possible thread instances. stacksz stack size (in bytes) requirements for the thread function.
So you specify one (1) priority. But you can specify multiple instances.
But that terminal server solution can then perform multiple osThreadCreate() in which the last parameter allows each thread to know which UART it is responsible for. And that parameter can be a pointer to a struct that can look like:
struct term_port { uint32_t addr; // Base address of UART. osMessageQId send_queue_id; // Where to pick up outgoing messages. osMessageQId recv_queue_id; // Where to send received data. ... };
In the end, the rest of the world needs to know where to send data. And where to pick up data. And how to flag events. So the rest of the program needs well defined objects to operate on. So what reason would there be to have a osMutexDef() that takes a parameter "instances"? I either wants to send my output to a specific printer ("office floor 2") or I want to send it to a generic pool and have the first free printer pick up the data. So either I want each printer to have a named queue. Or I want all printers to look in a common queue and the first to grab the data wins.
With the common queue, I expect the printers to be supplying the same service. With the separate queues, I would expect each printer to be able to have different capabilities so I may select a printer that has duplex support. Or photo colors.
In the end, I have to repeat the same thing I said in the previous post. Don't ask for anonymous mutex pools, anonymous queue pools, ... until you actually have managed to find a problem that would be able to take good advantage of such functionality.
The world have had pthreads for a great many years, without anyone actually getting stuck because of such needs.
When you make posts to this thread, you aren't making the posts to an arbitrary pool of queues or trying to take one mutex from an arbitrary pool of mutexes. You post an addresses message reaching a specific queue affecting a specific mutex. The server may be redundant or load-sharing, in which case there is a pool of symmetrical threads listening for incomming data from that queue.
So in the end, the bulk of all functionality around you just happens to be designed around the two basic variants: - multiple workers load-sharing tasks received from a single boss. - multiple companies with individual email addresses or phone numbers.
Spend some time with computer-science books and you'll see lots of generic examples of producer-consumer systems, or publisher-subscriber systems. And the thread implementations are designed around these two concepts.
The only companies who likes "random mailboxes" are the spam companies. But the normal need is to have either an addressed push or an addressed pull.
Wow, you sir, are a huge JACKASS!
And you are so eloquent.