This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
qsdqscdvsdvsdsd's profile picture

Concurrency, apis

Started by qsdqscdvsdvsdsd, 06 February 2014 - 06:20 PM
qsdqscdvsdvsdsd #1
Posted 06 February 2014 - 07:20 PM
Hey guys,
I made an api that controls a redpower frame machine (yeah, i know, not latest version….), it works fine. What I wanted to add on to that computer is the ability to resume its work when loading back from shutdown (logging off, etc). I can launch it to go eat whole chunks, but it will stop dead in its track if I log off, inefficient. I made it remember its position just fine, the problem lies in controlling the flow so to say. I'd like, for now, to keep a shell open that allows me to add new tasks to the machine, clear tasks, check on things, with a lua shell (calling api functions). But the machine should keep running through its list of tasks in the background.
I've tried a parallel approach, a snippet I've seen on this forum

local function run()
  shell.run 'dogoals'
end
local function runShell()
  shell.run 'shell'
end
shell.run 'clear'
parallel.waitForAny(run, runShell)
os.shutdown()
the dogoals program loads the api, and executes the loop inside that api that executes the tasks.
What I encountered is that some variables are apparently not shared between the code portions, i.e. I can modify a global variable but the parallel-ed dogoals doesn't see it. As I built persistence for the task list, state is saved to disk and loaded, so I could make the two portions seem to communicate that way. It seems very bad and sloppy to me, is there a better way?

Maybe I could just physically separate the load, like a computer that does the machine control, and its task list is updated via an event handler, listening to rednet messages from the controlling computer.

Cheers.
Himself12794 #2
Posted 07 February 2014 - 01:04 AM
Yes, I would recommend separating the load between various computers and have them communicate via rednet. I built frame machine just like yours that had several functions, and I have found that it is much easier to just have a different computer for each function. What I did, was build an input computer that sends commands to the appropriate computer, like you suggested.

It's much easier I believe than messing with parallel.waitForAny()
Edited on 07 February 2014 - 12:05 AM
LBPHacker #3
Posted 07 February 2014 - 04:33 AM
If you're on Minecraft 1.4.7, the parallel API will always be more efficient than sharing the load between computers. If you want to run five separate tasks, that's +5 coroutines using the parallel API (and the 2 coroutines which run on the computer by default). If you do that on five separate computers, that's +8 coroutines, because the 4 new computers each run two coroutines (the rednet and the shell).

As for the problem of communicating between corotuines, functions declared in the same scope should see the global variables (or, in my approach, the local ones as well:)
local a = 8
local function f()
    while true do os.pullEvent("key") print(a) end
end
local function g()
    while true do os.pullEvent("key") print(a) end
end
parallel.waitForAny(f, g)
-- run this: you will get "8" twice each time you press a key
qsdqscdvsdvsdsd #4
Posted 12 February 2014 - 07:30 AM
I've finally done it through multiple computers, one sending goals to another that executes them and persists them, it works fine. I still have kinks in the location aware movement, but thanks for your help guys.