View previous topic :: View next topic |
Author |
Message |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Sat Dec 14, 2024 3:02 am Post subject: LUA Threads and Mutexes |
|
|
I'm writing a multithreaded script in LUA.
I have some shared variables to which I must manage the access.
After reading a bit online, I found that LUA does not have mutexes, so I wanted to know how you handle these kind of problems?
Thanks in advanece.
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25765 Location: The netherlands
|
Posted: Sat Dec 14, 2024 3:41 am Post subject: |
|
|
most of lua in CE is thread safe, as in a var/table can only be accessed by one thread at a time
but in case you want to deal with it, look up celua.txt and look for CriticalSection, Event, Semaphore and
MultiReadExclusiveWriteSynchronizer
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Sat Dec 14, 2024 5:48 am Post subject: |
|
|
Dark Byte wrote: | most of lua in CE is thread safe, as in a var/table can only be accessed by one thread at a time
but in case you want to deal with it, look up celua.txt and look for CriticalSection, Event, Semaphore and
MultiReadExclusiveWriteSynchronizer |
Thank you for the quick reply Dark Byte!
I'm missing how can CE handle all the other threads \ tables I create in my own scripts and making them "thread safe".
I'll look into what you suggested, "MultiReadExclusiveWriteSynchronizer" is just what I need. Thanks again!
EDIT** - celua.txt is a gold mine
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25765 Location: The netherlands
|
Posted: Sun Dec 15, 2024 11:16 am Post subject: |
|
|
The main thing you should watch is GUI access from other threads. That will eventually lead to heap corruption and random memory location writes
you can prevent that using synchronize e.g:
Code: |
...your thread code...
local somethreadvar='some data'
...
synchronize(function() --runs in the main thread
labelOutput.Caption='Data is '..somethreadvar
end)
...continue your thread code...
|
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Mon Dec 30, 2024 2:26 am Post subject: |
|
|
Dark Byte wrote: | The main thing you should watch is GUI access from other threads. That will eventually lead to heap corruption and random memory location writes
you can prevent that using synchronize e.g:
Code: |
...your thread code...
local somethreadvar='some data'
...
synchronize(function() --runs in the main thread
labelOutput.Caption='Data is '..somethreadvar
end)
...continue your thread code...
|
|
Thank you! That fixed some weird exceptions I had.
Where should I look at if I’m not getting any exceptions but the main gui thread is frozen?
My program is using the ‘synchronized’ keyword whenever a gui-related action is executed.
If I create a criticalSection for syncing my lua threads, should enter and leave also be done in a synchronized fashion? If one of the threads crashes inside a synchronized segment, would it cause CE to stop responding?
*edit- I think that my questions is basically how is synchronize implemented, does the caller thread halt until the main thread finishes the execution? What happens if there there is a synchronized call inside a synchronized call?
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25765 Location: The netherlands
|
Posted: Mon Dec 30, 2024 3:20 am Post subject: |
|
|
If a crash happens inside the synchronized area it will likely crash yes, but if it's normal GUI access it really shouldn't (and if it would let's just say the rest of CE will soon follow anyhow)
synchronize will stop executing and wait for the main GUI thread to execute the code inside synchronize
when done the thread resumes
synchronize within the main thread just instantly calls the code.
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Mon Dec 30, 2024 3:36 am Post subject: |
|
|
Dark Byte wrote: | If a crash happens inside the synchronized area it will likely crash yes, but if it's normal GUI access it really shouldn't (and if it would let's just say the rest of CE will soon follow anyhow)
synchronize will stop executing and wait for the main GUI thread to execute the code inside synchronize
when done the thread resumes
synchronize within the main thread just instantly calls the code. |
I see! I’ll look elsewhere. Thanks again.
Last thing that pops in mind -
Can synchronized be used as a mutex of sorts to access a shared (global) variable?
If multiple threads try to run a synchronized part simultaneously, would there be concurrency or would one thread halt after another (w/e the order)? (To summarize, are there a couple of “gui” threads, or a single one executing the sync parts?)
Edit: Nvm, I read your reply again and I assume there is just one.
Thank you for your time.
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25765 Location: The netherlands
|
Posted: Mon Dec 30, 2024 7:28 am Post subject: |
|
|
Correct, there's just one main GUI thread, and it will execute the synchronize calls it receives in sequence. (and as mentioned, synchronize in the main GUI thread will just execute the code immediately)
Quote: |
Where should I look at if I’m not getting any exceptions but the main gui thread is frozen?
|
I missed this in the reply. When this happens the main thread is running inside an infinite loop or very long code and it's not calling checkSynchronize nor processMessages
In general, do NOT use infinite loops when the code runs inside the main thread. Same goes for long running codesnippets. (eventually windows will mark the application as non-responsive and bad thing happen at that point)
if you want the user to not do anything while the program is processing things, use a form displayed using showModal(), and set the form's OnCloseQuery to return false. Only allow your code to close the form when it is done
(again, run the code on a separate thread, and only synchronize when closing the form)
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4691
|
Posted: Mon Dec 30, 2024 2:04 pm Post subject: |
|
|
tomerminator wrote: | Can synchronized be used as a mutex of sorts to access a shared (global) variable? | If you're talking about Lua globals, that's probably unnecessary. CE made Lua thread-safe by basically putting one big mutex over everything so only one thread can execute Lua at any given time. Regarding pure Lua, data races won't happen.
Code: | local n_iter = 10000000
local function test(n_threads)
g = 0
local ts = {}
local startTime = getTickCount()
for i = 1,n_threads do
ts[#ts+1] = createThread(function(t)
t.freeOnTerminate(false)
for i=1,n_iter,1 do
g = g + 1
end
end)
end
for _,thread in ipairs(ts) do
thread.waitfor()
assert(thread.Finished)
thread.destroy()
end
local endTime = getTickCount()
print('n_threads:',n_threads)
print('g | deviation:', g, '|', g - n_iter * n_threads)
print('time:', (endTime - startTime)/1000)
print('time per thread:', (endTime - startTime) / 1000 / n_threads)
print''
end
for i = 1,10 do
test(i)
end | Notice how "time per thread" remains mostly unchanged even in environments with multiple hardware threads available. They're executed concurrently but not in parallel.
I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Mon Dec 30, 2024 3:11 pm Post subject: |
|
|
ParkourPenguin wrote: | tomerminator wrote: | Can synchronized be used as a mutex of sorts to access a shared (global) variable? | If you're talking about Lua globals, that's probably unnecessary. CE made Lua thread-safe by basically putting one big mutex over everything so only one thread can execute Lua at any given time. Regarding pure Lua, data races won't happen.
Code: | local n_iter = 10000000
local function test(n_threads)
g = 0
local ts = {}
local startTime = getTickCount()
for i = 1,n_threads do
ts[#ts+1] = createThread(function(t)
t.freeOnTerminate(false)
for i=1,n_iter,1 do
g = g + 1
end
end)
end
for _,thread in ipairs(ts) do
thread.waitfor()
assert(thread.Finished)
thread.destroy()
end
local endTime = getTickCount()
print('n_threads:',n_threads)
print('g | deviation:', g, '|', g - n_iter * n_threads)
print('time:', (endTime - startTime)/1000)
print('time per thread:', (endTime - startTime) / 1000 / n_threads)
print''
end
for i = 1,10 do
test(i)
end | Notice how "time per thread" remains mostly unchanged even in environments with multiple hardware threads available. They're executed concurrently but not in parallel.
I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations. |
Thank you for replying! that makes some* sense.
Now im interested in knowing whether calling CE functions concurrently might break things (I'm most certainly doing that in at least 2 threads which read some part of the memory \ AOB scan).
also, should Mono\.NET functionality happen in a synchronized fashion? I.E Is it safe calling mono invoke method from a thread which is not the main thread?
Is it safe to call mono invoke method 'concurrently'?
My CE freezes seems to be random. could'nt find the cause yet. might run for 3 hours fine, and might crash after 25 minutes.
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25765 Location: The netherlands
|
Posted: Mon Dec 30, 2024 3:14 pm Post subject: |
|
|
the mono library is thread safe. But long operations can lock other threads from access (fixed in the next version)
Also, there's aways the chance that mono just has a bug or unexpected situation and when that happens it's decided by mono_timeout what happens then (if it's 0, it means freeze forever)
ParkourPenguin wrote: |
I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations. |
yes, CE functions do not lock as long as they don't use Lua.
e.g putting
Code: |
local r=md5memory(0x00400000,4096)
|
inside the for loop will show that multiple threads will improve the speed
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Wed Jan 01, 2025 8:18 am Post subject: |
|
|
Dark Byte wrote: | the mono library is thread safe. But long operations can lock other threads from access (fixed in the next version)
Also, there's aways the chance that mono just has a bug or unexpected situation and when that happens it's decided by mono_timeout what happens then (if it's 0, it means freeze forever)
ParkourPenguin wrote: |
I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations. |
yes, CE functions do not lock as long as they don't use Lua.
e.g putting
Code: |
local r=md5memory(0x00400000,4096)
|
inside the for loop will show that multiple threads will improve the speed |
mono_timeout is a parameter to where? mono_invoke_method?
I meant that CE is freezing, not the game (Or I misunderstood you.)
Is there an issue with writing my forms in Lua? would it cause any issues?
(I mean
- testFromblabla=createForm(..)
....)
|
|
Back to top |
|
 |
Dark Byte Site Admin
Reputation: 470
Joined: 09 May 2003 Posts: 25765 Location: The netherlands
|
Posted: Wed Jan 01, 2025 8:32 am Post subject: |
|
|
mono_timeout is a global lua variable defined in monoscript.lua
as long as createForm and subsequent initializing and access code runs in synchronize() and doesn't enter an infinite loop inside there then it should be safe.
(next version ce version will warn for most thread issues )
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
 |
tomerminator Newbie cheater
Reputation: 0
Joined: 20 Nov 2024 Posts: 10
|
Posted: Fri Jan 03, 2025 7:17 am Post subject: |
|
|
Dark Byte wrote: | mono_timeout is a global lua variable defined in monoscript.lua
as long as createForm and subsequent initializing and access code runs in synchronize() and doesn't enter an infinite loop inside there then it should be safe.
(next version ce version will warn for most thread issues ) |
I was so hopeful that was the issue ;P, but it was not..
it seems like the weaker the machine is, the higher the likelyhood of the freeze to occour.
I have test my script on vm's with low amounts of cores and the freeze happens much more frequently.
Im running my script overnight basically, It uses mono, but it seems like the mono framework isnt the issue.
|
|
Back to top |
|
 |
|