13.0.0 Will be out soooooooon I promise

Anyway added some new objects, removed a few and wrote some more documentation... all thats left is system threads and network threads(nodes)
This commit is contained in:
Ryan Ward 2018-11-14 10:27:39 -05:00
parent 040d8842a2
commit 9b5acbd23e
4 changed files with 240 additions and 404 deletions

View File

@ -729,10 +729,74 @@ multi:newAlarm(3):OnRing(function() a = true end) -- allows a to exist
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
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
-----------------------------------

View File

@ -2,7 +2,7 @@
[TOC]
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:
- 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
@ -22,12 +22,47 @@ multi:mainloop()
Removed:
- 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:
- 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!
-------------

View File

@ -430,7 +430,7 @@ function multi:isDone()
end
multi.IsDone=multi.isDone
function multi:create(ref)
multi.OnObjectCreated:Fire(ref)
multi.OnObjectCreated:Fire(ref,self)
end
--Constructors [CORE]
function multi:newBase(ins)
@ -551,6 +551,10 @@ function multi:newTimer()
self:create(c)
return c
end
function multi:newConnector()
local c = {Type = "connector"}
return c
end
function multi:newConnection(protect,func)
local c={}
c.callback = func
@ -800,26 +804,28 @@ function multi:newAlarm(set)
local c=self:newBase()
c.Type='alarm'
c.Priority=self.Priority_Low
c.timer=self:newTimer()
c.set=set or 0
local count = 0
local t = clock()
function c:Act()
if self.timer:Get()>=self.set then
if clock()-t>=self.set then
self:Pause()
self.Active=false
for i=1,#self.func do
self.func[i](self)
end
t = clock()
end
end
function c:Resume()
self.Parent.Resume(self)
self.timer:Resume()
t = count + t
return self
end
function c:Reset(n)
if n then self.set=n end
self:Resume()
self.timer:Reset()
t = clock()
return self
end
function c:OnRing(func)
@ -827,7 +833,7 @@ function multi:newAlarm(set)
return self
end
function c:Pause()
self.timer:Pause()
count = clock()
self.Parent.Pause(self)
return self
end
@ -1432,299 +1438,10 @@ multi.scheduler:OnLoop(function(self)
end)
multi.scheduler:Pause()
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)
local c = {}
local holding = false
local kill = false
setmetatable(c, multi)
function c:newBase(ins)
local ct = {}
@ -1743,7 +1460,7 @@ function multi:newThreadedProcess(name)
c.Active=true
c.func={}
c.Id=0
c.Type='process'
c.Type='threadedprocess'
c.Mainloop={}
c.Garbage={}
c.Children={}
@ -1775,109 +1492,127 @@ function multi:newThreadedProcess(name)
self.ref:kill()
return self
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_"})
if err then
error("Failed to kill a thread! Exiting...")
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
ct:Act()
end
end)
return c
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
return ct
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.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](os.clock()-self.Start,c)
function c:getController()
return nil
end
thread.sleep(c.updaterate) -- lets rest a bit
end
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)
function c:Start()
holding = false
return self
end
function c:Resume()
self.rest=false
holding = false
return self
end
function c:Pause()
self.rest=true
holding = true
return self
end
c.rest=false
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.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
function c:Remove()
self.ref:kill()
return self
end
function c:Kill()
kill = true
return self
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)
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
end
-- Multi runners

View File

@ -1,14 +1,16 @@
package.path="?/init.lua;?.lua;"..package.path
local multi = require("multi")
multi:newThread("TickTocker",function()
print("Waiting for variable a to exist...")
ret,ret2 = thread.hold(function()
return a~=nil, "test!"
test = multi:newHyperThreadedProcess("test")
test:newLoop(function()
print("HI!")
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)
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()