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

[Question/Error] parallel API

Started by InputUsername, 10 January 2013 - 04:56 AM
InputUsername #1
Posted 10 January 2013 - 05:56 AM
Hello, a quick question/problem/error here.

I'm making a client/server based chat (I know, very original idea :)/>). In the client program, I have three functions:

one that receives messages from the server (getMessages), one that updates the screen (drawScreen) and one that gets user input (using the read() function) and sends the messages to the server (sendMessages). I then use the function parallel.waitForAny(getMessages,drawScreen,sendMessages) inside a while loop.

But when starting the program, I can't do anything, the screen keeps flickering and it exits after about 3-4 seconds with the error parallel:22 client:19: Too long without yielding

Simple question: how do I fix this?

By the way, should I post the code of the client program?

EDIT: I added the code

Spoiler

--[[
chat system client
© 2013 InputUsername
please don't copy/redistribute/use this code
it's only here because I need to get an error fixed
]]

local chat = {"Welcome to chat!","Commands: /leave"}
local sLocalName, nServer

rednet.open("top")

local function getMessages()
  ev,id,msg = os.pullEvent("rednet_message")
  if id == nServer then
	msg = textutils.unserialize(msg)
	if not (msg == nil or msg["name"] == nil or msg["msg"] == nil) then
	  table.insert(chat,msg["name"].."> "..msg["msg"])
	end
  end
end

local function drawScreen()
  term.clear()
  term.setCursorPos(1,1)
  if #chat <= 16 then
	for i = 1, #chat do
	  print(chat[i])
	end
  else
	for i = #chat-17,#chat do
	  print(chat[i])
	end
  end
  term.setCursorPos(1,18)
  print(string.rep("-",52))
end

local function sendMessages()
  term.setCursorPos(1,19)
  term.clearLine()
  term.write("> ")
  local send = read()
  rednet.send(nServer,textutils.serialize({name=sLocalName,msg=send}))
end

term.clear()
term.setCursorPos(1,1)

print("Insert desired username:\n")
print("Insert server id to join:\n")

while (not sLocalName) or (not nServer) do
  term.setCursorPos(1,2)
  term.clearLine()
  sLocalName = read()
  term.setCursorPos(1,4)
  term.clearLine()
  nServer = tonumber(read())
  rednet.send(nServer,textutils.serialize({name=sLocalName,msg="/join"}))
  id,msg = rednet.receive(5)
  if id == nServer and msg then
	msg = textutils.unserialize(msg)
	if msg["name"] == "server" and msg["msg"] == "/ok" then
	  break
	elseif msg["name"] == "server" and msg["msg"] == "/double" then
	  sLocalName,nServer = nil,nil
	end
  else
	sLocalName,nServer = nil,nil
  end
end

while true do
  parallel.waitForAny(getMessages,drawScreen,sendMessages)
end

or

http://pastebin.com/MZ0uA2ZT
Zudo #2
Posted 10 January 2013 - 06:08 AM
post the code please

or download a premade one
InputUsername #3
Posted 10 January 2013 - 06:29 AM
post the code please

or download a premade one

Okay, I'll do that. By the way, I'm making one myself because I want to find out how to do so myself, so downloading a premade one won't be happening anyway.
Orwell #4
Posted 10 January 2013 - 06:33 AM
post the code please

or download a premade one

Okay, I'll do that. By the way, I'm making one myself because I want to find out how to do so myself, so downloading a premade one won't be happening anyway.
You used <CODE> instead of
 tags. ;)/>
InputUsername #5
Posted 10 January 2013 - 06:34 AM
You used <CODE> instead of
 tags. ;)/>

I noticed just a second after editing :P/>
Lyqyd #6
Posted 10 January 2013 - 06:36 AM
drawScreen() doesn't yield. You need to make it yield. Maybe merge it with the getMessages function.

Edit: Definitely merge drawScreen and getMessages. That should fix the issue.
Exerro #7
Posted 10 January 2013 - 11:09 AM
parralel.waitForAny will stop all the functions if any of them finish so drawScreen doesnt yeild and finishes straight away…if you want user input then use a loop for the drawing or parralel.waitForAll with a timer to trigger a reset
Lyqyd #8
Posted 10 January 2013 - 11:15 AM
parralel.waitForAny will stop all the functions if any of them finish so drawScreen doesnt yeild and finishes straight away…if you want user input then use a loop for the drawing or parralel.waitForAll with a timer to trigger a reset

Please don't post just to add incorrect information. Failure-to-yield protection will kill drawScreen after approximately ten seconds (not right away), at which time the parallel coroutine manager will detect that it is a dead coroutine and return.