LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Printf in multithreading context (https://www.linuxquestions.org/questions/programming-9/printf-in-multithreading-context-4175735215/)

tuxuser1 03-23-2024 03:43 PM

Printf in multithreading context
 
Hi,

I'm writing a program which use multiple threads.
Now, I'd need to print for each thread some info.
Basically, each thread loads some data and I'd want to print something like:
Code:

printf("Thread %d -> Data (%d/%d)", thread_num, cur_data, tot_data);
Each thread should have to overwrite its own line rather than create another one.
Carriage return usage should be ok but, in this case, each thread overwrites the line
getting a non-wanted behaviour.
How could I achieve this goal ?

Regards

EdGr 03-23-2024 05:25 PM

Have each thread write an entry to an array. Print the entire array.
Ed

dugan 03-23-2024 06:07 PM

Use ANSI sequences to move the cursor to specific rows.

sundialsvcs 03-23-2024 08:00 PM

I definitely prefer @EdGr's suggestion. Very specifically, here's what I would do:
  1. Create an array of "messages," and an array (initialized to zero before any threads are started) of pid's. ("pid = process or thread-id")
  2. Create a mutex which will control access to both of these, and make it available to all threads.
  3. Each thread, upon initialization, (grabs the mutex and ...) finds a zero-slot in the pid array, puts its own pid into it, and remembers the index.
  4. Each thread thereafter, upon wanting to update a message, (grabs the mutex and ...) stores the message into "its" chosen message-array slot (using "sprintf").
  5. Finally, create another single thread which, (say ...) once per second, (grabs the mutex and ...), sends a "blank screen" sequence and then outputs all of the messages at once.
The (one ...) mutex first ensures that the threads will not "race" to claim their display slots. Then, it ensures that the display-update thread will never encounter an incomplete message. Finally, the presence of a display-update thread, also using this mutex, avoids visual chaos. Only this one thread actually performs any terminal output.

tuxuser1 03-24-2024 02:34 AM

Actually, I already thought a new thread but I was wondering whether a simple Ansi escape sequence can resolve the problem. Anyway the latter requires a mutex to properly work and I'd want to avoid because will cause a little bit slowing about threads parallelism. The new thread will have to simply composite an unique string with the data which are already in memory and print it with carriage return.
Thanks all for feedbacks.
Mark as solved.

sundialsvcs 03-26-2024 08:50 AM

If "every thread, independently," tries to perform I/O, the fully-asynchronous nature of "multitasking" inevitably results in visual chaos. After all, the thread or process could be pre-empted in the middle of trying to send a character sequence. It simply doesn't work.

In fact, this idea works generally. When "many threads or processes" need to read or write from a single physical resource, such as a disk file, the most-reliable method is to dedicate one thread or process, fed by (or, supplying) queues of some sort, to the task of "actually doing it."

pan64 03-26-2024 10:25 AM

yes, with other words (and in general): you need only one worker thread and all the other threads can collect and put the data into a common area/variable/array. This should be used in every case when the given "work" is not thread safe (like displaying those messages).

dugan 04-02-2024 03:45 PM

Quote:

Originally Posted by sundialsvcs (Post 6492039)
If "every thread, independently," tries to perform I/O, the fully-asynchronous nature of "multitasking" inevitably results in visual chaos. After all, the thread or process could be pre-empted in the middle of trying to send a character sequence. It simply doesn't work.

This is a solved problem. You treat stdout as a shared resource to which writes have to be synchronized. What that looks like, is that each thread locks the mutex before doing the printf, and unlocks it afterwards.

Honestly, the reason I didn’t spell this out is because I assumed I didn’t need to.

sundialsvcs 04-02-2024 08:10 PM

Quote:

Originally Posted by dugan (Post 6493682)
This is a solved problem. You treat stdout as a shared resource to which writes have to be synchronized. What that looks like, is that each thread locks the mutex before doing the printf, and unlocks it afterwards.

But if you also need to "position the cursor," in order to write the thread's output to a particular row on the terminal, the visual result might be "fairly schizophrenic." Hence the suggestion, in this case, to dedicate one thread to the task of "updating the display at periodic intervals." Much cleaner, and the display updates will be "steady, and 'fast enough.'" Plenty of ways to get it done.

pan64 04-03-2024 01:24 AM

Quote:

Originally Posted by dugan (Post 6493682)
This is a solved problem. You treat stdout as a shared resource to which writes have to be synchronized. What that looks like, is that each thread locks the mutex before doing the printf, and unlocks it afterwards.

Honestly, the reason I didn’t spell this out is because I assumed I didn’t need to.

No, I mean don't use mutex if you are not really need to do that. That adds an additional level of complexity and possibility to go into deadlock and other surprising situations. Better to have a dedicated thread for it.


All times are GMT -5. The time now is 10:42 AM.