Clarification about "Thread related functionality"

Typically: "How do I... ", "How can I... " questions
Post Reply
davide.barchi
Posts: 5
Joined: 28 May 2018, 08:52

Clarification about "Thread related functionality"

Post by davide.barchi »

Hi! I'm Davide and I have just started doing some jobs in VREP.

I would like to have some explanation about users's tool provided in order to achieve synchronization in threated applications.Mainly i do not understand the difference between " sim.setThreadAutomaticSwitch + sim.switchThread" and "sim.setThreadIsFree" given that the goal is basically ensure some blocking operations .

Thanks,
Davide

coppelia
Site Admin
Posts: 10339
Joined: 14 Dec 2012, 00:25

Re: Clarification about "Thread related functionality"

Post by coppelia »

Hello Davide,

a threaded child script is running more like a coroutine than a thraditional thread:

By default, when a threaded child script is launched, it will execute about 2ms. Then V-REP will interrupt or pause it, and only resume it in next simulation step (i.e. when the simulation time has become t=t+dt). It will resume for about 2ms, and be interrupted again. And resume again in next simulation step, and so on, and so forth.

Following example illustrates this:

Code: Select all

function sysCall_threadmain()
    local lastSimulationTime=sim.getSimulationTime()
    local simulationStep=sim.getSimulationTimeStep()
    while true do
        local cnt=0
        -- Inner loop:
        while sim.getSimulationTime()==lastSimulationTime do
            cnt=cnt+1
        end
        printf('Inner loop executed %i times for one simulation step.',cnt)
        local dt=sim.getSimulationTime()-lastSimulationTime
        printf('Thread was interrupted %i times since last simulation step.',math.floor((dt/simulationStep)+0.5))
        lastSimulationTime=sim.getSimulationTime()
    end
end
In above example, the inner loop gets executed many times for each simulation step. Interruption happens automatically,

Now just add sim.switchThread() as in following example:

Code: Select all

function sysCall_threadmain()
    local lastSimulationTime=sim.getSimulationTime()
    local simulationStep=sim.getSimulationTimeStep()
    while true do
        local cnt=0
        -- Inner loop:
        while sim.getSimulationTime()==lastSimulationTime do
            cnt=cnt+1
            sim.switchThread()
        end
        printf('Inner loop executed %i times for one simulation step.',cnt)
        local dt=sim.getSimulationTime()-lastSimulationTime
        printf('Thread was interrupted %i times since last simulation step.',math.floor((dt/simulationStep)+0.5))
        lastSimulationTime=sim.getSimulationTime()
    end
end
In above example, the inner loop gets executed almost exactly once for each simulation step. You are deciding when to interrupt. But the automatic interruption can still occur.

Now modify above example with a delay, so that it spends a little bit more time for each inner loop pass, to better visualize that the automatic switch is still happening:

Code: Select all

function sysCall_threadmain()
    local lastSimulationTime=sim.getSimulationTime()
    local simulationStep=sim.getSimulationTimeStep()
    while true do
        local cnt=0
        -- Inner loop:
        while sim.getSimulationTime()==lastSimulationTime do
            for j=1,100000,1 do end -- delay loop
            cnt=cnt+1
            sim.switchThread()
        end
        printf('Inner loop executed %i times for one simulation step.',cnt)
        local dt=sim.getSimulationTime()-lastSimulationTime
        printf('Thread was interrupted %i times since last simulation step.',math.floor((dt/simulationStep)+0.5))
        lastSimulationTime=sim.getSimulationTime()
    end
end
Now you clearly see that you are still not fully in control about the switching moment. In order to be able to perfectly synchronize your threaded script, you need to disable automatic thread switching, as in following example:

Code: Select all

function sysCall_threadmain()
    sim.setThreadAutomaticSwitch(false)
    local lastSimulationTime=sim.getSimulationTime()
    local simulationStep=sim.getSimulationTimeStep()
    while true do
        local cnt=0
        -- Inner loop:
        while sim.getSimulationTime()==lastSimulationTime do
            for j=1,100000,1 do end -- delay loop
            cnt=cnt+1
            sim.switchThread()
        end
        printf('Inner loop executed %i times for one simulation step.',cnt)
        local dt=sim.getSimulationTime()-lastSimulationTime
        printf('Thread was interrupted %i times since last simulation step.',math.floor((dt/simulationStep)+0.5))
        lastSimulationTime=sim.getSimulationTime()
    end
end
Cheers

davide.barchi
Posts: 5
Joined: 28 May 2018, 08:52

Re: Clarification about "Thread related functionality"

Post by davide.barchi »

Thanks for the example, now things seems to be much clear. Just another question, what about " simSetThreadFree"?
In my mind, these bottom situations are the same:

Code: Select all

-- EXAMPLE with AutomaticSwitch
function sysCall_threadmain()
    while true do
    	sim.setThreadAutomaticSwitch(true)
    	-- some non ordinary routine here 
    	
    	sim.setThreadAutomaticSwitch(false)
    	-- some routines that need to be blocked
	sim.setThreadAutomaticSwitch(true) -- end of the blocking part OR sim.switchThread()
end

Code: Select all

-- EXAMPLE with setThreadIsFree
function sysCall_threadmain()
    while true do
    	-- some non ordinary routine here 
    	
    	sim.setThreadIsFree(false) -- start of the blocking part
    	-- some routines that need to be blocked
	sim.setThreadIsFree(true) --end of the blocking part
end
Cheers

coppelia
Site Admin
Posts: 10339
Joined: 14 Dec 2012, 00:25

Re: Clarification about "Thread related functionality"

Post by coppelia »

sim.setThreadIsFree is kind of dangerous to use: it basically turns your coroutine into a real thread: in that case, you are not allowed to call the V-REP API, otherwise you risk collisions and crashes. I highly recommend not to use it.

Cheers

Post Reply