Create thread safe

I have a multithreaded program that prints to the console in hundreds of places. Unfortunately, instead

Line 2 Line 1 Line 3 

I get

 Line2Line1 Line3 

I am trying to make the puts thread safe.


In Python (which I think does not have this problem, but suppose it is), I would do

 old_print = print print_mutex = threading.Lock() def print(*args, **kwargs): print_mutex.acquire() try: old_print(*args, **kwargs) finally: print_mutex.release() 

I am trying to do this in Ruby,

 old_puts = puts puts_mutex = Mutex.new def puts(*args) puts_mutex.synchronize { old_puts(*args) } 

But this does not work: "undefined method old_puts "


How can I make it thread safe (i.e. do not print partial lines)?

+5
source share
2 answers
 alias old_puts puts 

or more modern way:

 module MyKernel PutsMutex = Mutex.new def puts(*) PutsMutex.synchronize{super} end end module Kernel prepend MyKernel end 
+6
source

The reason for this behavior is that puts internally calls the core write function twice — one for the actual value to be written and the other for the new line. (Explained in Ruby puts is not atomic )

Here, hack puts the write call exactly once: add \n to the line you are writing. This is how it looks in my code:

 # Threadsafe `puts` that outputs text and newline atomically def safe_puts(msg) puts msg + "\n" end 

puts internally checks to see if the text has a new character at the end, and only calls write if that is not true. Since we changed the input end to a new line, puts finishes executing only one call to write .

0
source

Source: https://habr.com/ru/post/1237937/


All Articles