I am trying to get into multithreading, but my threads are just not doing what they should, they just silently stop working.
This is the full code, (i am trying to use regions, but made sure it was not a weird error related to them, and tried it with arc with the same result):
when not compileOption("gc", "regions"):
type MemRegion = distinct int
template withScratchRegion(code: untyped) = code
template withRegion(x: MemRegion, code: untyped) = code
const RLBOT_NUM_AGENTS* = 2
type
RocketLeagueEnv* = object
ball*: ref Ball
agents*: array[2, ref CarAgent]
updateTick*: bool
when false: #still not used
fieldData*: seq[Vector3]
ballPrediction*: array[360, Ball]
Ball* = object
location*: Vector3
velocity*: Vector3
rotation*: Vector3
done*: bool
CarAgent* = object
location*: Vector3
velocity*: Vector3
rotation*: Vector3
done*: bool
proc step*(this: ref CarAgent) =
discard
proc step*(this: ref Ball) =
discard
proc CarStepThread*(args: tuple[rawEnv: pointer, idx: int]) {.thread, noReturn.} =
var env: ptr RocketLeagueEnv = cast[ptr RocketLeagueEnv](args.rawEnv)
while true:
if env[].updateTick and not env[].agents[args.idx].done:
withScratchRegion:
echo "updating"
env[].agents[args.idx].step()
env[].agents[args.idx].done = true
else:
withScratchRegion:
echo "not updating"
withScratchRegion:
echo "why broke :/"
proc BallStepThread*(rawEnv: pointer) {.thread, noReturn.} =
var env: ptr RocketLeagueEnv = cast[ptr RocketLeagueEnv](rawEnv)
while true:
if env[].updateTick and not env[].ball.done:
withScratchRegion:
echo "updating"
env[].ball.step()
env[].ball.done = true
var carsDone: int = 0
while carsDone < RLBOT_NUM_AGENTS:
carsDone = 0
for i in env[].agents:
if i.done:
inc carsDone
env[].updateTick = true
else:
withScratchRegion:
echo "not updating"
withScratchRegion:
echo "why broke :/"
proc main() =
var
mainRegion: MemRegion
ballPhysicsThread: Thread[pointer]
agentsPhysicsThreads: array[RLBOT_NUM_AGENTS, Thread[tuple[rawEnv: pointer, idx: int]]]
env: ref RocketLeagueEnv # since im using manual memory management, it wont matter (?)
# also tried making it a raw ptr and using createShared instead of new, didnt work either.
withregion mainRegion:
env = new RocketLeagueEnv
env.updateTick = true
withScratchRegion:
echo "starting threads..."
ballPhysicsThread.createThread(BallStepThread, toPtr(env))
withScratchRegion:
echo "started ball thread..."
for i in 0..<RLBOT_NUM_AGENTS:
withScratchRegion:
echo "started car ", i, " thread..."
agentsPhysicsThreads[i].createThread(CarStepThread, (toPtr(env), i))
main()
Everything compiles fine, but the output of the executable is:
threads...
started ball thread...
started car 0 thread...
started car 1 thread...
And thats it.
Is this some kind of known issue because im doing something wrong? Thanks in advance.
You need to initialize Ball and the two car agents here:
withregion mainRegion:
env = new RocketLeagueEnv
env.updateTick = true
# ball and the array of car agents both are nil
env.ball = new Ball
env. agents[0] = new CarAgent
env.agents[1] = new CarAgent
You should be getting a segfault from your program. Do you not see one?
Also, you should use joinThreads for your threads instead of joining right after creation.
joinThreads(agentsPhysicsThreads)
joinThreads([ballPhysicsThread])