mirror of
https://github.com/rayaman/multi.git
synced 2026-09-05 07:27:35 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5edea3a6a4 | ||
|
|
f072c2cfde | ||
|
|
bf011646f7 | ||
|
|
091cd90a0d | ||
|
|
acbfef10cc | ||
|
|
aad031062f | ||
|
|
3ff72de1e0 |
@@ -1,15 +1,87 @@
|
|||||||
# multi Version: 1.5.0
|
# multi Version: 1.7.0 (Taking multi-tasking to the next level)
|
||||||
Updated from 1.4.1
|
Updated from 1.6.0 to 1.7.0
|
||||||
|
Modified: multi.intergration.lanesManager.lua
|
||||||
|
It is now in a stable and simple state Works with the latest lanes version! Tested with version 3.11 I cannot promise that everything will work with eariler versions. Future versions are good though.
|
||||||
|
Example Usage:
|
||||||
|
```lua
|
||||||
|
local GLOBAL,lthread=require("multi.intergration.lanesManager").init()
|
||||||
|
require("multi.alarm")
|
||||||
|
require("multi.threading")
|
||||||
|
multi:newAlarm(2):OnRing(function(self)
|
||||||
|
GLOBAL["NumOfCores"]=lthread.getCores()
|
||||||
|
end)
|
||||||
|
multi:newAlarm(7):OnRing(function(self)
|
||||||
|
GLOBAL["AnotherTest"]=true
|
||||||
|
end)
|
||||||
|
multi:newAlarm(13):OnRing(function(self)
|
||||||
|
GLOBAL["FinalTest"]=true
|
||||||
|
end)
|
||||||
|
multi:newSystemThread("test",function() -- spawns a thread in another lua process
|
||||||
|
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
|
||||||
|
print("Waiting for variable: NumOfCores")
|
||||||
|
print("Got it: ",lthread.waitFor("NumOfCores"))
|
||||||
|
lthread.hold(function()
|
||||||
|
return GLOBAL["AnotherTest"] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded...
|
||||||
|
end)
|
||||||
|
print("Holding works!")
|
||||||
|
multi:newThread("tests",function()
|
||||||
|
thread.hold(function()
|
||||||
|
return GLOBAL["FinalTest"] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going!
|
||||||
|
end)
|
||||||
|
print("Final test works!")
|
||||||
|
os.exit()
|
||||||
|
end)
|
||||||
|
local a=0
|
||||||
|
multi:newTLoop(function()
|
||||||
|
a=a+1
|
||||||
|
print(a)
|
||||||
|
end,.5)
|
||||||
|
multi:mainloop()
|
||||||
|
end)
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
Onec I am happy with the intergration and feel it is ready I will document it better
|
||||||
|
|
||||||
|
|
||||||
|
Updated from 1.5.0 to 1.6.0
|
||||||
|
Changed: steps and loops
|
||||||
|
```lua
|
||||||
|
-- Was
|
||||||
|
step:OnStep(function(pos,self) -- same goes for tsteps as well
|
||||||
|
print(pos)
|
||||||
|
end)
|
||||||
|
multi:newLoop(function(dt,self)
|
||||||
|
print(dt)
|
||||||
|
end)
|
||||||
|
-- Is now
|
||||||
|
step:OnStep(function(self,pos) -- same goes for tsteps as well
|
||||||
|
print(pos)
|
||||||
|
end)
|
||||||
|
multi:newLoop(function(self,dt)
|
||||||
|
print(dt)
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
Reasoning I wanted to keep objects consistant, but a lot of my older libraries use the old way of doing things. Therefore I added a backwards module
|
||||||
|
```lua
|
||||||
|
require("multi.all")
|
||||||
|
require("multi.compat.backwards[1,5,0]") -- allows for the use of features that were scrapped/changed in 1.6.0+
|
||||||
|
```
|
||||||
|
Updated from 1.4.1 to 1.5.0
|
||||||
Added:
|
Added:
|
||||||
- An easy way to manage timeouts
|
- An easy way to manage timeouts
|
||||||
- Small bug fixes
|
- Small bug fixes
|
||||||
|
|
||||||
|
1.4.1 - First Public release of the library
|
||||||
|
|
||||||
|
IMPORTANT:
|
||||||
|
Every update I make aims to make things simpler more efficent and just better, but a lot of old code, which can be really big, uses a lot of older features. I know the pain of having to rewrite everything. My promise to my library users is that I will always have backwards support for older features! New ways may exist that are quicker and eaiser, but the old features/methods will be supported.
|
||||||
|
|
||||||
Example at end of the readme
|
Example at end of the readme
|
||||||
|
|
||||||
My multitasking library for lua</br>
|
My multitasking library for lua</br>
|
||||||
To install copy the multi folder into your enviroment and you are good to go</br>
|
To install copy the multi folder into your enviroment and you are good to go</br>
|
||||||
|
|
||||||
It is a pure lua binding if you ingore the intergrations (WIP)</br>
|
It is a pure lua binding if you ingore the intergrations (Stable!)</br>
|
||||||
|
|
||||||
If you find any bugs or have any issues please let me know :)
|
If you find any bugs or have any issues please let me know :)
|
||||||
|
|
||||||
@@ -68,7 +140,7 @@ Throughout these examples I am going to do some strange things in order to show
|
|||||||
-- Loops
|
-- Loops
|
||||||
require("multi.all") -- gets the entire library
|
require("multi.all") -- gets the entire library
|
||||||
count=0
|
count=0
|
||||||
loop=multi:newLoop(function(dt,self) -- dt is delta time and self is a reference to itself
|
loop=multi:newLoop(function(self,dt) -- dt is delta time and self is a reference to itself
|
||||||
count=count+1
|
count=count+1
|
||||||
if count > 10 then
|
if count > 10 then
|
||||||
self:Break() -- All methods on the multi objects are upper camel case, where as methods on the multi or process/queuer namespace are lower camel case
|
self:Break() -- All methods on the multi objects are upper camel case, where as methods on the multi or process/queuer namespace are lower camel case
|
||||||
@@ -108,7 +180,7 @@ This library aims to be Async like. In reality everything is still on one thread
|
|||||||
require("multi.all") -- gets the entire library
|
require("multi.all") -- gets the entire library
|
||||||
count=0
|
count=0
|
||||||
-- lets use the loop again to add to count!
|
-- lets use the loop again to add to count!
|
||||||
loop=multi:newLoop(function(dt,self)
|
loop=multi:newLoop(function(self,dt)
|
||||||
count=count+1
|
count=count+1
|
||||||
end)
|
end)
|
||||||
event=multi:newEvent(function() return count==100 end) -- set the event
|
event=multi:newEvent(function() return count==100 end) -- set the event
|
||||||
@@ -131,7 +203,7 @@ step2=multi:newStep(10,1,-1,1) -- a second step, notice the slight changes!
|
|||||||
step1:OnStart(function(self)
|
step1:OnStart(function(self)
|
||||||
print("Step Started!")
|
print("Step Started!")
|
||||||
end)
|
end)
|
||||||
step1:OnStep(function(pos,self)
|
step1:OnStep(function(self,pos)
|
||||||
if pos<=10 then -- what what is this? the step only goes to 10!!!
|
if pos<=10 then -- what what is this? the step only goes to 10!!!
|
||||||
print("Stepping... "..pos)
|
print("Stepping... "..pos)
|
||||||
else
|
else
|
||||||
@@ -150,7 +222,7 @@ end)
|
|||||||
-- step2 is bored lets give it some love :P
|
-- step2 is bored lets give it some love :P
|
||||||
step2.range=step2:newRange() -- Set up a range object to have a nested step in a sense! Each nest requires a new range
|
step2.range=step2:newRange() -- Set up a range object to have a nested step in a sense! Each nest requires a new range
|
||||||
-- it is in your interest not to share ranges between objects! You can however do it if it suits your needs though
|
-- it is in your interest not to share ranges between objects! You can however do it if it suits your needs though
|
||||||
step2:OnStep(function(pos,self)
|
step2:OnStep(function(self,pos)
|
||||||
-- for 1=1,math.huge do
|
-- for 1=1,math.huge do
|
||||||
-- print("Haha I am holding the code up because I can!!!")
|
-- print("Haha I am holding the code up because I can!!!")
|
||||||
--end
|
--end
|
||||||
@@ -163,7 +235,7 @@ end)
|
|||||||
-- TSteps are just like alarms and steps mixed together, the only difference in construction is the 4th Argument. On a TStep that argument controls time. The defualt is 1
|
-- TSteps are just like alarms and steps mixed together, the only difference in construction is the 4th Argument. On a TStep that argument controls time. The defualt is 1
|
||||||
-- The Reset(n) works just like you would figure!
|
-- The Reset(n) works just like you would figure!
|
||||||
step3=multi:newTStep(1,10,.5,2) -- lets go from 1 to 10 counting by .5 every 2 seconds
|
step3=multi:newTStep(1,10,.5,2) -- lets go from 1 to 10 counting by .5 every 2 seconds
|
||||||
step3:OnStep(function(pos,self)
|
step3:OnStep(function(self,pos)
|
||||||
print("Ok "..pos.."!")
|
print("Ok "..pos.."!")
|
||||||
end)
|
end)
|
||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
@@ -210,7 +282,7 @@ require("multi.all")
|
|||||||
-- Lets create the events
|
-- Lets create the events
|
||||||
yawn={} -- ill just leave that there
|
yawn={} -- ill just leave that there
|
||||||
OnCustomSafeEvent=multi:newConnection(true) -- lets pcall the calls incase something goes wrong defualt
|
OnCustomSafeEvent=multi:newConnection(true) -- lets pcall the calls incase something goes wrong defualt
|
||||||
OnCustomEvent=multi:newConnection(false) -- lets pcall the calls incase something goes wrong
|
OnCustomEvent=multi:newConnection(false) -- lets not pcall the calls and let errors happen... We are good at coding though so lets get a speed advantage by not pcalling. Pcalling is useful for plugins and stuff that may have been coded badly and you can ingore those connections if need be.
|
||||||
OnCustomEvent:Bind(yawn) -- create the connection lookup data in yawn
|
OnCustomEvent:Bind(yawn) -- create the connection lookup data in yawn
|
||||||
|
|
||||||
-- Lets connect to them, a recent update adds a nice syntax to connect to these
|
-- Lets connect to them, a recent update adds a nice syntax to connect to these
|
||||||
@@ -224,7 +296,7 @@ cd3=OnCustomSafeEvent:Connect(function(arg1,arg2,...)
|
|||||||
print("CSE3",arg1,arg2,...)
|
print("CSE3",arg1,arg2,...)
|
||||||
end) -- lets not give this connection a name
|
end) -- lets not give this connection a name
|
||||||
|
|
||||||
-- no need for connect, but I kept that function because of backwards compatibility
|
-- no need for connect, but I kept that function because of backwards compatibility.
|
||||||
OnCustomEvent(function(arg1,arg2,...)
|
OnCustomEvent(function(arg1,arg2,...)
|
||||||
print(arg1,arg2,...)
|
print(arg1,arg2,...)
|
||||||
end)
|
end)
|
||||||
@@ -395,7 +467,7 @@ updater:OnUpdate(function(self)
|
|||||||
b=b+1
|
b=b+1
|
||||||
end)
|
end)
|
||||||
a=0 -- a counter
|
a=0 -- a counter
|
||||||
loop2=proc:newLoop(function(dt,self)
|
loop2=proc:newLoop(function(self,dt)
|
||||||
print("Lets Go!")
|
print("Lets Go!")
|
||||||
self:hold(3) -- this will keep this object from doing anything! Note: You can only have one hold active at a time! Multiple are possible, but results may not be as they seem see * for how hold works
|
self:hold(3) -- this will keep this object from doing anything! Note: You can only have one hold active at a time! Multiple are possible, but results may not be as they seem see * for how hold works
|
||||||
-- Within a process using hold will keep it alive until the hold is satisified!
|
-- Within a process using hold will keep it alive until the hold is satisified!
|
||||||
@@ -463,10 +535,10 @@ queue = multi:newQueuer()
|
|||||||
queue:newAlarm(3):OnRing(function()
|
queue:newAlarm(3):OnRing(function()
|
||||||
print("Ring ring!!!")
|
print("Ring ring!!!")
|
||||||
end)
|
end)
|
||||||
queue:newStep(1,10):OnStep(function(pos,self)
|
queue:newStep(1,10):OnStep(function(self,pos)
|
||||||
print(pos)
|
print(pos)
|
||||||
end)
|
end)
|
||||||
queue:newLoop(function(dt,self)
|
queue:newLoop(function(self,dt)
|
||||||
if dt==3 then
|
if dt==3 then
|
||||||
self:Break()
|
self:Break()
|
||||||
print("Done")
|
print("Done")
|
||||||
@@ -515,17 +587,17 @@ require("multi.*") -- now I can use that lovely * symbol to require everything
|
|||||||
test=multi:newThreadedProcess("main") -- you can thread processors and all Actors see note for a list of actors you can thread!
|
test=multi:newThreadedProcess("main") -- you can thread processors and all Actors see note for a list of actors you can thread!
|
||||||
test2=multi:newThreadedProcess("main2")
|
test2=multi:newThreadedProcess("main2")
|
||||||
count=0
|
count=0
|
||||||
test:newLoop(function(dt,self)
|
test:newLoop(function(self,dt)
|
||||||
count=count+1
|
count=count+1
|
||||||
thread.sleep(.01)
|
thread.sleep(.01)
|
||||||
end)
|
end)
|
||||||
test2:newLoop(function(dt,self)
|
test2:newLoop(function(self,dt)
|
||||||
print("Hello!")
|
print("Hello!")
|
||||||
thread.sleep(1) -- sleep for some time
|
thread.sleep(1) -- sleep for some time
|
||||||
end)
|
end)
|
||||||
-- threads take a name object then the rest as normal
|
-- threads take a name object then the rest as normal
|
||||||
step=multi:newThreadedTStep("step",1,10)
|
step=multi:newThreadedTStep("step",1,10)
|
||||||
step:OnStep(function(p,self)
|
step:OnStep(function(self,p)
|
||||||
print("step",p)
|
print("step",p)
|
||||||
thread.skip(21) -- skip n cycles
|
thread.skip(21) -- skip n cycles
|
||||||
end)
|
end)
|
||||||
@@ -533,11 +605,11 @@ step:OnEnd(function()
|
|||||||
print("Killing thread!")
|
print("Killing thread!")
|
||||||
thread.kill() -- kill the thread
|
thread.kill() -- kill the thread
|
||||||
end)
|
end)
|
||||||
loop=multi:newThreadedLoop("loop",function(dt,self)
|
loop=multi:newThreadedLoop("loop",function(self,dt)
|
||||||
print(dt)
|
print(dt)
|
||||||
thread.sleep(1.1)
|
thread.sleep(1.1)
|
||||||
end)
|
end)
|
||||||
loop2=multi:newThreadedLoop("loop",function(dt,self)
|
loop2=multi:newThreadedLoop("loop",function(self,dt)
|
||||||
print(dt)
|
print(dt)
|
||||||
thread.hold(function() return count>=100 end)
|
thread.hold(function() return count>=100 end)
|
||||||
print("Count is "..count)
|
print("Count is "..count)
|
||||||
@@ -631,7 +703,7 @@ require("multi.task")
|
|||||||
multi:newTask(function()
|
multi:newTask(function()
|
||||||
print("Hi!")
|
print("Hi!")
|
||||||
end)
|
end)
|
||||||
multi:newLoop(function(dt,self)
|
multi:newLoop(function(self,dt)
|
||||||
print("Which came first the task or the loop?")
|
print("Which came first the task or the loop?")
|
||||||
self:Break()
|
self:Break()
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package.path="?/init.lua;"..package.path
|
||||||
|
require("multi.all")
|
||||||
|
require("multi.compat.backwards[1,5,0]")
|
||||||
|
multi:newLoop(function(dt,self)
|
||||||
|
print(dt)
|
||||||
|
end)
|
||||||
|
multi:mainloop() -- start the main runner
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package.path="?/init.lua;?.lua;"..package.path
|
||||||
|
local GLOBAL,lthread=require("multi.intergration.lanesManager").init()
|
||||||
|
require("multi.alarm")
|
||||||
|
require("multi.threading")
|
||||||
|
for i,v in pairs(lanes.ABOUT) do print(i,v) end
|
||||||
|
multi:newAlarm(2):OnRing(function(self)
|
||||||
|
GLOBAL["NumOfCores"]=lthread.getCores()
|
||||||
|
end)
|
||||||
|
multi:newAlarm(7):OnRing(function(self)
|
||||||
|
GLOBAL["AnotherTest"]=true
|
||||||
|
end)
|
||||||
|
multi:newAlarm(13):OnRing(function(self)
|
||||||
|
GLOBAL["FinalTest"]=true
|
||||||
|
end)
|
||||||
|
multi:newSystemThread("test",function() -- spawns a thread in another lua process
|
||||||
|
require("multi.all") -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the intergration. You would need to require the interaction again though
|
||||||
|
print("Waiting for variable: NumOfCores")
|
||||||
|
print("Got it: ",lthread.waitFor("NumOfCores"))
|
||||||
|
lthread.hold(function()
|
||||||
|
return GLOBAL["AnotherTest"] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded...
|
||||||
|
end)
|
||||||
|
print("Holding works!")
|
||||||
|
multi:newThread("tests",function()
|
||||||
|
thread.hold(function()
|
||||||
|
return GLOBAL["FinalTest"] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going!
|
||||||
|
end)
|
||||||
|
print("Final test works!")
|
||||||
|
os.exit()
|
||||||
|
end)
|
||||||
|
local a=0
|
||||||
|
multi:newTLoop(function()
|
||||||
|
a=a+1
|
||||||
|
print(a)
|
||||||
|
end,.5)
|
||||||
|
multi:mainloop()
|
||||||
|
end)
|
||||||
|
multi:mainloop()
|
||||||
@@ -0,0 +1,282 @@
|
|||||||
|
multi.OnObjectCreated(function(obj)
|
||||||
|
if obj.Type=="loop" then
|
||||||
|
function obj:Act()
|
||||||
|
for i=1,#self.func do
|
||||||
|
self.func[i](self.Parent.clock()-self.Start,self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif obj.Type=="step" then
|
||||||
|
function obj:Act()
|
||||||
|
if self~=nil then
|
||||||
|
if self.spos==0 then
|
||||||
|
if self.pos==self.start then
|
||||||
|
for fe=1,#self.funcS do
|
||||||
|
self.funcS[fe](self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i=1,#self.func do
|
||||||
|
self.func[i](self.pos,self)
|
||||||
|
end
|
||||||
|
self.pos=self.pos+self.count
|
||||||
|
if self.pos-self.count==self.endAt then
|
||||||
|
self:Pause()
|
||||||
|
for fe=1,#self.funcE do
|
||||||
|
self.funcE[fe](self)
|
||||||
|
end
|
||||||
|
self.pos=self.start
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.spos=self.spos+1
|
||||||
|
if self.spos>=self.skip then
|
||||||
|
self.spos=0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif obj.Type=="tstep" then
|
||||||
|
function c:Act()
|
||||||
|
if self.clock()-self.timer>=self.set then
|
||||||
|
self:Reset()
|
||||||
|
if self.pos==self.start then
|
||||||
|
for fe=1,#self.funcS do
|
||||||
|
self.funcS[fe](self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i=1,#self.func do
|
||||||
|
self.func[i](self.pos,self)
|
||||||
|
end
|
||||||
|
self.pos=self.pos+self.count
|
||||||
|
if self.pos-self.count==self.endAt then
|
||||||
|
self:Pause()
|
||||||
|
for fe=1,#self.funcE do
|
||||||
|
self.funcE[fe](self)
|
||||||
|
end
|
||||||
|
self.pos=self.start
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
if thread then
|
||||||
|
function multi:newThreadedLoop(name,func)
|
||||||
|
local c=self:newTBase()
|
||||||
|
c.Type='loopThread'
|
||||||
|
c.Start=os.clock()
|
||||||
|
if func then
|
||||||
|
c.func={func}
|
||||||
|
end
|
||||||
|
function c:tofile(path)
|
||||||
|
local m=bin.new()
|
||||||
|
m:addBlock(self.Type)
|
||||||
|
m:addBlock(self.func)
|
||||||
|
m:addBlock(self.Active)
|
||||||
|
m:tofile(path)
|
||||||
|
end
|
||||||
|
function c:Resume()
|
||||||
|
self.rest=false
|
||||||
|
end
|
||||||
|
function c:Pause()
|
||||||
|
self.rest=true
|
||||||
|
end
|
||||||
|
function c:OnLoop(func)
|
||||||
|
table.insert(self.func,func)
|
||||||
|
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)
|
||||||
|
else
|
||||||
|
for i=1,#c.func do
|
||||||
|
c.func[i](os.clock()-self.Start,c)
|
||||||
|
end
|
||||||
|
thread.sleep(c.updaterate)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
self:create(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function multi:newThreadedStep(name,start,reset,count,skip)
|
||||||
|
local c=self:newTBase()
|
||||||
|
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:tofile(path)
|
||||||
|
local m=bin.new()
|
||||||
|
m:addBlock(self.Type)
|
||||||
|
m:addBlock(self.func)
|
||||||
|
m:addBlock(self.funcE)
|
||||||
|
m:addBlock(self.funcS)
|
||||||
|
m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,spos=self.spos,count=self.count,start=self.start})
|
||||||
|
m:addBlock(self.Active)
|
||||||
|
m:tofile(path)
|
||||||
|
end
|
||||||
|
function c:Resume()
|
||||||
|
self.rest=false
|
||||||
|
end
|
||||||
|
function c:Pause()
|
||||||
|
self.rest=true
|
||||||
|
end
|
||||||
|
c.Reset=c.Resume
|
||||||
|
function c:OnStart(func)
|
||||||
|
table.insert(self.funcS,func)
|
||||||
|
end
|
||||||
|
function c:OnStep(func)
|
||||||
|
table.insert(self.func,1,func)
|
||||||
|
end
|
||||||
|
function c:OnEnd(func)
|
||||||
|
table.insert(self.funcE,func)
|
||||||
|
end
|
||||||
|
function c:Break()
|
||||||
|
self.rest=true
|
||||||
|
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()
|
||||||
|
end
|
||||||
|
c.updaterate=0
|
||||||
|
c.restRate=.1
|
||||||
|
multi:newThread(name,function(ref)
|
||||||
|
while true do
|
||||||
|
if c.rest then
|
||||||
|
ref:sleep(c.restRate)
|
||||||
|
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.pos,c)
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
self:create(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function multi:newThreadedTStep(name,start,reset,count,set)
|
||||||
|
local c=self:newTBase()
|
||||||
|
local think=1
|
||||||
|
c.Type='tstepThread'
|
||||||
|
c.Priority=self.Priority_Low
|
||||||
|
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()
|
||||||
|
end
|
||||||
|
function c:tofile(path)
|
||||||
|
local m=bin.new()
|
||||||
|
m:addBlock(self.Type)
|
||||||
|
m:addBlock(self.func)
|
||||||
|
m:addBlock(self.funcE)
|
||||||
|
m:addBlock(self.funcS)
|
||||||
|
m:addBlock({pos=self.pos,endAt=self.endAt,skip=self.skip,timer=self.timer,count=self.count,start=self.start,set=self.set})
|
||||||
|
m:addBlock(self.Active)
|
||||||
|
m:tofile(path)
|
||||||
|
end
|
||||||
|
function c:Resume()
|
||||||
|
self.rest=false
|
||||||
|
end
|
||||||
|
function c:Pause()
|
||||||
|
self.rest=true
|
||||||
|
end
|
||||||
|
function c:OnStart(func)
|
||||||
|
table.insert(self.funcS,func)
|
||||||
|
end
|
||||||
|
function c:OnStep(func)
|
||||||
|
table.insert(self.func,func)
|
||||||
|
end
|
||||||
|
function c:OnEnd(func)
|
||||||
|
table.insert(self.funcE,func)
|
||||||
|
end
|
||||||
|
function c:Break()
|
||||||
|
self.Active=nil
|
||||||
|
end
|
||||||
|
function c:Reset(n)
|
||||||
|
if n then self.set=n end
|
||||||
|
self.timer=os.clock()
|
||||||
|
self:Resume()
|
||||||
|
end
|
||||||
|
c.updaterate=0
|
||||||
|
c.restRate=0
|
||||||
|
multi:newThread(name,function(ref)
|
||||||
|
while true do
|
||||||
|
if c.rest then
|
||||||
|
thread.sleep(c.restRate)
|
||||||
|
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.pos,c)
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
self:create(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
end
|
||||||
+1
-1
@@ -22,7 +22,7 @@ function print(...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
multi = {}
|
multi = {}
|
||||||
multi.Version={1,5,0}
|
multi.Version={1,6,1}
|
||||||
multi.stage='stable'
|
multi.stage='stable'
|
||||||
multi.__index = multi
|
multi.__index = multi
|
||||||
multi.Mainloop={}
|
multi.Mainloop={}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ end
|
|||||||
-- Step 1 get lanes
|
-- Step 1 get lanes
|
||||||
lanes=require("lanes").configure()
|
lanes=require("lanes").configure()
|
||||||
package.path="lua/?/init.lua;lua/?.lua;"..package.path
|
package.path="lua/?/init.lua;lua/?.lua;"..package.path
|
||||||
require("multi.all") -- get it all and have it on all lanes
|
require("multi.updater") -- get it all and have it on all lanes
|
||||||
local multi=multi
|
local multi=multi
|
||||||
-- Step 2 set up the linda objects
|
-- Step 2 set up the linda objects
|
||||||
local __GlobalLinda = lanes.linda() -- handles global stuff
|
local __GlobalLinda = lanes.linda() -- handles global stuff
|
||||||
@@ -31,8 +31,21 @@ end
|
|||||||
function THREAD.get(name)
|
function THREAD.get(name)
|
||||||
__GlobalLinda:get(name)
|
__GlobalLinda:get(name)
|
||||||
end
|
end
|
||||||
|
local function randomString(n)
|
||||||
|
local str = ''
|
||||||
|
local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
|
||||||
|
for i=1,n do
|
||||||
|
str = str..''..strings[math.random(1,#strings)]
|
||||||
|
end
|
||||||
|
return str
|
||||||
|
end
|
||||||
function THREAD.waitFor(name)
|
function THREAD.waitFor(name)
|
||||||
--
|
local function wait()
|
||||||
|
math.randomseed(os.time())
|
||||||
|
__SleepingLinda:receive(.001,randomString(12))
|
||||||
|
end
|
||||||
|
repeat wait() until __GlobalLinda:get(name)
|
||||||
|
return __GlobalLinda:get(name)
|
||||||
end
|
end
|
||||||
function THREAD.testFor(name,val,sym)
|
function THREAD.testFor(name,val,sym)
|
||||||
--
|
--
|
||||||
@@ -45,63 +58,24 @@ if os.getOS()=="windows" then
|
|||||||
else
|
else
|
||||||
THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n"))
|
THREAD.__CORES=tonumber(io.popen("nproc --all"):read("*n"))
|
||||||
end
|
end
|
||||||
-- Step 4 change the coroutine threading methods to work the same, but with lanes TODO when the lanes scheduler is ready!
|
|
||||||
function THREAD.skip(n)
|
|
||||||
-- Do Nothing
|
|
||||||
end
|
|
||||||
function THREAD.kill() -- trigger the lane destruction
|
function THREAD.kill() -- trigger the lane destruction
|
||||||
-- coroutine.yield({"_kill_",":)"})
|
-- coroutine.yield({"_kill_",":)"})
|
||||||
end
|
end
|
||||||
--[[ Step 5 We need to get sleeping working so we need a lane to handle timing... We want idle wait not busy wait
|
--[[ Step 4 We need to get sleeping working to handle timing... We want idle wait, not busy wait
|
||||||
Idle wait keeps the CPU running better where busy wait wastes CPU cycles... Lanes does not have a sleep method
|
Idle wait keeps the CPU running better where busy wait wastes CPU cycles... Lanes does not have a sleep method
|
||||||
however, a linda recieve will in fact be a idle wait! So when wait is called we can pack the cmd up and send it to
|
however, a linda recieve will in fact be a idle wait! So we use that and wrap it in a nice package]]
|
||||||
the sleeping thread manager to send the variable for the other thread to consume, sending only after a certain time has passed!
|
|
||||||
]]
|
|
||||||
local function randomString(n)
|
|
||||||
local str = ''
|
|
||||||
local strings = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}
|
|
||||||
for i=1,n do
|
|
||||||
str = str..''..strings[math.random(1,#strings)]
|
|
||||||
end
|
|
||||||
return str
|
|
||||||
end
|
|
||||||
function THREAD.sleep(n)
|
function THREAD.sleep(n)
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
local randKey=randomString(12) -- generate a random string a-Z and 0-9
|
__SleepingLinda:receive(n,randomString(12))
|
||||||
__SleepingLinda:send("tired","SLEEP|"..randKey.."|"..tostring(n)) -- send the data that needs to be managed
|
|
||||||
local dat=__SleepingLinda:receive(randKey)
|
|
||||||
return dat
|
|
||||||
end
|
end
|
||||||
function THREAD.hold(n)
|
function THREAD.hold(n)
|
||||||
while not(n()) do
|
local function wait()
|
||||||
-- holding
|
math.randomseed(os.time())
|
||||||
|
__SleepingLinda:receive(.001,randomString(12))
|
||||||
end
|
end
|
||||||
|
repeat wait() until n()
|
||||||
end
|
end
|
||||||
-- start the time manager lane
|
-- Step 5 Basic Threads!
|
||||||
--~ lanes.gen("*", function()
|
|
||||||
--~ local timers={}
|
|
||||||
--~ while true do -- forever loop!
|
|
||||||
--~ local data=__SleepingLinda:receive(.001,"tired") -- timeout after .001 seconds and handle the other stuff
|
|
||||||
--~ if data then -- the .001 is an entarnal timer that keeps this thread from using too much CPU as well!
|
|
||||||
--~ print(data)
|
|
||||||
--~ local cmd,key,sec=data:match("(%S-)|(%S-)|(.+)")
|
|
||||||
--~ if cmd=="SLEEP" then
|
|
||||||
--~ print("GOT!")
|
|
||||||
--~ timers[#timers+1]={os.clock()+tonumber(sec),key}
|
|
||||||
--~ --__SleepingLinda:set()
|
|
||||||
--~ elseif cmd=="audit" then
|
|
||||||
--~ --
|
|
||||||
--~ end
|
|
||||||
--~ end
|
|
||||||
--~ for i=1,#timers do
|
|
||||||
--~ if os.clock()>=timers[i][1] then
|
|
||||||
--~ __SleepingLinda:send(timers[i][2],true)
|
|
||||||
--~ table.remove(timers,i)
|
|
||||||
--~ end
|
|
||||||
--~ end
|
|
||||||
--~ end
|
|
||||||
--~ end)() -- The global timer is now activated, and it works great!
|
|
||||||
-- Step 6 Basic Threads!
|
|
||||||
function multi:newSystemThread(name,func)
|
function multi:newSystemThread(name,func)
|
||||||
local c={}
|
local c={}
|
||||||
local __self=c
|
local __self=c
|
||||||
@@ -123,5 +97,9 @@ function multi:newSystemThread(name,func)
|
|||||||
end)
|
end)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
_G["GLOBAL"]=GLOBAL
|
print("Intergrated Lanes!")
|
||||||
_G["__GlobalLinda"]=__GlobalLinda
|
multi.intergration={} -- for module creators
|
||||||
|
multi.intergration.lanes={} -- for module creators
|
||||||
|
multi.intergration.lanes.GLOBAL=GLOBAL -- for module creators
|
||||||
|
multi.intergration.lanes.THREAD=THREAD -- for module creators
|
||||||
|
return {init=function() return GLOBAL,THREAD end}
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ function multi:newLoop(func)
|
|||||||
end
|
end
|
||||||
function c:Act()
|
function c:Act()
|
||||||
for i=1,#self.func do
|
for i=1,#self.func do
|
||||||
self.func[i](self.Parent.clock()-self.Start,self)
|
self.func[i](self,self.Parent.clock()-self.Start)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function c:OnLoop(func)
|
function c:OnLoop(func)
|
||||||
|
|||||||
+2
-2
@@ -35,7 +35,7 @@ function multi:newStep(start,reset,count,skip)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i=1,#self.func do
|
for i=1,#self.func do
|
||||||
self.func[i](self.pos,self)
|
self.func[i](self,self.pos)
|
||||||
end
|
end
|
||||||
self.pos=self.pos+self.count
|
self.pos=self.pos+self.count
|
||||||
if self.pos-self.count==self.endAt then
|
if self.pos-self.count==self.endAt then
|
||||||
@@ -74,4 +74,4 @@ function multi:newStep(start,reset,count,skip)
|
|||||||
end
|
end
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|||||||
+2
-2
@@ -42,7 +42,7 @@ function multi:newTStep(start,reset,count,set)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i=1,#self.func do
|
for i=1,#self.func do
|
||||||
self.func[i](self.pos,self)
|
self.func[i](self,self.pos)
|
||||||
end
|
end
|
||||||
self.pos=self.pos+self.count
|
self.pos=self.pos+self.count
|
||||||
if self.pos-self.count==self.endAt then
|
if self.pos-self.count==self.endAt then
|
||||||
@@ -73,4 +73,4 @@ function multi:newTStep(start,reset,count,set)
|
|||||||
end
|
end
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|||||||
+1
-1
@@ -19,4 +19,4 @@ function multi:newUpdater(skip)
|
|||||||
c.OnUpdate=self.OnMainConnect
|
c.OnUpdate=self.OnMainConnect
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package.path="?/init.lua;"..package.path
|
|
||||||
require("multi.all")
|
|
||||||
process=multi:newProcess() -- this can also load a file, to keep things really organized, I will show a simple example first then show the same thing being done within another file.
|
|
||||||
process:newTLoop(function(self)
|
|
||||||
print("Looping every second...")
|
|
||||||
end,1)
|
|
||||||
process:Start() -- starts the process
|
|
||||||
multi:mainloop() -- start the main runner
|
|
||||||
Reference in New Issue
Block a user