1. Phix: Understanding Multithreading
- Posted by euphoric (admin) Jun 03, 2019
- 1769 views
Hey, Pete! Can you fix this simple demo for me? I'm just trying to get a better grip on multithreading.
It actually works for a few seconds, doing what it's supposed to do, but then it crashes.
I think I got it! I was using a plain ?x, and I think maybe that's what was crashing it.
If you run the below code without the enter_cs()/leave_cs(), it crashes eventually. With them there, it works.
Pete, let me know if I'm on the right track here!
Thank you!
-- simple app to show multi-threading in Phix -- start 4 threads -- each thread will wait X seconds and then print its output atom cs = init_cs() bool terminate = false constant ESC = #1B procedure counter(integer x) atom nowTime atom endTime = time() + x while not terminate do nowTime = time() if nowTime >= endTime then endTime = nowTime + x enter_cs(cs) --<-- this is required to not crash ?x leave_cs(cs) --<-- this is required to not crash end if end while exit_thread(0) end procedure atom rid = routine_id("counter") procedure main() sequence threads = { create_thread(rid,{1}), create_thread(rid,{2}), create_thread(rid,{4}), create_thread(rid,{8}) } while not find(get_key(),{ESC,'q','Q'}) do end while terminate = true wait_thread(threads) delete_cs(cs) puts(1,"done") if getc(0) then end if end procedure main()
2. Re: Phix: Understanding Multithreading
- Posted by petelomax Jun 03, 2019
- 1692 views
- Last edited Jun 04, 2019
When using multithreading, shared reference counts (especially the hidden ones on literal constants) are a real pita.
The problem you hit is builtins/VM/pprntfN.e, aka sprintf(), is not thread safe - I have just made the following (yet more) fixes to it:
-- result = "1"&result result = '1'&result else -- result = "-1"&result[2..$] result = '-'&'1'&result[2..$] -- reve = "0" reve = repeat('0',1) -- if find(result,{"","-","+"}) then if length(result)=0 or (length(result)=1 and (result[1]='-' or result[1]='+')) then --string hexchar string hexchar, dxoetc hexchar = "0123456789ABCDEFabcdef" dxoetc = "dxobscvefgEXG" -- fidx = find(fi,"dxobscvefgEXG") fidx = 0 for dx=1 to length(dxoetc) do if fi=dxoetc[dx] then fidx = dx exit end if end for -- or (showcommas and find(fi,"df")=0) then or (showcommas and fi!='d' and fi!='f') then
EDIT: oops, i ==> dx
As you say though, that enter_cs()/leave_cs() is a perfectly fine way to deal with it as well, and the above is for educational purposes only.
I suppose multithreading is a bit like working for MI6 or the NSA - you have to be really paranoid about privacy. Ideally you should do the absolute bare minimum work in the thread itself, and pass the results back to the main thread for any printing/logging/storing, etc.
3. Re: Phix: Understanding Multithreading
- Posted by euphoric (admin) Jun 03, 2019
- 1671 views
Ideally you should do the absolute bare minimum work in the thread itself, and pass the results back to the main thread for any printing/logging/storing, etc.
Ah, like the loggit() functionality... Thanks for the help!
4. Re: Phix: Understanding Multithreading
- Posted by euphoric (admin) Jun 03, 2019
- 1690 views
When using multithreading, shared reference counts (especially the hidden ones on literal constants) are a real pita.
The problem you hit is builtins/VM/pprntfN.e, aka sprintf(), is not thread safe - I have just made the following (yet more) fixes to it:
Does this mean '?' is now thread safe?
5. Re: Phix: Understanding Multithreading
- Posted by petelomax Jun 04, 2019
- 1619 views
Does this mean '?' is now thread safe?
Maybe/maybe/no/no:
Maybe: I have already had five or six previous attempts at this...
Maybe: ? uses sprint() uses sprintf(), and I only changed the latter.
No: Mixing output from several threads on one screen will get very messy.
No: I will never claim it is nor recommend using ? from background threads[1].
PS: I should probably also say there is some merit for a thread-safe sprintf(), and even non-1 file i/o,
but I do not feel the same for the console (or gui), [1]at least that is without an explicit enter_cs()/leave_cs().