Page 1 of 2
thread:pause() ?
Posted: Mon Oct 13, 2014 2:39 pm
by Luke100000
I'm working on a game, where the player can write own code into an virtual computer. Because the main-loop should not stop, a thread is needed. The virtual computers are slow, ~1 MHz. To control them I have an extra thread who only controls all the computers.
Code: Select all
while true do
local time = os.clock()
for i = 1, #threads do
threads[i]:start()
love.timer.sleep(virtualCPUspeed / realCPUspeed)
threads[i]:pause() --And here's the problem, there is no pause.
end
love.timer.sleep(1 - (os.clock - time) )
end
The computers have every second some time to do their work.
Sorry for my English, I think I made some spelling errors
Re: thread:pause() ?
Posted: Mon Oct 13, 2014 7:04 pm
by Nixola
You should implement sleeping inside the thread itself, not outside of it. The thread can't be controlled directly from the outside, you've got to control it from within itself.
Re: thread:pause() ?
Posted: Mon Oct 13, 2014 7:27 pm
by slime
[wiki]Channel:demand[/wiki], [wiki]Channel:supply[/wiki], and [wiki]love.timer.sleep[/wiki] will all pause the thread the functions are called from (until the condition is met.) As Nixola mentioned, you'll need to do it from inside the thread's code rather than outside.
It's also generally a good idea to do a while-loop from inside the thread's code rather than constantly restarting it, since starting a thread is very expensive compared to just continuing a loop (and that gives you a great place to use the above functions to pause the thread.)
Re: thread:pause() ?
Posted: Tue Oct 14, 2014 10:01 am
by Luke100000
How can I do this, so that the player can't delete this love.timer.sleep() ?
The player could use a while-loop!
Can I yield a coroutine automatically after time? Something like this: coroutine:resume(forSeconds)
Re: thread:pause() ?
Posted: Wed Oct 15, 2014 1:00 pm
by Xgoff
Luke100000 wrote:How can I do this, so that the player can't delete this love.timer.sleep() ?
The player could use a while-loop!
unless this is a server program, i wouldn't worry too much about the user shooting their own foot
Can I yield a coroutine automatically after time? Something like this: coroutine:resume(forSeconds)
well, yes and no. unlike pre-emptive threads, coroutines have full control over their own yielding. you *could* write wrappers around the coroutine functions that cause a coroutine to yield itself automatically after some time period, but it will still be vulnerable to infinite loops or even long-running code, again because coroutines are not pre-emptive
Re: thread:pause() ?
Posted: Wed Oct 15, 2014 5:53 pm
by Robin
Actually, now that I think of it, Kikito has
written a sandbox library that limits the time a function can run. It might be something you can use.
Re: thread:pause() ?
Posted: Wed Oct 15, 2014 6:08 pm
by Luke100000
OK that's maybe a stupid idea: When the player launch the code, it will create a special love.timer.sleep() in front of every end/else/elseif.
Something like this:
--- original code
Code: Select all
local a = 0
while true do
if a < 100 then
a = a + 1
else
a = 0
end
end
-- code after launching
Code: Select all
local a = 0
while true do
if a < 100 then
a = a + 1
wait()
else
a = 0
wait()
end
wait()
end
It should work.
Xgoff wrote:Luke100000 wrote:How can I do this, so that the player can't delete this love.timer.sleep() ?
The player could use a while-loop!
unless this is a server program, i wouldn't worry too much about the user shooting their own foot
It's not a server, but there are different in-game-computer with different speed.
Xgoff, did you write "OBEY" in hexadecimal on your avatar?
Robin wrote:Actually, now that I think of it, Kikito has
written a sandbox library that limits the time a function can run. It might be something you can use.
Yeah that's great. The player can create short lag spikes but it's something I was looking for. At first.
Re: thread:pause() ?
Posted: Wed Oct 15, 2014 7:36 pm
by Robin
Luke100000 wrote:OK that's maybe a stupid idea: When the player launch the code, it will create a special love.timer.sleep() in front of every end/else/elseif.
That sounds exploitable.
If you implement that, I'd like to take a look at that, see if I can find ways to abuse it.
Re: thread:pause() ?
Posted: Sat Oct 18, 2014 3:38 pm
by Luke100000
Code: Select all
local lastTime = false
local timewhenstarted = love.timer.getTime()
local time = 0
local CPUspeed = 20 --MHz, the virtual-computer
local realCPUspeed = 3 * 3200 --MHz, my computer
local sleepAfter = CPUspeed / realCPUspeed
function wait()
local microtime = love.timer.getTime()
if lastTime then
time = time + ( microtime - lastTime )
if time > sleepAfter then
love.timer.sleep( sleepAfter * ( realCPUspeed / CPUspeed - 1 ) )
microtime = microtime + sleepAfter * ( realCPUspeed / CPUspeed - 1 )
time = time - sleepAfter
end
end
lastTime = microtime
if microtime - timewhenstarted > 10 then
print( "loops per second: " .. math.floor( a/10 ) .. "\n" )
os.exit()
end
end
function transformCode(code)
local i = 0
local functname = "wait()"
local commandsToCheck = {"end", "else", "elseif"}
local string = code
for i,v in ipairs(commandsToCheck) do
while true do
i, j = string.find(string .. " ", v, i + 2 + #functname)
if i == nil then
break
end
string = string.sub(string, 1, i - 1) .. functname .. " " .. string.sub(string, i, #string)
end
end
--remove all \n
while true do
i, j = string.find(string, "\n")
if i == nil then
break
end
string = string.sub(string, 1, i-1) .. " " .. string.sub(string, i+1, #string)
end
return string
end
local original_code = "a = 0\nwhile true do\n a = a + 1\nend"
local code = transformCode( original_code .. " " )
print("\nORIGINALCODE:\n" .. original_code .. "\n\nCODE:\n" .. code .. "\n")
local func, msg = pcall( loadstring( code ) )
if func then
func()
else
print("ERROR: " .. msg)
end
original_code is the code which can be written by the player. Because the player can write several lines, my "transformCode()" delete all "\n"
realCPUspeed is your PC, I need a library to check this automatically
CPUspeed is the speed of the ingame-computer. I type 20 MHz, this is very slow.
For this example, I will stop the code in the wait() function and print out the progress.
Re: thread:pause() ?
Posted: Sat Oct 18, 2014 6:42 pm
by Robin
Why do you remove all \n, tough?
Also, both adding wait() and removing \n could be done with simply calling [manual]string.gsub[/manual] instead of those expensive
Also:
Code: Select all
function wait() end
local a = 0
while true do
if a < 100 then
a = a + 1
else
a = 0
end
end
Also, this way I can't use
return anywhere, I don't know if that's intended.