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

coroutine.resume(...) without pause to main code

Started by Cross_Sans, 11 May 2017 - 02:59 PM
Cross_Sans #1
Posted 11 May 2017 - 04:59 PM
Hi,
I am currently writing my own thread manager, the only problem is I want to coroutine.resume without pausing the next piece of code. Example:
coroutine.resume(thread); – This will run in background
print("Thread started successfully"); – This will print when the coroutine has started successfuly


Is there any way to do that ?

Thanks for reading,
Redall.
Edited on 11 May 2017 - 03:20 PM
SquidDev #2
Posted 11 May 2017 - 06:13 PM
There is no such thing as "running in the background" in Lua - only one coroutine can run at once, and you must explicitly resume/suspend each coroutine. Multi-tasking, such as multishell is handled by waiting for one coroutine to yield and then resuming the next one - take a look at multishell or the parallel API's implementation to see how to do that.
Edited on 11 May 2017 - 04:13 PM
Cross_Sans #3
Posted 11 May 2017 - 07:14 PM
Thanks for your help. So, there is still a way to implement it ?
Edited on 11 May 2017 - 05:15 PM
SquidDev #4
Posted 11 May 2017 - 07:18 PM
Thanks for your help. So, there is still a way to implement it ?
No. Only one thing can be run at once with Lua. Even individual computers cannot be run at the same time.
Edited on 11 May 2017 - 05:18 PM
Cross_Sans #5
Posted 11 May 2017 - 07:25 PM
No. Only one thing can be run at once with Lua. Even individual computers cannot be run at the same time.

I mean by that, I could implement by running one at a time a thread, by helping me with the parallel and coroutine* sources ?
coroutine*: Not sure if the source is available.
Lyqyd #6
Posted 11 May 2017 - 08:43 PM
It seems like what you want to do is to create a coroutine manager that allows you to add coroutines as you go. Have you checked out how other implementations have been written? Take a look at LyqydOS's process API, for instance. That plus the bottom few lines of the procman file are the whole coroutine manager for the OS.
KingofGamesYami #7
Posted 11 May 2017 - 09:34 PM
If you do want to make a coroutine manager, I made a awesome flow chart that might help.
Cross_Sans #8
Posted 12 May 2017 - 05:07 PM
Thanks for the links.
I have already checked how does the LyqydOS's process API, but I didn't understand how does actually works.
But, with the flow chart of KingofGamesYami, I figured out how does it works. I will tell if I still couldn't do it.
Edited on 12 May 2017 - 03:07 PM
Cross_Sans #9
Posted 12 May 2017 - 06:02 PM
(Sorry for the double post)

Okay, I have figured out how to fix it, but when I run it, the thread is turning to "dead" mode when coroutine.yield() is called:


Code for threading: https://pastebin.com/HZiRT8d5
Code for kernel (part of): https://pastebin.com/GKubbDRq
Edited on 12 May 2017 - 04:36 PM
SquidDev #10
Posted 12 May 2017 - 06:54 PM
I'm not entirely sure what you're expecting next to do here. This normally accepts a table and a key and returns the next key in the table. Here you're passing no arguments.

I also note that you're iterating over the table while removing items from it. This will result in you skipping items as all the indexes shift. You should iterate in reverse instead:


--# Note the arguments are flipped and the -1. This says "start at the length and continue to 1".
for Index = #Nature.Thread.List, 1, -1 do
    --# Whatever you had before.
    if CanResume == false then
        --# Removing is actually the same here too.
        table.remove(Nature.Thread.List, Index)
    end
end
Cross_Sans #11
Posted 12 May 2017 - 07:07 PM
Thanks for helping me, I managed to fix it without having to do a reversed for loop.

--# Note the arguments are flipped and the -1. This says "start at the length and continue to 1".
for Index = #Nature.Thread.List, 1, -1 do
	--# Whatever you had before.
	if CanResume == false then
		--# Removing is actually the same here too.
		table.remove(Nature.Thread.List, Index)
	end
end

I'm not entirely sure what you're expecting next to do here. This normally accepts a table and a key and returns the next key in the table. Here you're passing no arguments.
I didn't understand what are you talking about; give me an example; and sorry if i'm dumb by the way.
Edited on 12 May 2017 - 05:08 PM
SquidDev #12
Posted 12 May 2017 - 07:14 PM
I managed to fix it without having to do a reversed for loop.
Great! Make sure you don't accidentally skip elements, which was my original worry with your code.

I didn't understand what are you talking about; give me an example.
So consider something like this:

local tbl = { a = 1, b = 2, c = 3 }

local k, v = next(tbl)
print(k, v) -- prints a key and its corresponding value. On my machine this is "c" and "3"

k, v = next(tbl, k) -- Find the next value after "c".
print(k, v) -- prints "b" and "2" on my machine

k, v = next(tbl, k) -- Find the next value after "b".
print(k, v) -- prints "a" and "1" on my machine
This is exactly what pairs uses to iterate over a table. If you try:

for k, v in pairs(tbl) do
    print(k, v)
end
You'll get the same "c 3", "b 2", "a 1".
Cross_Sans #13
Posted 12 May 2017 - 07:45 PM

I changed my for loop to use ipairs function. I try to fix errors by reading the parralel API, I managed to run threads but the only problem is that the screen is black for 10 seconds, and then the output of the threads displays for 1 second, and shuts down. It says an error like "windows: 95: too long without yielding" but I use coroutine.yield() in my two functions for the threads. Here is the modified function:

function Nature.Thread.Switch()
	if ThreadMode then
		error("Nature.Thread.Switch: Cannot switch because Thread Mode is already activated");
	end

	Nature.Logger.LogLine("THRD", "Switching to ThreadMode...");
	ThreadMode = true;

	while #Nature.Thread.List > 0 do
		local Event = Nature.Thread.GetEvent() or {};

		for Index, ThreadItem in ipairs(Nature.Thread.List) do
			if Nature.Thread.List[Index] ~= nil then
				repeat
				local CanResume, Parameter = coroutine.resume(ThreadItem.Thread, unpack(Event));

				write("Thread #" .. Index .. " is running... ");
				write(tostring(coroutine.status(ThreadItem.Thread)));
				print(" - " .. tostring(Parameter));

				if CanResume == false then
					Nature.Logger.LogLine("THRD", "Error while running thread ID " .. Index .. ": " .. Parameter);
					table.remove(Nature.Thread.List, Index);
					break;
				elseif coroutine.status(Nature.Thread.List[Index].Thread) == "dead" then
					table.remove(Nature.Thread.List, Index);
					break;
				end
				until true
			end
		end
	end
end
Edited on 12 May 2017 - 05:46 PM
Cross_Sans #14
Posted 13 May 2017 - 11:26 AM
(Sorry for the double post)

I managed to fix problems, and the thread manager is working now :D/> !
Many thanks for SquidDev, Lyqyd, and KingofGamesYami for helping me.

Moderators, you can close this topic.