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

How does one apply a timeout to read()

Started by tom2018, 29 October 2012 - 10:34 PM
tom2018 #1
Posted 29 October 2012 - 11:34 PM
basically what the titles says how does one apply a timeout to read
Lyqyd #2
Posted 30 October 2012 - 12:34 AM
Make a copy of the read function that starts a timer at the beginning, then listens for the event to fire.
KaoS #3
Posted 30 October 2012 - 08:01 AM
or try this out, I got it to work but it is fairly complicated


a=coroutine.wrap(function() result=read() end)
local evts={}
os.startTimer(5)
while true do
if evts[1]=='timer' or result then break end
a(unpack(evts))
evts={os.pullEvent()}
end

the variable 'result' gets the read value

Edit: argh… doen't break when result has a value. does anyone know why this is?
KaoS #4
Posted 30 October 2012 - 08:22 AM
ahah. got it. it was waiting for an event. if you submit the result and then press a key it finishes. I figured a better way though. compiled into a function too


local function readFor(time,char)
result=nil
a=coroutine.wrap(function() result=read(char) os.queueEvent('timer') end)
local evts={}
os.startTimer(time)
while true do
  a(unpack(evts))
  evts={os.pullEvent()}
  if evts[1]=='timer' then break end
end
return result
end

EDIT: I made a function for running anything for a certain amount of time. go ahead and try it


local function runfor(func,timeout,tArgs)
  local result=nil
  local co=coroutine.wrap(function() os.queueEvent('done',func(unpack(tArgs or {}))) end)
  local evt={}
  local timer=os.startTimer(timeout)
  while true do
   co(unpack(evt))
   evt={os.pullEvent()}
   if evt[1]=='timer' then return 'timed out' elseif evt[1]=='done' then return evt[2] end
  end
end
Duster #5
Posted 26 March 2016 - 11:33 AM
ahah. got it. it was waiting for an event. if you submit the result and then press a key it finishes. I figured a better way though. compiled into a function too


local function readFor(time,char)
result=nil
a=coroutine.wrap(function() result=read(char) os.queueEvent('timer') end)
local evts={}
os.startTimer(time)
while true do
  a(unpack(evts))
  evts={os.pullEvent()}
  if evts[1]=='timer' then break end
end
return result
end

EDIT: I made a function for running anything for a certain amount of time. go ahead and try it


local function runfor(func,timeout,tArgs)
  local result=nil
  local co=coroutine.wrap(function() os.queueEvent('done',func(unpack(tArgs or {}))) end)
  local evt={}
  local timer=os.startTimer(timeout)
  while true do
   co(unpack(evt))
   evt={os.pullEvent()}
   if evt[1]=='timer' then return 'timed out' elseif evt[1]=='done' then return evt[2] end
  end
end
is there a way for it to end or break? as soon as someone inputted something?
Edited on 26 March 2016 - 10:33 AM
Stekeblad #6
Posted 27 March 2016 - 10:02 AM

parallel.waitForAny(result=read(), sleep(timeout))
Try this, continues then one of read or sleep finnish.
Bomb Bloke #7
Posted 27 March 2016 - 10:46 AM
is there a way for it to end or break? as soon as someone inputted something?

That seems to be what it's built to do. External timers may mess up the code you quoted, though.


parallel.waitForAny(result=read(), sleep(timeout))
Try this, continues then one of read or sleep finnish.

Methinks you should take your own advice about "trying it".

Here's what you were going for:

local result

parallel.waitForAny(
  function()
    result = read()
  end,

  function()
    sleep(30)  --# Or whatever timeout you want.
  end
)

if result then
  --# Got input before the timeout.
else
  --# Didn't.
end

If you wanted to gather whatever the user typed before the timeout, you'd indeed need a custom version of read(). But really it may be better to cancel the timeout if the user starts typing:

local result

parallel.waitForAny(
  function()
    result = read()
  end,

  function()
    local myTimer = os.startTimer(30)

    while true do
      local myEvent = {os.pullEvent()}

      if myEvent[1] == "timer" and myEvent[2] == myTimer then
        break

      elseif myEvent[1] == "char" then
        os.pullEvent("yield forever")

      end
    end
  end
)

if result then
  --# Got input before the timeout.
else
  --# Didn't.
end