سؤال

Summary: Can I cause time to (appear to) pass in my script without busywaiting? Using os.execute('sleep 1') doesn't cut it (and also wastes time).

Details
I have a library that does work after specific intervals. I currently schedule this by injecting a table into a time-sorted list. Roughly:

local delayedWork = {}
function handleLater( data, delaySeconds )
  local delayedItem = { data=data, execTime=os.clock() + delaySeconds }
  local i=1
  for _,existing in ipairs(delayedWork) do
    if existing.execTime > delayedItem.execTime then break else i=i+1 end
  end
  table.insert(delayedWork,i,delayedItem)
end

Later on I periodically check for work to do. Roughly:

function processDelayedWork()
  local i,last = 1,#delayedWork
  while i<=last do
    local delayedItem = delayedWork[i]
    if delayedItem.execTime <= os.clock() then
      table.remove(delayedWork,i)
      -- use delayedItem.data
      last = last-1
    else
      i=i+1
    end
  end
end

(The fact that this uses CPU time instead of wall time is an issue for a different question. The fact that I repeatedly shift the array during processing instead of one compacting pass is an optimization not relevant here.)

When I am running unit tests of the system I need to cause time to pass, preferably faster than normal. However, calling os.execute('sleep 1') consumes one wall clock second, but does not cause os.clock() to increment.

$ lua -e "require 'os' print(os.clock()) os.execute('sleep 1') print(os.clock())"
0.002493
0.002799

I can't use os.time() because this is only integer seconds (and less than that on systems compiled to use float instead double for numbers):

$ lua -e "require 'os' print(os.time()) os.execute('sleep 0.4') print(os.time())"
1397704209
1397704209

Can I force time to pass in my script without just busywaiting?

هل كانت مفيدة؟

المحلول 2

Why not write your own clock function that does what you want?

do
   local clock = os.clock
   local increment = 0
   os.clock = function(inc)
     increment = increment + (inc or 0)
     return clock()+increment
   end
end
print(os.clock())
os.clock(1)
print(os.clock())

This will print 0.001 1.001 or something similar.

نصائح أخرى

Paul answered this already: make os.clock return whatever you need.

I'm adding an implementation that lets you control how fast time passes according to os.clock \\\\\\\\\\\\\\\\\\\\\\\.

do
    local realclock = os.clock
    local lasttime = realclock()
    local faketime = lasttime
    local clockMultiplier = 1
    function setClockMultiplier(multiplier)
        clockMultiplier = multiplier
    end
    function adjustTime(offsetAmount)
        faketime = faketime + offsetAmount
    end
    function os.clock()
        local now = realclock()
        adjustTime((now - lasttime) * clockMultiplier)
        lasttime = now
        return faketime
    end
end

You can now call setClockMultiplier to freely slow down or speed up the passage of time as reported by os.clock. You can call adjustTime to advance or retard the clock by arbitrary amounts.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top