Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal
  • 0
Dustmuz

coroutine - Parallel - something

Question

Hello. 

i'm rather new to OC. and missing my Parallel API from CC. 

i'm trying to run 4 different functions at the same time, they are writing to different parts of the screen (power monitor) 
Is there a way to do this, and what should i read up upon. 

personally, i think that the OC wiki, is lacking a great deal, when it comes to examples, and in general explaning things, when youre trying to learn. 
it covers the absoute basic of building the computer, and thats about where the usefullness stops - for me at least. its in no way helpfull :( which i find a bit sad, as it should be the goto place :) 

so a short code snippet of how you could run multiple functions at the same time would be helpfull. 

Link to post
Share on other sites

10 answers to this question

Recommended Posts

  • 1
  • Solution

A partial demo of your first script. Should get the ball rolling..

local component = require "component"
local thread = require "thread"
local event = require "event"
local text = require "text"
local term = require "term"

-- # make a function that formats part(s) of its input
local function status_print(x, y, pat, format)
  return function(str)
    term.setCursor(x, y)
    -- # pad the output to wipe old overhanging chars from prev long outputs
    term.write(text.padRight(str:gsub(pat, format), 30))
  end
end

-- # NOTE: all the 'print format' functions below are using arbitrary values
--      for things like `maxCaseTemp` and `warnCaseTemp`. Tweak bounds to
--      your satisfaction.

-- # `print energy cell power`
-- # Usage: pECPower "Total Energy: 100001" -->  "Total Energy: \27[32m100001\27[37m"
local pECPower = status_print(2, 3, "(%d+)", function(amount)
  -- # wrap power amount in vt100 color codes depending on int value
  -- # `\27[37m` resets fg color to white
  return (tonumber(amount) > 100000 and '\27[32m' or '\27[31m') .. amount .. '\27[37m'
end)

local energyLastTick = 0 -- # initial value so we don't crash as we start :3
local pReactorPower = status_print(2, 6, "(%d+)", function(amount)
  -- # wrap amount in green if energy production is up, red if down.
  local output = (tonumber(amount) > energyLastTick and '\27[32m' or '\27[31m') .. amount .. '\27[37m'
  energyLastTick = tonumber(amount)
  return output
end)

-- # Tweak these bounds to signal properly
local maxCaseTemp, warnCaseTemp = 1000000, 900000
local pRCaseTemp = status_print(2, 8, "(%d+)", function(amount)
  -- # danger, warning, and normal color formats
  local temp = tonumber(amount)
  if temp >= maxCaseTemp then
    return '\27[31m' .. amount .. '\27[37m'
  elseif temp >= warnCaseTemp then
    return '\27[33m' .. amount .. '\27[37m'
  else
    return '\27[32m' .. amount .. '\27[37m'
  end
end)

-- # Tweak these too..
local maxFuelTemp, warnFuelTemp = 1000000, 900000
local pRFuelTemp = status_print(2, 9, "(%d+)", function(amount)
  -- # see pRCaseTemp().
  local temp = tonumber(amount)
  if temp >= maxFuelTemp then
    return '\27[31m' .. amount .. '\27[37m'
  elseif temp >= warnFuelTemp then
    return '\27[33m' .. amount .. '\27[37m'
  else
    return '\27[32m' .. amount .. '\27[37m'
  end
end)


-- # the meat.
local function monitorPower(cells, ref_rate)
  while true do
    local sum = 0
    for address, _ in pairs(cells) do
      sum = sum + (component.invoke(address, 'getEnergyStored') or 0)
      -- # yield for a while so we dont spam component calls and because we have to somewhere..
      event.pull(ref_rate or .25)
    end
    pECPower("Total Power: " .. tostring(sum) .. 'rf')
  end
end
-- # more meat.
local function monitorReactor(reactor, ref_rate)
  while true do
    pReactorPower("Power produced: " .. tostring(reactor.getEnergyProducedLastTick()) .. 'rf/t')
    pRCaseTemp("Case temp: " .. tostring(reactor.getCasingTemperature()) .. '°C')
    pRFuelTemp("Fuel temp: " .. tostring(reactor.getFuelTemperature()) .. '°C')
    -- # yield for a bit. consider it a 'refresh rate'
    event.pull(ref_rate or 1)
  end
end

-- # lies. virtual reactor. I dont want to build all this shit.. sorry
-- # create your `monitorReactor` thread with a real reactor component proxy.
local mockReactor = {
  getEnergyProducedLastTick = function() return math.random(5000, 1000000) end,
  getFuelTemperature = function() return math.random(500000, 1000001) end,
  getCasingTemperature = function() return math.random(500000, 1000001) end
}

-- # the things we do.
local threads = {
  -- # TE energy cells are typed as `energy_device` in my pack. Tweak if needed
  thread.create(monitorPower, component.list('energy_device'), 1),
  thread.create(monitorReactor, mockReactor),
  -- # clean up thread. hit ctrl+c to exit program
  thread.create(function()
    local name
    repeat
      name = event.pull(0, 'interrupted')
    until name == 'interrupted'
    print "\nquitting.."
  end)
}

-- # do the stuff until we interrupt the fun.
thread.waitForAny(threads)
os.exit(0) -- # stab all the other threads to death so we can finish

--[[
  #  ** I know this isn't your whole program but it should demo how to use threads.
  #  All of those format functions are just there to keep the threads as simple
  #  as possible. They bake in [x,y] coords and a formatting function that wraps
  #  text in 'vt100' color codes('cause I'm duckin' lazy thats why).
]]

 

Link to post
Share on other sites
  • 0

Basically the api is more flexible.. 

local function counter(num)
    local i = num or 0
    while i < 25 do
      print(i)
      os.sleep(1)
      i = i + 1
    end
end

local threadA = thread.create(counter, 1)
local threadB = thread.create(counter, 5)

--# Normally these will start and continue running asap. However, you
--# can block the program from exiting early by using the 'waitForAll' and 'waitForAny' methods i.e

thread.waitForAny({threadA, threadB})

 

Link to post
Share on other sites
  • 0
2 hours ago, Molinko said:

Basically the api is more flexible.. 


local function counter(num)
    local i = num or 0
    while i < 25 do
      print(i)
      os.sleep(1)
      i = i + 1
    end
end

local threadA = thread.create(counter, 1)
local threadB = thread.create(counter, 5)

--# Normally these will start and continue running asap. However, you
--# can block the program from exiting early by using the 'waitForAll' and 'waitForAny' methods i.e

thread.waitForAny({threadA, threadB})

 

Hi again :D

 

i actually just made this up.
from what i gather, from the code snippets of the wiki - but it only shows

Start
End


the threads are never run.

 

 

 

	local thread = require("thread")
local component = require("component")
local gpu = component.gpu
local event = require("event")
local colors = require("colors")
local term = require("term")
	
gpu.setResolution(120,30)
	local TEcell1 = component.proxy("98a5d647-be62-4c6a-ba60-749715173e73")
local TEcell2 = component.proxy("af0e927a-3235-4f67-ag46-dcd5aed640f8")
local TEcell3 = component.proxy("ef7fa5d2-aa29-4258-a573-23d8e73d9ab2")
	print("start")
local t1 = thread.create(function()
  while true do
    --cell1
    gpu.setBackground(colors.Blue)
    local maxEnergy = TEcell1.getMaxEnergyStored()
    gpu.fill(10,9,110,10," ")
    local cellStored1 = TEcell1.getEnergyStored()
    local perc = math.floor((cellStored1/maxEnergy)*100)
    gpu.setBackground(colors.green)
    gpu.fill(10,9,perc,10," ")
    term.setCursor(10,8)
    term.clearLine()
    print("Resonant Cell: "..perc)
    end
end)
	local t2 = thread.create(function()
  while true do
    --cell2
    gpu.setBackground(colors.Blue)
    local maxEnergy = TEcell2.getMaxEnergyStored()
    gpu.fill(10,9,110,10," ")
    local cellStored2 = TEcell2.getEnergyStored()
    local perc = math.floor((cellStored2/maxEnergy)*100)
    gpu.setBackground(colors.green)
    gpu.fill(10,14,perc,15," ")
    term.setCursor(10,13)
    term.clearLine()
    print("Resonant Cell: "..perc)
  end
end)
	thread.waitForAny({t1, t2})
print("end")
	
 




i'm gonna try moving the functions out of the thread.create() as you do in your example, and see if that actually helps..
if it does, then the snippets on the wiki, might have to be changed or explained better at least :)

EDIT: after messing about a little.
your code works fine, but as soon as try manipulating the screen with the below code inside your function - nothing happens. it just finishes.
if i try and run the code without doing it in a thread. it works

        local maxEnergy = TEcell1.getMaxEnergyStored()
        local cellStored1 = TEcell1.getEnergyStored()
        local perc = math.floor((cellStored1/maxEnergy)*100)
        term.clearLine()
        term.setCursor(10,13)
        term.write("Resonant Cell: "..perc)
 
        gpu.setBackground(blue)
        gpu.fill(perc+1,9,100-perc,2," ")
        gpu.setBackground(black)
        gpu.setBackground(green)
        gpu.fill(10,14,perc,2," ")
        gpu.setBackground(black)
 
 

	local thread = require("thread")
local component = require("component")
local gpu = component.gpu
local event = require("event")
local colors = require("colors")
local term = require("term")
gpu.setResolution(120,30)
	local TEcell1 = component.proxy("98a5d647-be62-4c6a-ba60-749715173e73")
local TEcell2 = component.proxy("af0e927a-3235-4f67-ag46-dcd5aed640f8")
local TEcell3 = component.proxy("ef7fa5d2-aa29-4258-a573-23d8e73d9ab2")
	local function counter(num)
    local i = num or 0
    while i < 25 do
        --cell1
        local maxEnergy = TEcell1.getMaxEnergyStored()
        local cellStored1 = TEcell1.getEnergyStored()
        local perc = math.floor((cellStored1/maxEnergy)*100)
        term.clearLine()
        term.setCursor(10,8)
        term.write("Resonant Cell: "..perc)
	        gpu.setBackground(blue)
        gpu.fill(perc+1,9,100-perc,2," ")
        gpu.setBackground(black)
        gpu.setBackground(green)
        gpu.fill(10,9,perc,2," ")
        gpu.setBackground(black)
    end
end
	local function counter1(num)
    local i = num or 0
    while i < 25 do
        --cell1
        local maxEnergy = TEcell1.getMaxEnergyStored()
        local cellStored1 = TEcell1.getEnergyStored()
        local perc = math.floor((cellStored1/maxEnergy)*100)
        term.clearLine()
        term.setCursor(10,13)
        term.write("Resonant Cell: "..perc)
	        gpu.setBackground(blue)
        gpu.fill(perc+1,14,100-perc,2," ")
        gpu.setBackground(black)
        gpu.setBackground(green)
        gpu.fill(10,14,perc,2," ")
        gpu.setBackground(black)
     end
end
local threadA = thread.create(counter, 1)
local threadB = thread.create(counter1, 1)
	--# Normally these will start and continue running asap. However, you
--# can block the program from exiting early by using the 'waitForAll' and 'waitForAny' methods i.e
 
thread.waitForAny({threadA, threadB})
	

 

Link to post
Share on other sites
  • 0

The issue with your adaptation is that is doesn't yield. As in coroutine.yield()

Threads from the thread lib are fancy objects based around coroutines. Coroutines, basically, are functions you can pause(yield). This means they do a little something and before they return, they yield.

Yielding is basically a way to generate values before a final value is returned. More importantly threads(coroutines) pause(yield) so other routines(functions) can run(and presumably yield or return quickly), but lets not forget they resume as well, to finish their doings...

In my example I use the os.sleep(1) call to yield the running thread(fancy coroutine). 

There are other issues with your program, but just to be clear, threads are a little more than just plug and play and my example shouldn't be adapted to achieve your goals.

Link to post
Share on other sites
  • 0

and im back again :(

i've tried playing around with this, and as you say.
It's not just plug and play.

tried reading up on it, and that only confused me even more.
i can get very simple scripts to run, but as soon as i try and do something that pulls info from other blocks, it just stops working.

i ended up just adding in CC again, to be able to do this.


Problem with OC, is that theres not much info to get, anywhere. not even here..
A better description/tutorials on some of the "advanced" stuff, would be very helpfull, and why (from what i see on servers) most people still use CC over OC.
the learning curve for OC, is like climbing to the moon on a ladder.

 

Link to post
Share on other sites
  • 0

i couldnt agree more with that.
OC has a ton more possibilities and is integrated with most mods.

from the code above, i have added a total of 9 TE resonant energy cells.
1x Extreme reactor (only as last resort, tweaked config so it used 50x the fuel)
8x magmatic dynamo's for main power (cant be controlled with CC - so using a redstone output for this)
2x bio fuel generators (cant be controlled with CC - so using a redstone output for this)

from what i've been able to gather, OC can has methods for both mods (TE and industrialforegoing) also a good reason to use OC

This is the code i use for my Extreme reactor and powerstorage

	Above here, is all the peripheral wraps, and os.load(ButtonAPI) and a few other "irrelevant" things, nothing that is crucial to the code.
Mon, is just the monitor connected to the computer.
    
mon.clear()    
mon.setCursorPos(2,1)    
mon.setTextColor(blue)    
mon.write("Menphis's Power Bank Monitor")        
mon.setCursorPos(2,4)    
mon.write("Total Energy Capacity: "..TotalCapMill.." Mill")              
local function Power()
      
    while true do        
        teCell1en = Cell1.getEnergyStored()        
        teCell2en = Cell2.getEnergyStored()        
        teCell3en = Cell3.getEnergyStored()        
        teCell4en = Cell4.getEnergyStored()        
        teCell5en = Cell5.getEnergyStored()        
        teCell6en = Cell6.getEnergyStored()        
        teCell7en = Cell7.getEnergyStored()        
        teCell8en = Cell8.getEnergyStored()        
        teCell9en = Cell9.getEnergyStored()             
        EnergyStored = teCell1en + teCell2en + teCell3en + teCell4en + teCell5en + teCell6en + teCell7en + teCell8en + teCell9en        
        EnergyStoredMill = math.floor(EnergyStored / 1000000)             
        if EnergyStored > 100000 then          
            mon.setCursorPos(2,3)          
            mon.clearLine()          
            mon.setTextColor(green)          
            mon.write("Total Energy Stored: "..EnergyStoredMill.." Mill")          
        elseif EnergyStored < 100000 then          
            mon.setCursorPos(2,3)              
            mon.clearLine()          
            mon.setTextColor(red)          
            mon.write("Total Energy Stored: "..EnergyStored)        
        end        
        
        mon.setTextColor(white)        
        sleep(2)      
    end    
end         
	local function ProducedPower()      
    while true do        
        mon.setCursorPos(2,6)        
        mon.setTextColor(red)        
        local Prod = math.floor(Reac.getEnergyProducedLastTick())        
        mon.write("Produced RF: "..Prod)       
        mon.setTextColor(white)        
        sleep(2)      
    end    
end         
	local function Temp()      
    while true do        
        mon.setTextColor(green)        
        mon.setCursorPos(2,8)        
        local CaseTemp = math.floor(Reac.getCasingTemperature())        
        local FuelTemp = math.floor(Reac.getFuelTemperature())        
        mon.write("Case Temp: "..CaseTemp.." Celcius")        
        mon.setCursorPos(2,9)        
        mon.write("Fuel Temp: "..FuelTemp.." Celcius")        
        mon.setTextColor(white)        sleep(2)      
    end    
end         
	local function button()      
    while true do        
        local event = {t:handleEvents()}        
        if event[1] == "button_click" then          
            t:toggleButton(event[2])        
        end      
    end    
end              
	local function rfGen(bool)      
    if bool == true then        
        Reac.setActive(true)      
    else        
        Reac.setActive(false)      
    end    
end         
	default.label = "Button1"    default[1] = "OFF"    t:add(default,function(bool) rfGen(bool) return "ON", "OFF" end ,30,1,33,1,red,green,black,black)              
t:draw()         
	while true do      
    parallel.waitForAny(Temp,ProducedPower,Power,button,rfgen)    
end   
	

 

The code for controlling the 4 IC2 Reactors

	    term.setTextColor(blue)    
    print("Reactor Status")    
    term.setTextColor(red)    
    print("Reactor 1: "..r1active)    
    print("Reactor 2: "..r2active)    
    print("Reactor 3: "..r3active)    
    print("Reactor 4: "..r4active)              
    
    while true do            
        local event, button, MouseX, MouseY = os.pullEvent("mouse_click")            
        if (MouseX >= 12 and MouseX <= 13) and MouseY == 2 then                    
            if r1active == "off" then                            
                rs.setOutput("top",true)                            
                r1active = "on"                            
                pos(1,2)                            
                term.clearLine()                            
                term.setTextColor(green)                            
                term.write("Reactor 1: "..r1active)                    
            elseif r1active == "on" then                            
                rs.setOutput("top",false)                            
                r1active = "off"                                                           
                pos(1,2)                            
                term.clearLine()                            
                term.setTextColor(red)                            
                term.write("Reactor 1: "..r1active)
            end            
        elseif (MouseX >= 12 and MouseX <= 13) and MouseY == 3 then                    
            if r2active == "off" then                            
                rs.setOutput("left",true)                           
                r2active = "on"                                                    
                pos(1,3)                            
                term.clearLine()                            
                term.setTextColor(green)                            
                term.write("Reactor 2: "..r2active)                    
            elseif r2active == "on" then                            
                rs.setOutput("left",false)                            
                r2active = "off"                                                           
                pos(1,3)                            
                term.clearLine()                            
                term.setTextColor(red)                            
                term.write("Reactor 2: "..r2active)                    
            end                        
        elseif (MouseX >= 12 and MouseX <= 13) and MouseY == 4 then                    
            if r3active == "off" then                            
                rs.setOutput("back",true)                            
                r3active = "on"                                                    
                pos(1,4)                            
                term.clearLine()                            
                term.setTextColor(green)                            
                term.write("Reactor 3: "..r3active)                    
            elseif r3active == "on" then                            
                rs.setOutput("back",false)                            
                r3active = "off"                            
                pos(1,4)                            
                term.clearLine()                            
                term.setTextColor(red)                            
                term.write("Reactor 3: "..r3active)                    
            end                        
        elseif (MouseX >= 12 and MouseX <= 13) and MouseY == 5 then                    
            if r4active == "off" then                            
                rs.setOutput("front",true)                            
                r4active = "on"                            
                pos(1,5)                            
                term.clearLine()                            
                term.setTextColor(green)                            
                term.write("Reactor 4: "..r4active)                    
            elseif r4active == "on" then                            
                rs.setOutput("front",false)                            
                r4active = "off"                            
                pos(1,5)                            
                term.clearLine()                            
                term.setTextColor(red)                            
                term.write("Reactor 4: "..r4active)                    
            end                
        end    
    end   
	

 

the 2 code snippets above, is the ones that i need to have running.
as you can see. firs one, that controls the reactor and such, has 4 functions running at the same time, and then another one for the IC2

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.