reworking jobs
This commit is contained in:
parent
3f147443bc
commit
f737516009
20
changes.md
20
changes.md
@ -4,6 +4,26 @@ Table of contents
|
||||
---
|
||||
[Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)</br>[Update 14.0.0 - Consistency, Additions and Stability](#update-1400-consistency-additions-and-stability)</br>[Update 13.1.0 - Bug fixes and features added](#update-1310-bug-fixes-and-features-added)</br>[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300-added-some-documentation-and-some-new-features-too-check-it-out)</br>[Update 12.2.2 - Time for some more bug fixes!](#update-1222-time-for-some-more-bug-fixes)</br>[Update 12.2.1 - Time for some bug fixes!](#update-1221-time-for-some-bug-fixes)</br>[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)</br>[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)</br>[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200-big-update-lots-of-additions-some-changes)</br>[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)</br>[Update: 1.11.0](#update-1110)</br>[Update: 1.10.0](#update-1100)</br>[Update: 1.9.2](#update-192)</br>[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)</br>[Update: 1.9.0](#update-190)</br>[Update: 1.8.7](#update-187)</br>[Update: 1.8.6](#update-186)</br>[Update: 1.8.5](#update-185)</br>[Update: 1.8.4](#update-184)</br>[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)</br>[Update: 1.8.2](#update-182)</br>[Update: 1.8.1](#update-181)</br>[Update: 1.7.6](#update-176)</br>[Update: 1.7.5](#update-175)</br>[Update: 1.7.4](#update-174)</br>[Update: 1.7.3](#update-173)</br>[Update: 1.7.2](#update-172)</br>[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)</br>[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)</br>[Update: 1.6.0](#update-160)</br>[Update: 1.5.0](#update-150)</br>[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)</br>[Update: 1.4.0 (3/20/2017)](#update-140-3202017)</br>[Update: 1.3.0 (1/29/2017)](#update-130-1292017)</br>[Update: 1.2.0 (12.31.2016)](#update-120-12312016)</br>[Update: 1.1.0](#update-110)</br>[Update: 1.0.0](#update-100)</br>[Update: 0.6.3](#update-063)</br>[Update: 0.6.2](#update-062)</br>[Update: 0.6.1-6](#update-061-6)</br>[Update: 0.5.1-6](#update-051-6)</br>[Update: 0.4.1](#update-041)</br>[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)</br>[Update: EventManager 2.0.0](#update-eventmanager-200)</br>[Update: EventManager 1.2.0](#update-eventmanager-120)</br>[Update: EventManager 1.1.0](#update-eventmanager-110)</br>[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</br>[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different)
|
||||
|
||||
# Update 14.2.0 - State Saving reworked!
|
||||
Full Update Showcase
|
||||
---
|
||||
```lua
|
||||
package.path="?.lua;?/init.lua;?.lua;"..package.path
|
||||
local multi, thread = require("multi"):init()
|
||||
GLOBAL,THREAD = require("multi.integration.lanesManager"):init()
|
||||
```
|
||||
Going Forward:
|
||||
---
|
||||
-
|
||||
Added:
|
||||
---
|
||||
-
|
||||
Changed:
|
||||
---
|
||||
-
|
||||
Removed:
|
||||
---
|
||||
- multi:newTrigger() — Connections do everything this thing could do and more. I plan on removing bloat features from the library anyway
|
||||
# Update 14.1.0 - A whole new world of possibilities
|
||||
Full Update Showcase
|
||||
---
|
||||
|
||||
322
multi/init.lua
322
multi/init.lua
@ -21,7 +21,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]
|
||||
local bin = pcall(require,"bin")
|
||||
local multi = {}
|
||||
local clock = os.clock
|
||||
local thread = {}
|
||||
@ -42,9 +41,7 @@ multi.fps = 60
|
||||
multi.Type = "mainprocess"
|
||||
multi.Rest = 0
|
||||
multi._type = type
|
||||
multi.Jobs = {}
|
||||
multi.queue = {}
|
||||
multi.jobUS = 2
|
||||
multi.clock = os.clock
|
||||
multi.time = os.time
|
||||
multi.LinkedPath = multi
|
||||
@ -198,6 +195,8 @@ function multi:setPriority(s)
|
||||
elseif type(s)=='string' then
|
||||
if s:lower()=='core' or s:lower()=='c' then
|
||||
self.Priority=self.Priority_Core
|
||||
elseif s:lower()=="very high" or s:lower()=="vh" then
|
||||
self.Priority=self.Priority_Very_High
|
||||
elseif s:lower()=='high' or s:lower()=='h' then
|
||||
self.Priority=self.Priority_High
|
||||
elseif s:lower()=='above' or s:lower()=='a' then
|
||||
@ -208,6 +207,8 @@ function multi:setPriority(s)
|
||||
self.Priority=self.Priority_Below_Normal
|
||||
elseif s:lower()=='low' or s:lower()=='l' then
|
||||
self.Priority=self.Priority_Low
|
||||
elseif s:lower()=="very low" or s:lower()=="vl" then
|
||||
self.Priority=self.Priority_Very_Low
|
||||
elseif s:lower()=='idle' or s:lower()=='i' then
|
||||
self.Priority=self.Priority_Idle
|
||||
end
|
||||
@ -458,26 +459,6 @@ function multi:reallocate(o,n)
|
||||
self.Active=true
|
||||
end
|
||||
multi.Reallocate=multi.Reallocate
|
||||
function multi:setJobSpeed(n)
|
||||
self.jobUS=n
|
||||
return self
|
||||
end
|
||||
function multi:hasJobs()
|
||||
return #self.Jobs>0,#self.Jobs
|
||||
end
|
||||
function multi:getJobs()
|
||||
return #self.Jobs
|
||||
end
|
||||
function multi:removeJob(name)
|
||||
local count = 0
|
||||
for i=#self.Jobs,1,-1 do
|
||||
if self.Jobs[i][2]==name then
|
||||
table.remove(self.Jobs,i)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
function multi:FreeMainEvent()
|
||||
self.func={}
|
||||
end
|
||||
@ -656,116 +637,6 @@ function multi:newBase(ins)
|
||||
_tid = _tid + 1
|
||||
return c
|
||||
end
|
||||
function multi:newProcessor(file)
|
||||
if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end
|
||||
local c = {}
|
||||
setmetatable(c, self)
|
||||
c.Parent=self
|
||||
c.Active=true
|
||||
c.func={}
|
||||
c.Type='process'
|
||||
c.Mainloop={}
|
||||
c.Garbage={}
|
||||
c.Children={}
|
||||
c.Active=false
|
||||
c.Rest=0
|
||||
c.Jobs={}
|
||||
c.queue={}
|
||||
c.jobUS=2
|
||||
c.l=self:newLoop(function(self,dt)
|
||||
if self.link.Active then
|
||||
c:uManager()
|
||||
end
|
||||
end)
|
||||
c.l.link = c
|
||||
c.l.Type = "processor"
|
||||
function c:getController()
|
||||
return c.l
|
||||
end
|
||||
function c:Start()
|
||||
self.Active = true
|
||||
return self
|
||||
end
|
||||
function c:Resume()
|
||||
self.Active = false
|
||||
return self
|
||||
end
|
||||
function c:setName(name)
|
||||
c.l.Name = name
|
||||
return self
|
||||
end
|
||||
function c:Pause()
|
||||
if self.l then
|
||||
self.l:Pause()
|
||||
end
|
||||
return self
|
||||
end
|
||||
function c:Remove()
|
||||
if self.Type == "process" then
|
||||
self:__Destroy()
|
||||
self.l:Destroy()
|
||||
else
|
||||
self:__Destroy()
|
||||
end
|
||||
end
|
||||
function c:Destroy()
|
||||
if self == c then
|
||||
self.l:Destroy()
|
||||
else
|
||||
for i = #c.Mainloop,1,-1 do
|
||||
if c.Mainloop[i] == self then
|
||||
table.remove(c.Mainloop,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if file then
|
||||
self.Cself=c
|
||||
loadstring('local process=multi.Cself '..io.open(file,'rb'):read('*all'))()
|
||||
end
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newTimer()
|
||||
local c={}
|
||||
c.Type='timer'
|
||||
local time=0
|
||||
local count=0
|
||||
local paused=false
|
||||
function c:Start()
|
||||
time=os.clock()
|
||||
return self
|
||||
end
|
||||
function c:Get()
|
||||
if self:isPaused() then return time end
|
||||
return (clock()-time)+count
|
||||
end
|
||||
function c:isPaused()
|
||||
return paused
|
||||
end
|
||||
c.Reset=c.Start
|
||||
function c:Pause()
|
||||
time=self:Get()
|
||||
paused=true
|
||||
return self
|
||||
end
|
||||
function c:Resume()
|
||||
paused=false
|
||||
time=os.clock()-time
|
||||
return self
|
||||
end
|
||||
function c:tofile(path)
|
||||
local m=bin.new()
|
||||
count=count+self:Get()
|
||||
m:addBlock(self.Type)
|
||||
m:addBlock(count)
|
||||
m:tofile(path)
|
||||
return self
|
||||
end
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newConnector()
|
||||
local c = {Type = "connector"}
|
||||
return c
|
||||
@ -773,6 +644,7 @@ end
|
||||
local CRef = {
|
||||
Fire = function() end
|
||||
}
|
||||
local ignoreconn = true
|
||||
function multi:newConnection(protect,func,kill)
|
||||
local c={}
|
||||
c.callback = func
|
||||
@ -939,39 +811,121 @@ function multi:newConnection(protect,func,kill)
|
||||
m:tofile(path)
|
||||
return self
|
||||
end
|
||||
if not(ignoreconn) then
|
||||
multi:create(c)
|
||||
end
|
||||
return c
|
||||
end
|
||||
multi.OnObjectCreated=multi:newConnection()
|
||||
multi.OnObjectDestroyed=multi:newConnection()
|
||||
function multi:newJob(func,name)
|
||||
if not(self.Type=='mainprocess' or self.Type=='process') then error('Can only create an object on multi or an interface obj') return false end
|
||||
ignoreconn = false
|
||||
function multi:newProcessor(file)
|
||||
if not(self.Type=='mainprocess') then error('Can only create an interface on the multi obj') return false end
|
||||
local c = {}
|
||||
if self.Type=='process' then
|
||||
setmetatable(c, self.Parent)
|
||||
else
|
||||
setmetatable(c, self)
|
||||
end
|
||||
c.Parent=self
|
||||
c.Active=true
|
||||
c.func={}
|
||||
c.Parent=self
|
||||
c.Type='job'
|
||||
c.trigfunc=func or function() end
|
||||
function c:Act()
|
||||
self:trigfunc(self)
|
||||
c.Type='process'
|
||||
c.Mainloop={}
|
||||
c.Garbage={}
|
||||
c.Children={}
|
||||
c.Active=false
|
||||
c.Rest=0
|
||||
c.queue={}
|
||||
c.l=self:newLoop(function(self,dt)
|
||||
if self.link.Active then
|
||||
c:uManager()
|
||||
end
|
||||
table.insert(self.Jobs,{c,name})
|
||||
if self.JobRunner==nil then
|
||||
self.JobRunner=self:newAlarm(self.jobUS):setName("multi.jobHandler")
|
||||
self.JobRunner:OnRing(function(self)
|
||||
if #self.Parent.Jobs>0 then
|
||||
if self.Parent.Jobs[1] then
|
||||
self.Parent.Jobs[1][1]:Act()
|
||||
table.remove(self.Parent.Jobs,1)
|
||||
end
|
||||
end
|
||||
self:Reset(self.Parent.jobUS)
|
||||
end)
|
||||
c.l.link = c
|
||||
c.l.Type = "processor"
|
||||
function c:getController()
|
||||
return c.l
|
||||
end
|
||||
function c:Start()
|
||||
self.Active = true
|
||||
return self
|
||||
end
|
||||
function c:Resume()
|
||||
self.Active = false
|
||||
return self
|
||||
end
|
||||
function c:setName(name)
|
||||
c.l.Name = name
|
||||
return self
|
||||
end
|
||||
function c:Pause()
|
||||
if self.l then
|
||||
self.l:Pause()
|
||||
end
|
||||
return self
|
||||
end
|
||||
function c:Remove()
|
||||
if self.Type == "process" then
|
||||
self:__Destroy()
|
||||
self.l:Destroy()
|
||||
else
|
||||
self:__Destroy()
|
||||
end
|
||||
end
|
||||
function c:Destroy()
|
||||
if self == c then
|
||||
self.l:Destroy()
|
||||
else
|
||||
for i = #c.Mainloop,1,-1 do
|
||||
if c.Mainloop[i] == self then
|
||||
table.remove(c.Mainloop,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if file then
|
||||
self.Cself=c
|
||||
loadstring('local process=multi.Cself '..io.open(file,'rb'):read('*all'))()
|
||||
end
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newTimer()
|
||||
local c={}
|
||||
c.Type='timer'
|
||||
local time=0
|
||||
local count=0
|
||||
local paused=false
|
||||
function c:Start()
|
||||
time=os.clock()
|
||||
return self
|
||||
end
|
||||
function c:Get()
|
||||
if self:isPaused() then return time end
|
||||
return (clock()-time)+count
|
||||
end
|
||||
function c:isPaused()
|
||||
return paused
|
||||
end
|
||||
c.Reset=c.Start
|
||||
function c:Pause()
|
||||
time=self:Get()
|
||||
paused=true
|
||||
return self
|
||||
end
|
||||
function c:Resume()
|
||||
paused=false
|
||||
time=os.clock()-time
|
||||
return self
|
||||
end
|
||||
function c:tofile(path)
|
||||
local m=bin.new()
|
||||
count=count+self:Get()
|
||||
m:addBlock(self.Type)
|
||||
m:addBlock(count)
|
||||
m:tofile(path)
|
||||
return self
|
||||
end
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi.nextStep(func)
|
||||
ncount = ncount+1
|
||||
@ -1093,6 +1047,7 @@ end
|
||||
function multi:newFunction(func)
|
||||
local c={}
|
||||
c.func=func
|
||||
c.Type = "mfunc"
|
||||
mt={
|
||||
__index=multi,
|
||||
__call=function(self,...)
|
||||
@ -1225,17 +1180,6 @@ end
|
||||
function multi:setTimeout(func,t)
|
||||
multi:newThread(function() thread.sleep(t) func() end)
|
||||
end
|
||||
function multi:newTrigger(func)
|
||||
local c={}
|
||||
c.Type='trigger'
|
||||
c.trigfunc=func or function() end
|
||||
function c:Fire(...)
|
||||
self:trigfunc(...)
|
||||
return self
|
||||
end
|
||||
self:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newTStep(start,reset,count,set)
|
||||
local c=self:newBase()
|
||||
think=1
|
||||
@ -1643,6 +1587,7 @@ function multi:newThread(name,func,...)
|
||||
end
|
||||
c.creationTime = os.clock()
|
||||
threadid = threadid + 1
|
||||
multi.create(multi,c)
|
||||
return c
|
||||
end
|
||||
function multi.initThreads(justThreads)
|
||||
@ -1819,7 +1764,7 @@ function multi:newService(func) -- Priority managed threads
|
||||
local time
|
||||
local p = multi.Priority_Normal
|
||||
local ap
|
||||
local task
|
||||
local task = thread.sleep
|
||||
local scheme = 1
|
||||
function c.Start()
|
||||
time = multi:newTimer()
|
||||
@ -1881,8 +1826,45 @@ function multi:newService(func) -- Priority managed threads
|
||||
p = pri
|
||||
c.SetScheme(scheme)
|
||||
end
|
||||
multi.create(multi,c)
|
||||
return c
|
||||
end
|
||||
multi.Jobs = multi:newService(function(self,jobs)
|
||||
local job = table.remove(jobs,1)
|
||||
if job and job.removed==nil then
|
||||
job.func()
|
||||
end
|
||||
end)
|
||||
multi.Jobs.OnStarted(function(self,jobs)
|
||||
function self:newJob(func,name)
|
||||
table.insert(jobs,{
|
||||
func = func,
|
||||
name = name,
|
||||
removeJob = function(self) self.removed = true end
|
||||
})
|
||||
end
|
||||
function self:getJobs(name)
|
||||
local tab = {}
|
||||
if not name then return jobs end
|
||||
for i=1,#jobs do
|
||||
if name == jobs[i].name then
|
||||
table.insert(tab,jobs[i])
|
||||
end
|
||||
end
|
||||
return tab
|
||||
end
|
||||
function self:removeJobs(name)
|
||||
for i=1,#jobs do
|
||||
if name ~= nil and name == jobs[i].name then
|
||||
jobs[i]:removeJob()
|
||||
elseif name == nil then
|
||||
jobs[i]:removeJob()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
multi.Jobs.SetPriority(multi.Priority_Normal)
|
||||
multi.Jobs.Start()
|
||||
function multi:newThreadedProcess(name)
|
||||
local c = {}
|
||||
local holding = false
|
||||
@ -1911,9 +1893,7 @@ function multi:newThreadedProcess(name)
|
||||
c.Rest=0
|
||||
c.updaterate=.01
|
||||
c.restRate=.1
|
||||
c.Jobs={}
|
||||
c.queue={}
|
||||
c.jobUS=2
|
||||
c.rest=false
|
||||
function c:getController()
|
||||
return nil
|
||||
@ -1962,6 +1942,7 @@ function multi:newThreadedProcess(name)
|
||||
c:uManager()
|
||||
end
|
||||
end)
|
||||
multi:create(c)
|
||||
return c
|
||||
end
|
||||
function multi:newHyperThreadedProcess(name)
|
||||
@ -2008,9 +1989,7 @@ function multi:newHyperThreadedProcess(name)
|
||||
c.Rest=0
|
||||
c.updaterate=.01
|
||||
c.restRate=.1
|
||||
c.Jobs={}
|
||||
c.queue={}
|
||||
c.jobUS=2
|
||||
c.rest=false
|
||||
function c:getController()
|
||||
return nil
|
||||
@ -2052,6 +2031,7 @@ function multi:newHyperThreadedProcess(name)
|
||||
return self
|
||||
end
|
||||
c.Hold=c.Sleep
|
||||
multi:create(c)
|
||||
return c
|
||||
end
|
||||
-- Multi runners
|
||||
|
||||
@ -21,37 +21,45 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]
|
||||
local bin = pcall(require,"bin")
|
||||
if not bin then return error("The bin library is required to use sterilization!") end
|
||||
local multi,thread = require("multi"):init()
|
||||
local sterilizer = {}
|
||||
---------------------
|
||||
-- State Saving Stuff
|
||||
---------------------
|
||||
function multi:IngoreObject()
|
||||
multi.OnObjectCreated(function(obj)
|
||||
print(obj.Type)
|
||||
end)
|
||||
|
||||
function IngoreObject()
|
||||
-- Tells system to not sterilize this object
|
||||
end
|
||||
function multi:ToString()
|
||||
function sterilizer:ToString()
|
||||
-- Turns the object into a string
|
||||
end
|
||||
function multi:newFromString(str)
|
||||
function sterilizer:newFromString(str)
|
||||
-- Creates an object from string
|
||||
end
|
||||
function multi:ToFile(path)
|
||||
function sterilizer:ToFile(path)
|
||||
-- Turns multi object into a string
|
||||
end
|
||||
function multi:fromFile(path)
|
||||
function sterilizer:fromFile(path)
|
||||
-- Loads multi object form file
|
||||
end
|
||||
function multi:SetStateFlag(opt)
|
||||
function sterilizer:SetStateFlag(opt)
|
||||
-- manage the states
|
||||
end
|
||||
function multi:quickStateSave(b)
|
||||
function sterilizer:quickStateSave(b)
|
||||
-- enables quick state saving
|
||||
end
|
||||
function multi:saveState(path,opt)
|
||||
function sterilizer:saveState(path,opt)
|
||||
-- Saves entire state to file
|
||||
end
|
||||
function multi:loadState(path)
|
||||
function sterilizer:loadState(path)
|
||||
-- Loads entire state from file
|
||||
end
|
||||
function multi:setDefualtStateFlag(opt)
|
||||
function sterilizer:setDefualtStateFlag(opt)
|
||||
-- sets the default flags for managing states
|
||||
end
|
||||
return sterilizer
|
||||
105
test.lua
105
test.lua
@ -1,100 +1,15 @@
|
||||
package.path="?.lua;?/init.lua;?.lua;"..package.path
|
||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
||||
local multi,thread = require("multi"):init()
|
||||
GLOBAL,THREAD = require("multi.integration.lanesManager"):init()
|
||||
serv = multi:newService(function(self,data)
|
||||
print("Service Uptime: ",self:GetUpTime(),data.test)
|
||||
--local sterilizer = require("multi.integration.sterilization")
|
||||
multi.Jobs:newJob(function()
|
||||
print("job called")
|
||||
end)
|
||||
serv.OnError(function(...)
|
||||
print(...)
|
||||
multi.Jobs:newJob(function()
|
||||
print("job called2")
|
||||
end)
|
||||
serv.OnStarted(function(self,data)
|
||||
print("Started!",self.Type,data)
|
||||
data.test = "Testing..."
|
||||
-- self as reference to the object and data is a reference to the datatable that the service has access to
|
||||
multi.Jobs:newJob(function()
|
||||
print("job called3")
|
||||
end)
|
||||
serv:Start()
|
||||
serv:SetPriority(multi.Priority_Idle)
|
||||
t = THREAD:newFunction(function(...)
|
||||
print("This is a system threaded function!",...)
|
||||
THREAD.sleep(1) -- This is handled within a system thread! Note: this creates a system thread that runs then ends.
|
||||
return "We done!"
|
||||
end)
|
||||
print(t("hehe",1,2,3,true).connect(function(...)
|
||||
print("connected:",...)
|
||||
end)) -- The same features that work with thread:newFunction() are here as well
|
||||
multi.OnLoad(function()
|
||||
print("Code Loaded!") -- Connect to the load event
|
||||
end)
|
||||
t = os.clock()
|
||||
co = 0
|
||||
multi.OnExit(function(n)
|
||||
print("Code Exited: ".. os.clock()-t .." Count: ".. co) -- Lets print when things have ended
|
||||
end)
|
||||
test = thread:newFunction(function()
|
||||
thread.sleep(1) -- Internally this throws a yield call which sends to the scheduler to sleep 1 second for this thread!
|
||||
return 1,math.random(2,100)
|
||||
end)
|
||||
multi:newThread(function()
|
||||
while true do
|
||||
thread.skip() -- Even though we have a few metamethods "yielding" I used this as an example of things still happening and counting. It connects to the Code Exited event later on.
|
||||
co = co + 1
|
||||
end
|
||||
end)
|
||||
-- We can get around the yielding across metamethods by using a threadedFunction
|
||||
-- For Example
|
||||
example = {}
|
||||
setmetatable(example,{
|
||||
__newindex = function(t,k,v) -- Using a threaded function inside of a normal function
|
||||
print("Inside metamethod",t,k,v)
|
||||
local a,b = test().wait() -- This function holds the code and "yields" see comment inside the test function!
|
||||
-- we should see a 1 seconde delay since the function sleeps for a second than returns
|
||||
print("We did it!",a,b)
|
||||
rawset(t,k,v)
|
||||
-- This means by using a threaded function we can get around the yielding across metamethods.
|
||||
-- This is useful if you aren't using luajit, or if you using lua in an enviroment that is on version 5.1
|
||||
-- There is a gotcha however, if using code that was meant to work with another coroutine based scheduler this may not work
|
||||
end,
|
||||
__index = thread:newFunction(function(t,k,v) -- Using a threaded function as the metamethod
|
||||
-- This works by returning a table with a __call metamethod. Will this work? Will lua detect this as a function or a table?
|
||||
thread.sleep(1)
|
||||
return "You got a string"
|
||||
end,true) -- Tell the code to force a wait. We need to do this for metamethods
|
||||
})
|
||||
example["test"] = "We set a variable!"
|
||||
print(example["test"])
|
||||
print(example.hi)
|
||||
-- When not in a threaded enviroment at root level we need to tell the code that we are waiting! Alternitavely after the function argument we can pass true to force a wait
|
||||
c,d = test().wait()
|
||||
print(c,d)
|
||||
a,b = 6,7
|
||||
multi:newThread(function()
|
||||
a,b = test().wait() -- Will modify Global
|
||||
print("Waited:",a,b)
|
||||
|
||||
--This returns instantly even though the function isn't done!
|
||||
print("called")
|
||||
test().connect(function(a,b)
|
||||
print("Connected:",a,b)
|
||||
os.exit()
|
||||
end)
|
||||
print("Returned")
|
||||
-- This waits for the returns since we are demanding them
|
||||
end)
|
||||
local test = multi:newSystemThreadedJobQueue(4) -- Load up a queue that has 4 running threads
|
||||
func = test:newFunction("test",function(a) -- register a function on the queue that has an async function feature
|
||||
test2() -- Call the other registered function on the queue
|
||||
return a..a
|
||||
end,true)
|
||||
func2 = test:newFunction("test2",function(a)
|
||||
print("ooo")
|
||||
console = THREAD:getConsole()
|
||||
console.print("Hello!",true)
|
||||
end,true) -- When called internally on the job queue the function is a normal sync function and not an async function.
|
||||
multi:scheduleJob({min = 15, hour = 14},function()
|
||||
-- This function will be called once everyday at 2:15
|
||||
-- Using a combination of the values above you are able to schedule a time
|
||||
end)
|
||||
print(func("1"))
|
||||
print(func("Hello"))
|
||||
print(func("sigh"))
|
||||
multi.Jobs.SetScheme(1)
|
||||
multi.Jobs.SetPriority(multi.Priority_Core)
|
||||
multi:lightloop()
|
||||
570
time/init.lua
570
time/init.lua
@ -1,570 +0,0 @@
|
||||
--------------------------------------------------------------------------------
|
||||
-- A library for the manipulation of dates and periods according to the
|
||||
-- Gregorian calendar.
|
||||
--
|
||||
-- Credit: the Gregorian calendar routines contained in this library are
|
||||
-- ported from Claus Tøndering calendar algorithms:
|
||||
-- http://www.tondering.dk/main/index.php/calendar-information .
|
||||
--
|
||||
-- Copyright (C) 2011-2016 Stefano Peluchetti. All rights reserved.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local ffi = require "ffi"
|
||||
|
||||
local C = ffi.C
|
||||
local format = string.format
|
||||
local floor, min = math.floor, math.min
|
||||
local type, new, istype, tonumber = type, ffi.new, ffi.istype, tonumber
|
||||
|
||||
local int64_ct = ffi.typeof("int64_t")
|
||||
|
||||
local function T_int(x)
|
||||
if not (type(x) == "number" and x == floor(x)) then
|
||||
error("integer number expected")
|
||||
end
|
||||
end
|
||||
|
||||
local function T_same(x, y)
|
||||
if not istype(x, y) then
|
||||
error("same type expected")
|
||||
end
|
||||
end
|
||||
|
||||
-- Period ----------------------------------------------------------------------
|
||||
-- Return string representation for a positive period.
|
||||
local function posptostr(h, m, s, ms)
|
||||
return format("%02i:%02i:%02i.%06i", h, m, s, ms)
|
||||
end
|
||||
|
||||
local p_ct
|
||||
|
||||
local function T_period(x)
|
||||
if not istype(p_ct, x) then
|
||||
error("period expected")
|
||||
end
|
||||
end
|
||||
|
||||
local function p_64(ticks)
|
||||
return new(p_ct, ticks)
|
||||
end
|
||||
|
||||
local function pfirst(x, y)
|
||||
if istype(p_ct, y) then
|
||||
return y, x
|
||||
else
|
||||
return x, y
|
||||
end
|
||||
end
|
||||
|
||||
local p_mt = {
|
||||
__new = function(ct, h, m, s, ms)
|
||||
h = h or 0; m = m or 0; s = s or 0; ms = ms or 0;
|
||||
T_int(h); T_int(m); T_int(s); T_int(ms);
|
||||
return new(ct, h*(1e6*60*60LL)+m*(1e6*60LL)+s*(1e6*1LL)+ms)
|
||||
end,
|
||||
copy = function(self)
|
||||
return new(p_ct, self)
|
||||
end,
|
||||
__eq = function(self, rhs) T_same(self, rhs)
|
||||
return self._ticks == rhs._ticks
|
||||
end,
|
||||
__lt = function(self, rhs) T_same(self, rhs)
|
||||
return self._ticks < rhs._ticks
|
||||
end,
|
||||
__le = function(self, rhs) T_same(self, rhs)
|
||||
return self._ticks <= rhs._ticks
|
||||
end,
|
||||
__add = function(self, rhs) T_same(self, rhs) -- Commutative.
|
||||
return p_64(self._ticks + rhs._ticks)
|
||||
end,
|
||||
__sub = function(self, rhs) T_same(self, rhs)
|
||||
return p_64(self._ticks - rhs._ticks)
|
||||
end,
|
||||
__unm = function(self)
|
||||
return p_64(-self._ticks)
|
||||
end,
|
||||
__mul = function(self, rhs) -- Commutative.
|
||||
local p, n = pfirst(self, rhs)
|
||||
T_int(n)
|
||||
return p_64(p._ticks*n)
|
||||
end,
|
||||
-- Approximate ratio, non-reversible in both cases.
|
||||
__div = function(self, rhs)
|
||||
T_period(self) -- Disallow (not-a-period)/period.
|
||||
if type(rhs) == "number" then
|
||||
return p_64(self._ticks/rhs)
|
||||
elseif istype(p_ct, rhs) then
|
||||
return tonumber(self._ticks)/tonumber(rhs._ticks)
|
||||
else
|
||||
error("unexpected type")
|
||||
end
|
||||
end,
|
||||
__tostring = function(self)
|
||||
local h, m, s, ms = self:parts()
|
||||
if self._ticks >= 0 then
|
||||
return posptostr(h, m, s, ms)
|
||||
else
|
||||
return "-"..posptostr(-h, -m, -s, -ms)
|
||||
end
|
||||
end,
|
||||
ticks = function(self) -- Expose int64_t.
|
||||
return self._ticks
|
||||
end,
|
||||
microseconds = function(self)
|
||||
return tonumber(self._ticks%1e6)
|
||||
end,
|
||||
seconds = function(self)
|
||||
return tonumber((self._ticks/1e6)%60)
|
||||
end,
|
||||
minutes = function(self)
|
||||
return tonumber((self._ticks/(1e6*60))%60)
|
||||
end,
|
||||
hours = function(self)
|
||||
return tonumber(self._ticks/(1e6*60*60))
|
||||
end,
|
||||
parts = function(self)
|
||||
return self:hours(), self:minutes(), self:seconds(), self:microseconds()
|
||||
end,
|
||||
tomicroseconds = function(self)
|
||||
return tonumber(self._ticks)
|
||||
end,
|
||||
tomilliseconds = function(self)
|
||||
return tonumber(self._ticks)/1e3
|
||||
end,
|
||||
toseconds = function(self)
|
||||
return tonumber(self._ticks)/1e6
|
||||
end,
|
||||
tominutes = function(self)
|
||||
return tonumber(self._ticks)/(1e6*60)
|
||||
end,
|
||||
tohours = function(self)
|
||||
return tonumber(self._ticks)/(1e6*60*60)
|
||||
end,
|
||||
}
|
||||
p_mt.__index = p_mt
|
||||
|
||||
p_ct = ffi.metatype("struct { int64_t _ticks; }", p_mt)
|
||||
|
||||
local function weeks(x) T_int(x) return p_64(x*(1e6*60*60*24*7LL)) end
|
||||
local function days(x) T_int(x) return p_64(x*(1e6*60*60*24LL)) end
|
||||
local function hours(x) T_int(x) return p_64(x*(1e6*60*60LL)) end
|
||||
local function minutes(x) T_int(x) return p_64(x*(1e6*60LL)) end
|
||||
local function seconds(x) T_int(x) return p_64(x*(1e6*1LL)) end
|
||||
local function milliseconds(x) T_int(x) return p_64(x*(1e3*1LL)) end
|
||||
local function microseconds(x) T_int(x) return p_64(x*1LL) end
|
||||
|
||||
local function toperiod(x)
|
||||
if type(x) == "string" then
|
||||
local f1, l1, h, m, s, ms = x:find("(%d+):(%d+):(%d+).(%d+)")
|
||||
if h == nil or ms == nil or l1 ~= #x then
|
||||
error("'"..x.."' is not a string representation of a period")
|
||||
end
|
||||
local ton = tonumber
|
||||
return p_ct(ton(h), ton(m), ton(s), ton(ms))
|
||||
elseif istype(int64_ct, x) then
|
||||
return p_64(x)
|
||||
else
|
||||
error("unexpected type")
|
||||
end
|
||||
end
|
||||
|
||||
-- Months ----------------------------------------------------------------------
|
||||
local months_mt = {
|
||||
__new = function(ct, x) T_int(x)
|
||||
return new(ct, x)
|
||||
end,
|
||||
}
|
||||
|
||||
local months_ct = ffi.metatype("struct { int32_t _m; }", months_mt)
|
||||
|
||||
-- Years -----------------------------------------------------------------------
|
||||
local years_mt = {
|
||||
__new = function(ct, x) T_int(x)
|
||||
return new(ct, x)
|
||||
end,
|
||||
}
|
||||
|
||||
local years_ct = ffi.metatype("struct { int32_t _y; }", years_mt)
|
||||
|
||||
-- Date ------------------------------------------------------------------------
|
||||
-- It's date(1582, 1, 1):
|
||||
local d_ticks_min = 198622713600000000LL
|
||||
-- It's date(9999,12,31) + period(23, 59, 59, 999999):
|
||||
local d_ticks_max = 464269103999999999LL
|
||||
|
||||
local d_ct
|
||||
|
||||
local function T_date(x)
|
||||
if not istype(d_ct, x) then
|
||||
error("date expected")
|
||||
end
|
||||
end
|
||||
|
||||
local function T_date_range(ticks)
|
||||
if not (d_ticks_min <= ticks and ticks <= d_ticks_max) then
|
||||
error("resulting date is outside the allowed range")
|
||||
end
|
||||
end
|
||||
|
||||
local function d_64(ticks) T_date_range(ticks)
|
||||
return new(d_ct, ticks)
|
||||
end
|
||||
|
||||
local function dfirst(x, y)
|
||||
if istype(d_ct, y) then
|
||||
return y, x
|
||||
else
|
||||
return x, y
|
||||
end
|
||||
end
|
||||
|
||||
-- 1582 adoption, 9999 to keep 4 chars for years part:
|
||||
local function T_year(year) T_int(year)
|
||||
if not (1582 <= year and year <= 9999) then
|
||||
error("year "..year.." outside the allowed range [1582, 9999]")
|
||||
end
|
||||
end
|
||||
|
||||
local function T_month(month) T_int(month)
|
||||
if not (1 <= month and month <= 12) then
|
||||
error("month "..month.." outside the allowed range [1, 12]")
|
||||
end
|
||||
end
|
||||
|
||||
local function isleapyear(year) T_year(year)
|
||||
return year%4 == 0 and (year%100 ~= 0 or year%400 == 0)
|
||||
end
|
||||
|
||||
local eom = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
|
||||
local function endofmonth(year, month) T_year(year) T_month(month)
|
||||
return (month == 2 and isleapyear(year)) and 29 or eom[month]
|
||||
end
|
||||
|
||||
local function T_day(year, month, day)
|
||||
if not (1 <= day and day <= endofmonth(year, month)) then
|
||||
error(year.."-"..month.."-"..day.." is not a valid date")
|
||||
end
|
||||
end
|
||||
|
||||
local function weekday(year, month, day) T_year(year) T_month(month)
|
||||
T_day(year, month, day)
|
||||
local a = floor((14 - month)/12)
|
||||
local y = year - a
|
||||
local m = month + 12*a - 2
|
||||
local d = (day + y + floor(y/4) - floor(y/100) + floor(y/400) +
|
||||
floor((31*m)/12)) % 7
|
||||
return d == 0 and 7 or d -- Days of week from 1 = Monday to 7 = Sunday.
|
||||
end
|
||||
|
||||
local function shift_months(y, m, deltam)
|
||||
local newm = (m - 1 + deltam) % 12 + 1
|
||||
local newy = y + floor((m - 1 + deltam)/12)
|
||||
T_year(newy)
|
||||
T_month(newm)
|
||||
return newy, newm
|
||||
end
|
||||
|
||||
local function ymd_to_julian(year, month, day)
|
||||
-- Range of numbers suffices for this:
|
||||
local a = floor((14 - month)/12)
|
||||
local y = year + 4800 - a
|
||||
local m = month + 12*a - 3
|
||||
return day + floor((153*m + 2)/5) + 365*y + floor(y/4) - floor(y/100) +
|
||||
floor(y/400) - 32045
|
||||
end
|
||||
|
||||
local function julian_to_ymd(julian)
|
||||
-- Range of numbers suffices for this:
|
||||
local a = julian + 32044
|
||||
local b = floor((4*a + 3)/146097)
|
||||
local c = a - floor((146097*b)/4)
|
||||
local d = floor((4*c + 3)/1461)
|
||||
local e = c - floor((1461*d)/4)
|
||||
local m = floor((5*e + 2)/153)
|
||||
local day = e - floor((153*m + 2)/5) + 1
|
||||
local month = m + 3 - 12*floor(m/10)
|
||||
local year = 100*b + d - 4800 + floor(m/10)
|
||||
return year, month, day
|
||||
end
|
||||
|
||||
-- Assumes only violation of valid date may be in day outside of end of month
|
||||
-- due to months and years shifts. Cap the day and returns a valid date.
|
||||
local function valid_date_cap_day(year, month, day)
|
||||
day = min(day, endofmonth(year, month))
|
||||
return d_ct(year, month, day)
|
||||
end
|
||||
|
||||
local d_mt = {
|
||||
__new = function(ct, year, month, day) T_year(year) T_month(month)
|
||||
T_day(year, month, day)
|
||||
return new(ct, ymd_to_julian(year, month, day)*(86400LL*1e6))
|
||||
end,
|
||||
copy = function(self)
|
||||
return new(d_ct, self)
|
||||
end,
|
||||
__eq = p_mt.__eq,
|
||||
__lt = p_mt.__lt,
|
||||
__le = p_mt.__le,
|
||||
__add = function(self, rhs) -- Commutative.
|
||||
local d, s = dfirst(self, rhs)
|
||||
if istype(p_ct, s) then
|
||||
return d_64(d._ticks + s._ticks)
|
||||
elseif istype(months_ct, s) then
|
||||
local year, month, day = d:ymd()
|
||||
year, month = shift_months(year, month, s._m)
|
||||
return valid_date_cap_day(year, month, day) + d:period()
|
||||
elseif istype(years_ct, s) then
|
||||
local year, month, day = d:ymd()
|
||||
year = year + s._y
|
||||
return valid_date_cap_day(year, month, day) + d:period()
|
||||
else
|
||||
error("unexpected type")
|
||||
end
|
||||
end,
|
||||
__sub = function(self, rhs)
|
||||
T_date(self) -- Disallow (not-a-date)-date.
|
||||
if istype(p_ct, rhs) then
|
||||
return d_64(self._ticks - rhs._ticks)
|
||||
elseif istype(months_ct, rhs) then
|
||||
local year, month, day = self:ymd()
|
||||
year, month = shift_months(year, month, -rhs._m)
|
||||
return valid_date_cap_day(year, month, day) + self:period()
|
||||
elseif istype(years_ct, rhs) then
|
||||
local year, month, day = self:ymd()
|
||||
year = year - rhs._y
|
||||
return valid_date_cap_day(year, month, day) + self:period()
|
||||
elseif istype(d_ct, rhs) then
|
||||
return p_64(self._ticks - rhs._ticks)
|
||||
else
|
||||
error("unexpected type")
|
||||
end
|
||||
end,
|
||||
__tostring = function(self)
|
||||
local year, month, day = self:ymd()
|
||||
local h, m, s, ms = self:period():parts()
|
||||
return format("%i-%02i-%02iT", year, month, day)..posptostr(h, m, s, ms)
|
||||
end,
|
||||
ticks = p_mt.ticks,
|
||||
ymd = function(self)
|
||||
local julian = tonumber(self._ticks/(86400LL*1e6))
|
||||
return julian_to_ymd(julian)
|
||||
end,
|
||||
year = function(self) local y, m, d = self:ymd() return y end,
|
||||
month = function(self) local y, m, d = self:ymd() return m end,
|
||||
day = function(self) local y, m, d = self:ymd() return d end,
|
||||
period = function(self)
|
||||
return p_64(self._ticks%(86400LL*1e6))
|
||||
end,
|
||||
isleapyear = function(self)
|
||||
local y = self:ymd()
|
||||
return isleapyear(y)
|
||||
end,
|
||||
endofmonth = function(self)
|
||||
local y, m = self:ymd()
|
||||
return endofmonth(y, m)
|
||||
end,
|
||||
weekday = function(self)
|
||||
local y, m, d = self:ymd()
|
||||
return weekday(y, m, d)
|
||||
end,
|
||||
}
|
||||
d_mt.__index = d_mt
|
||||
|
||||
d_ct = ffi.metatype("struct { int64_t _ticks; }", d_mt)
|
||||
|
||||
local function todate(x)
|
||||
if type(x) == "string" then
|
||||
local f1, l1, year, month, day, h, m, s, ms =
|
||||
x:find("(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+).(%d+)")
|
||||
if year == nil or ms == nil or l1 ~= #x then
|
||||
error("'"..x.."' is not a string representation of a date")
|
||||
end
|
||||
local ton = tonumber
|
||||
return d_ct(ton(year), ton(month), ton(day)) +
|
||||
p_ct(ton(h), ton(m), ton(s), ton(ms))
|
||||
elseif istype(int64_ct, x) then
|
||||
return d_64(x)
|
||||
else
|
||||
error("unexpected type")
|
||||
end
|
||||
end
|
||||
|
||||
-- System-dependent functions --------------------------------------------------
|
||||
local nowlocal, nowutc, sleep
|
||||
|
||||
if jit.os == "Windows" then -- On Windows sizeof(long) == 4 on both x86 and x64.
|
||||
ffi.cdef[[
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned __int64 ULONGLONG;
|
||||
|
||||
typedef struct _SYSTEMTIME {
|
||||
WORD wYear;
|
||||
WORD wMonth;
|
||||
WORD wDayOfWeek;
|
||||
WORD wDay;
|
||||
WORD wHour;
|
||||
WORD wMinute;
|
||||
WORD wSecond;
|
||||
WORD wMilliseconds;
|
||||
} SYSTEMTIME, *PSYSTEMTIME;
|
||||
|
||||
typedef union _ULARGE_INTEGER {
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
DWORD HighPart;
|
||||
};
|
||||
struct {
|
||||
DWORD LowPart;
|
||||
DWORD HighPart;
|
||||
} u;
|
||||
ULONGLONG QuadPart;
|
||||
} ULARGE_INTEGER, *PULARGE_INTEGER;
|
||||
|
||||
typedef struct _FILETIME {
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME, *PFILETIME;
|
||||
|
||||
void GetLocalTime(
|
||||
PSYSTEMTIME lpSystemTime
|
||||
);
|
||||
//void GetSystemTime(
|
||||
// PSYSTEMTIME lpSystemTime
|
||||
//);
|
||||
void GetSystemTimeAsFileTime(
|
||||
PFILETIME lpSystemTimeAsFileTime
|
||||
);
|
||||
void GetSystemTimeAsPreciseFileTime(
|
||||
PFILETIME lpSystemTimeAsFileTime
|
||||
);
|
||||
void Sleep(
|
||||
DWORD dwMilliseconds
|
||||
);
|
||||
]]
|
||||
|
||||
local st = ffi.new("SYSTEMTIME")
|
||||
local ft = ffi.new("FILETIME")
|
||||
local ul = ffi.new("ULARGE_INTEGER")
|
||||
|
||||
nowlocal = function()
|
||||
C.GetLocalTime(st)
|
||||
return d_ct(st.wYear, st.wMonth, st.wDay) + p_ct(st.wHour, st.wMinute,
|
||||
st.wSecond, st.wMilliseconds*1000)
|
||||
end
|
||||
|
||||
local epoch_offset = d_ct(1601, 1, 1):ticks()
|
||||
local function if_available(lib, fname)
|
||||
local ok, f = pcall(function() return lib[fname] end)
|
||||
return ok and f
|
||||
end
|
||||
local get_system_time = if_available(C, 'GetSystemTimeAsPreciseFileTime')
|
||||
or C.GetSystemTimeAsFileTime
|
||||
|
||||
nowutc = function()
|
||||
-- Resolution: 1 microsecond.
|
||||
-- Accuracy : 1 millisecond up to Windows 7, higher otherwise.
|
||||
get_system_time(ft)
|
||||
ul.LowPart = ft.dwLowDateTime
|
||||
ul.HighPart = ft.dwHighDateTime
|
||||
return new(d_ct, epoch_offset + ul.QuadPart/10)
|
||||
end
|
||||
|
||||
sleep = function(p)
|
||||
if p < p_ct() then
|
||||
error("cannot sleep a negative amount of time")
|
||||
end
|
||||
C.Sleep(p:ticks()/1000)
|
||||
end
|
||||
|
||||
else -- Linux and OSX.
|
||||
ffi.cdef[[
|
||||
typedef long time_t;
|
||||
typedef int useconds_t;
|
||||
|
||||
typedef struct timeval {
|
||||
long tv_sec;
|
||||
int tv_usec;
|
||||
} timeval;
|
||||
typedef struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
long tm_gmtoff;
|
||||
char *tm_zone;
|
||||
} tm;
|
||||
|
||||
int gettimeofday(
|
||||
struct timeval * restrict,
|
||||
void * restrict
|
||||
);
|
||||
struct tm *localtime(
|
||||
const time_t *
|
||||
);
|
||||
int usleep(
|
||||
useconds_t useconds
|
||||
);
|
||||
]]
|
||||
|
||||
-- C.host_get_clock_service it's slower and we don't need higher resolution.
|
||||
-- C.mach_absolute_time does not report real clock.
|
||||
local epoch_offset = d_ct(1970, 1, 1):ticks()
|
||||
local tv = ffi.new("timeval[1]")
|
||||
local tt = ffi.new("time_t[1]")
|
||||
|
||||
nowlocal = function()
|
||||
C.gettimeofday(tv, nil)
|
||||
tt[0] = tv[0].tv_sec
|
||||
local tm = C.localtime(tt)
|
||||
return d_ct(1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday) +
|
||||
p_ct(tm.tm_hour, tm.tm_min, tm.tm_sec, tv[0].tv_usec)
|
||||
end
|
||||
|
||||
nowutc = function()
|
||||
-- Resolution: 1 microsecond.
|
||||
-- Accuracy : 1 microsecond.
|
||||
C.gettimeofday(tv, nil)
|
||||
return new(d_ct, epoch_offset + tv[0].tv_sec*1000000LL + tv[0].tv_usec)
|
||||
end
|
||||
|
||||
sleep = function(p)
|
||||
if p < p_ct() then
|
||||
error("cannot sleep a negative amount of time")
|
||||
end
|
||||
C.usleep(p:ticks())
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
period = p_ct,
|
||||
toperiod = toperiod,
|
||||
|
||||
weeks = weeks,
|
||||
days = days,
|
||||
hours = hours,
|
||||
minutes = minutes,
|
||||
seconds = seconds,
|
||||
milliseconds = milliseconds,
|
||||
microseconds = microseconds,
|
||||
|
||||
date = d_ct,
|
||||
todate = todate,
|
||||
|
||||
isleapyear = isleapyear,
|
||||
endofmonth = endofmonth,
|
||||
weekday = weekday,
|
||||
|
||||
months = months_ct,
|
||||
years = years_ct,
|
||||
|
||||
sleep = sleep,
|
||||
nowlocal = nowlocal,
|
||||
nowutc = nowutc,
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user