Jump to content




Run code "in background"


19 replies to this topic

#1 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 06 August 2014 - 04:25 AM

So, let's say we (theoretically) want to run some code parallel of a main program, but we are making an API. How would you accomplish this? I've stumbled upon the answer.
You will want to have a good understanding of
-os.pullEvent
-coroutines
-functions
-variables
-etc.
before continuing.

Step 1: Make some looping code in a function
Example:
function foo()
  while true do
	local event = { os.pullEvent( "modem_message" ) }
	--#do stuff with it
  end
end
Now, while this code does not seem particularly useful, it can be. You may want to "network" several devices together and listen for the specific events they send.

Step 2: Backup os.pullEventRaw() and create a coroutine
local oldPull = os.pullEventRaw --#note the lack of parentheses
local coFoo = coroutine.create( foo ) --#note "foo" does not have parentheses

Step 3: Overwrite os.pullEventRaw()
function os.pullEventRaw( sFilter )
  while true do
	local event = { oldPull() } --#note I am using the backup
	if coroutine.status( coFoo ) == "suspended" then --#we to make sure it is not our function (now a coroutine) calling it.
	   coroutine.resume( coFoo, unpack( event ) ) --#unpack( tbl ) returns the contents of the table.
	end
	if sFilter == event[ 1 ] or not sFilter then --#if the event is the correct type, or there is no filter;
	  return unpack( event )
	end
  end
end

If you wished, you could even have this iterate through different coroutines. I suspect you could also write a function to insert additional coroutines into the program, but I think it would be highly unnecessary.

Questions? Comments?

#2 Engineer

  • Members
  • 1,378 posts
  • LocationThe Netherlands

Posted 06 August 2014 - 11:41 AM

You would want to override coroutine.yield, because that is the real os.pullEventRaw()

#3 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 06 August 2014 - 09:48 PM

View PostEngineer, on 06 August 2014 - 11:41 AM, said:

You would want to override coroutine.yield, because that is the real os.pullEventRaw()
I hesitate to overwrite coroutine functions as I don't fully understand them.

#4 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 07 August 2014 - 12:54 AM

coroutine.yield is the same as the pull events, that's actually what they use. Perhaps you should get an understanding of that and improve upon your tutorial, at the moment it is a little lacking, not quite to the standard we are looking for in a tutorial. Take a look at Lyqyd's or my own tutorials for the Ask a Pro series to see the rough standard we are looking for in tutorials.

#5 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 07 August 2014 - 05:14 AM

View Posttheoriginalbit, on 07 August 2014 - 12:54 AM, said:

coroutine.yield is the same as the pull events, that's actually what they use. Perhaps you should get an understanding of that and improve upon your tutorial, at the moment it is a little lacking, not quite to the standard we are looking for in a tutorial. Take a look at Lyqyd's or my own tutorials for the Ask a Pro series to see the rough standard we are looking for in tutorials.
Yeah, I know what coroutine.yeild does, but I'm more concerned as of where it may be used other than in os.pullEvent. What program would use coroutine.yield in place of os.pullEvent anyway?

About the tutorial: Yeah I know it's pretty quick. I wrote it in 5 minutes, but I figure if someone understands coroutines, they can understand what I'm doing in the examples. I'll update it when I find the time. (might be a while, school's starting)

#6 Engineer

  • Members
  • 1,378 posts
  • LocationThe Netherlands

Posted 11 August 2014 - 09:56 PM

coroutine.yield does get called when you call os.pullEvent. os.pullEvent calls os.pullEventRaw and os.pullEventRaw only returns coroutine.yield(), so that meas the coroutine.yield is the first layer of the events. When you overwrite coroutine.yield, nobody else can manipulate you, because I can still manipulate you when i override coroutine.yield!

Do you catch my drift?

#7 skwerlman

  • Members
  • 163 posts
  • LocationPennsylvania

Posted 12 August 2014 - 01:20 PM

So basically:
Event -> coroutine.yield -> os.pullEventRaw -> os.pullEvent
Did I get that right?

#8 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 12 August 2014 - 03:13 PM

yep.

from bios.lua
function os.pullEventRaw( sFilter )
  return coroutine.yield( sFilter )
end

function os.pullEvent( sFilter )
  local eventData = { os.pullEventRaw( sFilter ) }
  if eventData[1] == "terminate" then
    error( "Terminated", 0 )
  end
  return unpack( eventData )
end


#9 Ferdi265

  • Members
  • 21 posts

Posted 28 August 2014 - 10:56 AM

I wrote an API that does this and a bit more. I could link this as a kind of partial explanation.

My API iterates over coroutines and resumes them if the current event passes a filter that is stored along with the coroutine. (E.g. You coupd have a coroutine that only resumes on 'rednet_message' and one that resumes on all events.)

It also exposes functions to add coroutines at runtime, and one for adding repeatable event listeners.

http://www.computerc...375#entry192375

Sorry for the ugly link, I'm on mobile.

#10 electrodude512

  • Members
  • 167 posts
  • LocationEastern USA

Posted 01 September 2014 - 02:44 AM

You might want to put your function in a pcall so you can restore the real coroutine.yield in case the function dies, so the whole computer doesn't crash.

#11 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 07 November 2014 - 09:33 PM

This is exactly wht I need for my new project :)

Only problem is that I do not fully understand the code !

My main problem is, taht we create a coroutine but then we do not resume it.

I thought you have to resume a coroutine right after creating in order to run the function ?

Would be very nice if someone could explain this to me !

Thank you in advance

Kouksi44

#12 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 08 November 2014 - 01:01 AM

View PostKouksi44, on 07 November 2014 - 09:33 PM, said:

-snip-
you can resume it whenever you wish to run the coroutine, in this case it is being run inside the loop. However since it is yielding before it resumes the coroutine, you should probably resume it after you create it, that way it can run up to a yield point and be ready to receive events. You should probably take a look at Bubba's Coroutine Tutorial :)

View PostKingofGamesYami, on 06 August 2014 - 04:25 AM, said:

-snip-
Second reminder, please update/improve this tutorial, it is seriously lacking in explanations, and does contain some questionable content. It isn't to the standard we're looking for, please take a look at Lyqyd's or my own tutorials for the Ask a Pro series to see the rough standard we are aiming for in tutorials.

#13 mentalr0b123

  • Members
  • 11 posts

Posted 22 February 2015 - 12:25 PM

there is a background program
--Background Rednet Listener--
rednet.open("left")
function listen()
while true do   
    id , msg = rednet.receive()
    if msg == "shutdown" then
		   os.shutdown()
    end
end
end
function toBackground()
    shell.run("/rom/programs/advanced/multishell")
end
--İts working only advanced computers...--
parallel.waitForAny(toBackground , listen)
its working on background.

#14 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 23 February 2015 - 12:43 AM

Mind you, if you're going to use multishell, you also have the option of using the instance that's already running.

Eg, just:

rednet.open("left")

while true do   
    id , msg = rednet.receive()
    if msg == "shutdown" then
                   os.shutdown()
    end
end

Then at the CraftOS command prompt, launch it via:

bg <scriptName>


#15 thecrimulo

  • Members
  • 87 posts
  • Locationhere

Posted 05 July 2016 - 05:26 PM

View PostBomb Bloke, on 23 February 2015 - 12:43 AM, said:

Mind you, if you're going to use multishell, you also have the option of using the instance that's already running.

Eg, just:

rednet.open("left")

while true do  
	id , msg = rednet.receive()
	if msg == "shutdown" then
				   os.shutdown()
	end
end

Then at the CraftOS command prompt, launch it via:

bg <scriptName>
So, if i wanted to run something in the background on an advanced comuter, i can just do shell.run("bg", "myscript")?

#16 Lyqyd

    Lua Liquidator

  • Moderators
  • 8,465 posts

Posted 05 July 2016 - 06:29 PM

Yes, that's correct.

#17 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 06 July 2016 - 12:52 AM

Though it'd be more elegant to use shell.openTab("myscript").

#18 thecrimulo

  • Members
  • 87 posts
  • Locationhere

Posted 06 July 2016 - 12:14 PM

And what about programs that paint to the screen (like an OS' desktop) or detect keyboard presses? Easy multitasking would be great

#19 HDeffo

  • Members
  • 214 posts

Posted 07 July 2016 - 09:46 AM

View Postthecrimulo, on 06 July 2016 - 12:14 PM, said:

And what about programs that paint to the screen (like an OS' desktop) or detect keyboard presses? Easy multitasking would be great

Plenty of very simple multi tasking APIs on buried on the forums. The issue is when someone really needs a multi tasking API they have usually gotten to the point they can make it themselves and don't want to use someone else's code. Because of that the multitasking threads tend to get pretty buried and hidden. I have one that runs off a single function call made to be as similar to the parallel API as possible. I believe yami has one somewhere that's actually very unique that creates a task queue of sorts (if I read and remember the program's description right). If you really need something like that and don't have the ability to code it you can definitely find it here somewhere just need to look.

#20 KingofGamesYami

  • Members
  • 3,002 posts
  • LocationUnited States of America

Posted 07 July 2016 - 12:53 PM

I believe HDeffo is referring to this API I wrote.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users