v13.0.0 #11
@ -729,10 +729,74 @@ multi:newAlarm(3):OnRing(function() a = true end) -- allows a to exist
|
|||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
```
|
```
|
||||||
|
|
||||||
CBT: Process
|
CBT: Threaded Process
|
||||||
-----------
|
---------------------
|
||||||
`process = multi:newThreadedProcess(STRING name)` -- Creates a process object that is able allows all processes created on it to use the thread.* namespace
|
`process = multi:newThreadedProcess(STRING name)` -- Creates a process object that is able allows all processes created on it to use the thread.* namespace
|
||||||
|
|
||||||
System Threads - Multi-core
|
`nil = process:getController()` -- Returns nothing there is no "controller" when using threaded processes
|
||||||
---------------------------
|
`self = process:Start()` -- Starts the processor
|
||||||
|
`self = process:Pause()` -- Pauses the processor
|
||||||
|
`self = process:Resume()` -- Resumes a paused processor
|
||||||
|
`self = process:Kill()` -- Kills/Destroys the process thread
|
||||||
|
`self = process:Remove()` -- Destroys/Kills the processor and all of the Actors running on it
|
||||||
|
`self = process:Sleep(NUMBER n)` -- Forces a process to sleep for n amount of time
|
||||||
|
`self = process:Hold(FUNCTION/NUMBER n)` -- Forces a process to either test a condition or sleep.
|
||||||
|
|
||||||
|
Everything eles works as if you were using the multi.* interface. You can create multi objects on the process and the objects are able to use the thread.* interface.
|
||||||
|
|
||||||
|
Note: When using Hold/Sleep/Skip on an object created inside of a threaded process, you actually hold the entire process! Which means all objects on that process will be stopping until the conditions are met!
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
test = multi:newThreadedProcess("test")
|
||||||
|
test:newLoop(function()
|
||||||
|
print("HI!")
|
||||||
|
end)
|
||||||
|
test:newLoop(function()
|
||||||
|
print("HI2!")
|
||||||
|
thread.sleep(.5)
|
||||||
|
end)
|
||||||
|
multi:newAlarm(3):OnRing(function()
|
||||||
|
test:Sleep(10)
|
||||||
|
end)
|
||||||
|
test:Start()
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
|
||||||
|
CBT: Hyper Threaded Process
|
||||||
|
---------------------------
|
||||||
|
`process = multi:newHyperThreadedProcess(STRING name)` -- Creates a process object that is able allows all processes created on it to use the thread.* namespace. Hold/Sleep/Skip can be used in each multi obj created without stopping each other object that is running.
|
||||||
|
|
||||||
|
`nil = process:getController()` -- Returns nothing there is no "controller" when using threaded processes
|
||||||
|
`self = process:Start()` -- Starts the processor
|
||||||
|
`self = process:Pause()` -- Pauses the processor
|
||||||
|
`self = process:Resume()` -- Resumes a paused processor
|
||||||
|
`self = process:Kill()` -- Kills/Destroys the process thread
|
||||||
|
`self = process:Remove()` -- Destroys/Kills the processor and all of the Actors running on it
|
||||||
|
`self = process:Sleep(NUMBER n)` -- Forces a process to sleep for n amount of time
|
||||||
|
`self = process:Hold(FUNCTION/NUMBER n)` -- Forces a process to either test a condition or sleep.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
test = multi:newHyperThreadedProcess("test")
|
||||||
|
test:newLoop(function()
|
||||||
|
print("HI!")
|
||||||
|
end)
|
||||||
|
test:newLoop(function()
|
||||||
|
print("HI2!")
|
||||||
|
thread.sleep(.5)
|
||||||
|
end)
|
||||||
|
multi:newAlarm(3):OnRing(function()
|
||||||
|
test:Sleep(10)
|
||||||
|
end)
|
||||||
|
test:Start()
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
Same example as above, but notice how this works opposed to the non hyper version
|
||||||
|
|
||||||
|
System Threads - Multi-Integration
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Network Threads - Multi-Integration
|
||||||
|
-----------------------------------
|
||||||
|
|||||||
41
changes.md
41
changes.md
@ -2,7 +2,7 @@
|
|||||||
[TOC]
|
[TOC]
|
||||||
Update 13.0.0 So you documented it, finally, but it's sad to see some things go isn't it?
|
Update 13.0.0 So you documented it, finally, but it's sad to see some things go isn't it?
|
||||||
-------------
|
-------------
|
||||||
Fixed: Tons of bugs, I actually went through the entire library and did a full test of everything while writing the documentation.
|
Fixed: Tons of bugs, I actually went through the entire library and did a full test of everything, I mean everything, while writing the documentation.
|
||||||
Changed:
|
Changed:
|
||||||
- A few things, to make concepts in the library more clear
|
- A few things, to make concepts in the library more clear
|
||||||
- The way functions returned paused status. Before it would return "PAUSED" now it returns nil, true if paused
|
- The way functions returned paused status. Before it would return "PAUSED" now it returns nil, true if paused
|
||||||
@ -22,12 +22,47 @@ multi:mainloop()
|
|||||||
|
|
||||||
Removed:
|
Removed:
|
||||||
- Ranges and conditions -- corutine based threads can dmulate what these objects did and much better!
|
- Ranges and conditions -- corutine based threads can dmulate what these objects did and much better!
|
||||||
-
|
- Due to the creation of hyper threaded processes the following objects are no more!
|
||||||
|
-- ~~multi:newThreadedEvent()~~
|
||||||
|
-- ~~multi:newThreadedLoop()~~
|
||||||
|
-- ~~multi:newThreadedTLoop()~~
|
||||||
|
-- ~~multi:newThreadedStep()~~
|
||||||
|
-- ~~multi:newThreadedTStep()~~
|
||||||
|
-- ~~multi:newThreadedAlarm()~~
|
||||||
|
-- ~~multi:newThreadedUpdater()~~
|
||||||
|
|
||||||
|
These didn't have much use in their previous form, but with the addition of hyper threaded processes the goals that these objects aimed to solve are now possible using a process
|
||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
- There were some bugs in the networkmanager.lua file. Desrtoy -> Destroy some misspellings.
|
- There were some bugs in the networkmanager.lua file. Desrtoy -> Destroy some misspellings.
|
||||||
|
|
||||||
Added: ...
|
Added:
|
||||||
|
- multi:newHyperThreadedProcess(STRING name) -- This is a version of the threaded process that gives each object created its own coroutine based thread which means you can use thread.* without affecting other objects created within the hyper threaded processes.
|
||||||
|
- multi:newConnector() -- A simple object that allows you to use the new connection Fire syntax without using a multi obj
|
||||||
|
|
||||||
|
```lua
|
||||||
|
package.path="?/init.lua;?.lua;"..package.path
|
||||||
|
local multi = require("multi")
|
||||||
|
conn = multi:newConnector()
|
||||||
|
conn.OnTest = multi:newConnection()
|
||||||
|
conn.OnTest(function()
|
||||||
|
print("Yes!")
|
||||||
|
end)
|
||||||
|
test = multi:newHyperThreadedProcess("test")
|
||||||
|
test:newTLoop(function()
|
||||||
|
print("HI!")
|
||||||
|
conn:OnTest()
|
||||||
|
end,1)
|
||||||
|
test:newLoop(function()
|
||||||
|
print("HI2!")
|
||||||
|
thread.sleep(.5)
|
||||||
|
end)
|
||||||
|
multi:newAlarm(3):OnRing(function()
|
||||||
|
test:Sleep(10)
|
||||||
|
end)
|
||||||
|
test:Start()
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
|
||||||
Update 12.2.2 Time for some more bug fixes!
|
Update 12.2.2 Time for some more bug fixes!
|
||||||
-------------
|
-------------
|
||||||
|
|||||||
495
multi/init.lua
495
multi/init.lua
@ -430,7 +430,7 @@ function multi:isDone()
|
|||||||
end
|
end
|
||||||
multi.IsDone=multi.isDone
|
multi.IsDone=multi.isDone
|
||||||
function multi:create(ref)
|
function multi:create(ref)
|
||||||
multi.OnObjectCreated:Fire(ref)
|
multi.OnObjectCreated:Fire(ref,self)
|
||||||
end
|
end
|
||||||
--Constructors [CORE]
|
--Constructors [CORE]
|
||||||
function multi:newBase(ins)
|
function multi:newBase(ins)
|
||||||
@ -551,6 +551,10 @@ function multi:newTimer()
|
|||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
function multi:newConnector()
|
||||||
|
local c = {Type = "connector"}
|
||||||
|
return c
|
||||||
|
end
|
||||||
function multi:newConnection(protect,func)
|
function multi:newConnection(protect,func)
|
||||||
local c={}
|
local c={}
|
||||||
c.callback = func
|
c.callback = func
|
||||||
@ -800,26 +804,28 @@ function multi:newAlarm(set)
|
|||||||
local c=self:newBase()
|
local c=self:newBase()
|
||||||
c.Type='alarm'
|
c.Type='alarm'
|
||||||
c.Priority=self.Priority_Low
|
c.Priority=self.Priority_Low
|
||||||
c.timer=self:newTimer()
|
|
||||||
c.set=set or 0
|
c.set=set or 0
|
||||||
|
local count = 0
|
||||||
|
local t = clock()
|
||||||
function c:Act()
|
function c:Act()
|
||||||
if self.timer:Get()>=self.set then
|
if clock()-t>=self.set then
|
||||||
self:Pause()
|
self:Pause()
|
||||||
self.Active=false
|
self.Active=false
|
||||||
for i=1,#self.func do
|
for i=1,#self.func do
|
||||||
self.func[i](self)
|
self.func[i](self)
|
||||||
end
|
end
|
||||||
|
t = clock()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function c:Resume()
|
function c:Resume()
|
||||||
self.Parent.Resume(self)
|
self.Parent.Resume(self)
|
||||||
self.timer:Resume()
|
t = count + t
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
function c:Reset(n)
|
function c:Reset(n)
|
||||||
if n then self.set=n end
|
if n then self.set=n end
|
||||||
self:Resume()
|
self:Resume()
|
||||||
self.timer:Reset()
|
t = clock()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
function c:OnRing(func)
|
function c:OnRing(func)
|
||||||
@ -827,7 +833,7 @@ function multi:newAlarm(set)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
function c:Pause()
|
function c:Pause()
|
||||||
self.timer:Pause()
|
count = clock()
|
||||||
self.Parent.Pause(self)
|
self.Parent.Pause(self)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -1432,299 +1438,10 @@ multi.scheduler:OnLoop(function(self)
|
|||||||
end)
|
end)
|
||||||
multi.scheduler:Pause()
|
multi.scheduler:Pause()
|
||||||
multi.OnError=multi:newConnection()
|
multi.OnError=multi:newConnection()
|
||||||
function multi:newThreadedAlarm(name,set)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
c.Type='alarmThread'
|
|
||||||
c.timer=self:newTimer()
|
|
||||||
c.set=set or 0
|
|
||||||
function c:Resume()
|
|
||||||
self.rest=false
|
|
||||||
self.timer:Resume()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Reset(n)
|
|
||||||
if n then self.set=n end
|
|
||||||
self.rest=false
|
|
||||||
self.timer:Reset(n)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnRing(func)
|
|
||||||
table.insert(self.func,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Pause()
|
|
||||||
self.timer:Pause()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.rest=false
|
|
||||||
c.updaterate=multi.Priority_Low -- skips
|
|
||||||
c.restRate=0 -- secs
|
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
thread.sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
if c.timer:Get()>=c.set then
|
|
||||||
c:Pause()
|
|
||||||
for i=1,#c.func do
|
|
||||||
c.func[i](c)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
thread.skip(c.updaterate) -- lets rest a bit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
self:create(c)
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
function multi:newThreadedUpdater(name,skip)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
c.Type='updaterThread'
|
|
||||||
c.pos=1
|
|
||||||
c.skip=skip or 1
|
|
||||||
function c:Resume()
|
|
||||||
self.rest=false
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Pause()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.OnUpdate=self.OnMainConnect
|
|
||||||
c.rest=false
|
|
||||||
c.updaterate=0
|
|
||||||
c.restRate=.75
|
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
thread.sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
for i=1,#c.func do
|
|
||||||
c.func[i](c)
|
|
||||||
end
|
|
||||||
c.pos=c.pos+1
|
|
||||||
thread.skip(c.skip)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
self:create(c)
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
function multi:newThreadedTStep(name,start,reset,count,set)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
local think=1
|
|
||||||
c.Type='tstepThread'
|
|
||||||
c.start=start or 1
|
|
||||||
local reset = reset or math.huge
|
|
||||||
c.endAt=reset
|
|
||||||
c.pos=start or 1
|
|
||||||
c.skip=skip or 0
|
|
||||||
c.count=count or 1*think
|
|
||||||
c.funcE={}
|
|
||||||
c.timer=os.clock()
|
|
||||||
c.set=set or 1
|
|
||||||
c.funcS={}
|
|
||||||
function c:Update(start,reset,count,set)
|
|
||||||
self.start=start or self.start
|
|
||||||
self.pos=self.start
|
|
||||||
self.endAt=reset or self.endAt
|
|
||||||
self.set=set or self.set
|
|
||||||
self.count=count or self.count or 1
|
|
||||||
self.timer=os.clock()
|
|
||||||
self:Resume()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Resume()
|
|
||||||
self.rest=false
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Pause()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnStart(func)
|
|
||||||
table.insert(self.funcS,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnStep(func)
|
|
||||||
table.insert(self.func,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnEnd(func)
|
|
||||||
table.insert(self.funcE,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Break()
|
|
||||||
self.Active=nil
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Reset(n)
|
|
||||||
if n then self.set=n end
|
|
||||||
self.timer=os.clock()
|
|
||||||
self:Resume()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.updaterate=0--multi.Priority_Low -- skips
|
|
||||||
c.restRate=0
|
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
thread.sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
if os.clock()-c.timer>=c.set then
|
|
||||||
c:Reset()
|
|
||||||
if c.pos==c.start then
|
|
||||||
for fe=1,#c.funcS do
|
|
||||||
c.funcS[fe](c)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i=1,#c.func do
|
|
||||||
c.func[i](c,c.pos)
|
|
||||||
end
|
|
||||||
c.pos=c.pos+c.count
|
|
||||||
if c.pos-c.count==c.endAt then
|
|
||||||
c:Pause()
|
|
||||||
for fe=1,#c.funcE do
|
|
||||||
c.funcE[fe](c)
|
|
||||||
end
|
|
||||||
c.pos=c.start
|
|
||||||
end
|
|
||||||
end
|
|
||||||
thread.skip(c.updaterate) -- lets rest a bit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
self:create(c)
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
function multi:newThreadedTLoop(name,func,n)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
c.Type='tloopThread'
|
|
||||||
c.restN=n or 1
|
|
||||||
if func then
|
|
||||||
c.func={func}
|
|
||||||
end
|
|
||||||
function c:Resume()
|
|
||||||
self.rest=false
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Pause()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnLoop(func)
|
|
||||||
table.insert(self.func,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.rest=false
|
|
||||||
c.updaterate=0
|
|
||||||
c.restRate=.75
|
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
thread.sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
for i=1,#c.func do
|
|
||||||
c.func[i](c)
|
|
||||||
end
|
|
||||||
thread.sleep(c.restN) -- lets rest a bit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
self:create(c)
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
function multi:newThreadedStep(name,start,reset,count,skip)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
local think=1
|
|
||||||
c.Type='stepThread'
|
|
||||||
c.pos=start or 1
|
|
||||||
c.endAt=reset or math.huge
|
|
||||||
c.skip=skip or 0
|
|
||||||
c.spos=0
|
|
||||||
c.count=count or 1*think
|
|
||||||
c.funcE={}
|
|
||||||
c.funcS={}
|
|
||||||
c.start=start or 1
|
|
||||||
if start~=nil and reset~=nil then
|
|
||||||
if start>reset then
|
|
||||||
think=-1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function c:Resume()
|
|
||||||
self.rest=false
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Pause()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.Reset=c.Resume
|
|
||||||
function c:OnStart(func)
|
|
||||||
table.insert(self.funcS,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnStep(func)
|
|
||||||
table.insert(self.func,1,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnEnd(func)
|
|
||||||
table.insert(self.funcE,func)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Break()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Update(start,reset,count,skip)
|
|
||||||
self.start=start or self.start
|
|
||||||
self.endAt=reset or self.endAt
|
|
||||||
self.skip=skip or self.skip
|
|
||||||
self.count=count or self.count
|
|
||||||
self:Resume()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.updaterate=0
|
|
||||||
c.restRate=.1
|
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
ref:sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
if c~=nil then
|
|
||||||
if c.spos==0 then
|
|
||||||
if c.pos==c.start then
|
|
||||||
for fe=1,#c.funcS do
|
|
||||||
c.funcS[fe](c)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for i=1,#c.func do
|
|
||||||
c.func[i](c,c.pos)
|
|
||||||
end
|
|
||||||
c.pos=c.pos+c.count
|
|
||||||
if c.pos-c.count==c.endAt then
|
|
||||||
c:Pause()
|
|
||||||
for fe=1,#c.funcE do
|
|
||||||
c.funcE[fe](c)
|
|
||||||
end
|
|
||||||
c.pos=c.start
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
c.spos=c.spos+1
|
|
||||||
if c.spos>=c.skip then
|
|
||||||
c.spos=0
|
|
||||||
end
|
|
||||||
ref:sleep(c.updaterate) -- lets rest a bit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
self:create(c)
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
function multi:newThreadedProcess(name)
|
function multi:newThreadedProcess(name)
|
||||||
local c = {}
|
local c = {}
|
||||||
|
local holding = false
|
||||||
|
local kill = false
|
||||||
setmetatable(c, multi)
|
setmetatable(c, multi)
|
||||||
function c:newBase(ins)
|
function c:newBase(ins)
|
||||||
local ct = {}
|
local ct = {}
|
||||||
@ -1743,7 +1460,7 @@ function multi:newThreadedProcess(name)
|
|||||||
c.Active=true
|
c.Active=true
|
||||||
c.func={}
|
c.func={}
|
||||||
c.Id=0
|
c.Id=0
|
||||||
c.Type='process'
|
c.Type='threadedprocess'
|
||||||
c.Mainloop={}
|
c.Mainloop={}
|
||||||
c.Garbage={}
|
c.Garbage={}
|
||||||
c.Children={}
|
c.Children={}
|
||||||
@ -1775,109 +1492,127 @@ function multi:newThreadedProcess(name)
|
|||||||
self.ref:kill()
|
self.ref:kill()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
function c:kill()
|
function c:Kill()
|
||||||
|
kill = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function c:Sleep(n)
|
||||||
|
holding = true
|
||||||
|
if type(n)=="number" then
|
||||||
|
multi:newAlarm(n):OnRing(function(a)
|
||||||
|
holding = false
|
||||||
|
a:Destroy()
|
||||||
|
end)
|
||||||
|
elseif type(n)=="function" then
|
||||||
|
multi:newEvent(n):OnEvent(function(e)
|
||||||
|
holding = false
|
||||||
|
e:Destroy()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
c.Hold=c.Sleep
|
||||||
|
multi:newThread(name,function(ref)
|
||||||
|
while true do
|
||||||
|
thread.hold(function()
|
||||||
|
return not(holding)
|
||||||
|
end)
|
||||||
|
c:uManager()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function multi:newHyperThreadedProcess(name)
|
||||||
|
if not name then error("All threads must have a name!") end
|
||||||
|
local c = {}
|
||||||
|
setmetatable(c, multi)
|
||||||
|
local ind = 0
|
||||||
|
local holding = true
|
||||||
|
local kill = false
|
||||||
|
function c:newBase(ins)
|
||||||
|
local ct = {}
|
||||||
|
ct.Active=true
|
||||||
|
ct.func={}
|
||||||
|
ct.ender={}
|
||||||
|
ct.Id=0
|
||||||
|
ct.Act=function() end
|
||||||
|
ct.Parent=self
|
||||||
|
ct.held=false
|
||||||
|
ct.ref=self.ref
|
||||||
|
ind = ind + 1
|
||||||
|
multi:newThread("Proc <"..name.."> #"..ind,function()
|
||||||
|
while true do
|
||||||
|
thread.hold(function()
|
||||||
|
return not(holding)
|
||||||
|
end)
|
||||||
|
if kill then
|
||||||
err=coroutine.yield({"_kill_"})
|
err=coroutine.yield({"_kill_"})
|
||||||
if err then
|
if err then
|
||||||
error("Failed to kill a thread! Exiting...")
|
error("Failed to kill a thread! Exiting...")
|
||||||
end
|
end
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:sleep(n)
|
|
||||||
if type(n)=="function" then
|
|
||||||
ret=coroutine.yield({"_hold_",n})
|
|
||||||
elseif type(n)=="number" then
|
|
||||||
n = tonumber(n) or 0
|
|
||||||
ret=coroutine.yield({"_sleep_",n})
|
|
||||||
else
|
|
||||||
error("Invalid Type for sleep!")
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.hold=c.sleep
|
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
ref:Sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
c:uManager()
|
|
||||||
ref:sleep(c.updaterate) -- lets rest a bit
|
|
||||||
end
|
end
|
||||||
|
ct:Act()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
return c
|
return ct
|
||||||
end
|
|
||||||
function multi:newThreadedLoop(name,func)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
c.Type='loopThread'
|
|
||||||
c.Start=os.clock()
|
|
||||||
if func then
|
|
||||||
c.func={func}
|
|
||||||
end
|
|
||||||
function c:Resume()
|
|
||||||
self.rest=false
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:Pause()
|
|
||||||
self.rest=true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
function c:OnLoop(func)
|
|
||||||
table.insert(self.func,func)
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
c.Parent=self
|
||||||
|
c.Active=true
|
||||||
|
c.func={}
|
||||||
|
c.Id=0
|
||||||
|
c.Type='hyperthreadedprocess'
|
||||||
|
c.Mainloop={}
|
||||||
|
c.Garbage={}
|
||||||
|
c.Children={}
|
||||||
|
c.Active=true
|
||||||
|
c.Id=-1
|
||||||
|
c.Rest=0
|
||||||
|
c.updaterate=.01
|
||||||
|
c.restRate=.1
|
||||||
|
c.Jobs={}
|
||||||
|
c.queue={}
|
||||||
|
c.jobUS=2
|
||||||
c.rest=false
|
c.rest=false
|
||||||
c.updaterate=0
|
function c:getController()
|
||||||
c.restRate=.75
|
return nil
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
thread.sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
for i=1,#c.func do
|
|
||||||
c.func[i](os.clock()-self.Start,c)
|
|
||||||
end
|
end
|
||||||
thread.sleep(c.updaterate) -- lets rest a bit
|
function c:Start()
|
||||||
end
|
holding = false
|
||||||
end
|
|
||||||
end)
|
|
||||||
self:create(c)
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
function multi:newThreadedEvent(name,task)
|
|
||||||
local c=self:newTBase(name)
|
|
||||||
c.Type='eventThread'
|
|
||||||
c.Task=task or function() end
|
|
||||||
function c:OnEvent(func)
|
|
||||||
table.insert(self.func,func)
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
function c:Resume()
|
function c:Resume()
|
||||||
self.rest=false
|
holding = false
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
function c:Pause()
|
function c:Pause()
|
||||||
self.rest=true
|
holding = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
c.rest=false
|
function c:Remove()
|
||||||
c.updaterate=0
|
self.ref:kill()
|
||||||
c.restRate=1
|
return self
|
||||||
multi:newThread(name,function(ref)
|
|
||||||
while true do
|
|
||||||
if c.rest then
|
|
||||||
ref:sleep(c.restRate) -- rest a bit more when a thread is paused
|
|
||||||
else
|
|
||||||
if c.Task(self) then
|
|
||||||
for _E=1,#c.func do
|
|
||||||
c.func[_E](c)
|
|
||||||
end
|
|
||||||
c:Pause()
|
|
||||||
end
|
|
||||||
ref:sleep(c.updaterate) -- lets rest a bit
|
|
||||||
end
|
end
|
||||||
|
function c:Kill()
|
||||||
|
kill = true
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
function c:Sleep(b)
|
||||||
|
holding = true
|
||||||
|
if type(b)=="number" then
|
||||||
|
local t = os.clock()
|
||||||
|
multi:newAlarm(b):OnRing(function(a)
|
||||||
|
holding = false
|
||||||
|
a:Destroy()
|
||||||
end)
|
end)
|
||||||
self:create(c)
|
elseif type(b)=="function" then
|
||||||
|
multi:newEvent(b):OnEvent(function(e)
|
||||||
|
holding = false
|
||||||
|
e:Destroy()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
c.Hold=c.Sleep
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
-- Multi runners
|
-- Multi runners
|
||||||
|
|||||||
18
test.lua
18
test.lua
@ -1,14 +1,16 @@
|
|||||||
package.path="?/init.lua;?.lua;"..package.path
|
package.path="?/init.lua;?.lua;"..package.path
|
||||||
local multi = require("multi")
|
local multi = require("multi")
|
||||||
|
test = multi:newHyperThreadedProcess("test")
|
||||||
multi:newThread("TickTocker",function()
|
test:newLoop(function()
|
||||||
print("Waiting for variable a to exist...")
|
print("HI!")
|
||||||
ret,ret2 = thread.hold(function()
|
|
||||||
return a~=nil, "test!"
|
|
||||||
end)
|
end)
|
||||||
print(ret,ret2) -- The hold method returns the arguments when the first argument is true. This methods return feature is rather new and took more work then you think to get working. Since threads
|
test:newLoop(function()
|
||||||
|
print("HI2!")
|
||||||
|
thread.sleep(.5)
|
||||||
end)
|
end)
|
||||||
multi:newAlarm(3):OnRing(function() a = true end) -- allows a to exist
|
multi:newAlarm(3):OnRing(function()
|
||||||
|
test:Sleep(10)
|
||||||
|
end)
|
||||||
|
test:Start()
|
||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user