mirror of
https://github.com/rayaman/multi.git
synced 2026-09-05 07:27:35 -04:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
873e47d42b | ||
|
|
f8265fbb3b | ||
|
|
b995b1c0a7 | ||
|
|
66e922a971 | ||
|
|
92659c7eaf | ||
|
|
011ed53337 | ||
|
|
474ad6438f |
@@ -1,41 +1,32 @@
|
|||||||
name: Build & Run tests Ubuntu
|
name: Lua Unit Tests (Matrix)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ main ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
build-type: [Release] # Debug
|
luaVersion: ["5.1", "5.2", "5.3", "5.4", "luajit-2.1.0-beta3"]
|
||||||
lua: ["lua 5.1", "lua 5.2", "lua 5.3", "lua 5.4", "luajit 2.1.0-beta3"]
|
|
||||||
os: ["ubuntu-latest"]
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- name: Checkout repository
|
||||||
with:
|
uses: actions/checkout@v4
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- uses: actions/setup-python@v2
|
- name: Setup Lua
|
||||||
with:
|
uses: leafo/gh-actions-lua@v10
|
||||||
python-version: '3.10'
|
with:
|
||||||
|
luaVersion: ${{ matrix.luaVersion }}
|
||||||
|
|
||||||
- name: Setup env
|
- name: Verify Lua version
|
||||||
run: |
|
run: lua -v
|
||||||
pip install hererocks
|
|
||||||
hererocks lua-pkg --${{ matrix.lua }} -rlatest
|
|
||||||
|
|
||||||
- name: Install lanes and multi
|
- name: Run unit tests
|
||||||
run: |
|
run: |
|
||||||
source ${{github.workspace}}/lua-pkg/bin/activate
|
# Replace with your actual test file
|
||||||
luarocks install lanes
|
lua tests/multi_test.lua
|
||||||
luarocks install rockspecs/multi-16.0-0.rockspec
|
|
||||||
|
|
||||||
- name: Run Tests
|
|
||||||
run: |
|
|
||||||
source ${{github.workspace}}/lua-pkg/bin/activate
|
|
||||||
lua tests/runtests.lua
|
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
# Multi Version: 16.0.1 - Bug fix
|
# Multi Version: 16.1.0 - The Flow State
|
||||||
|
**Key Changes**
|
||||||
|
- Updated Processors to have more controlled over scheduled processes
|
||||||
|
- Forwarding connections
|
||||||
|
- New Timeout handling
|
||||||
|
|
||||||
|
Refer to the [Change Log](https://github.com/rayaman/multi/blob/master/docs/changes.md) for more infromation
|
||||||
|
|
||||||
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
|
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
|
||||||
|
|
||||||
@@ -6,7 +12,7 @@ My multitasking library for lua. It is a pure lua binding, with exceptions of th
|
|||||||
|
|
||||||
</br>
|
</br>
|
||||||
|
|
||||||
Progress is being made in [v16.1.0](https://github.com/rayaman/multi/tree/v16.1.0)
|
Progress is being made in [v16.2.0](https://github.com/rayaman/multi/tree/v16.2.0)
|
||||||
---
|
---
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
@@ -45,7 +51,7 @@ Planned features/TODO
|
|||||||
- [x] ~~Create test suite (In progress, mostly done)~~
|
- [x] ~~Create test suite (In progress, mostly done)~~
|
||||||
- [ ] Network Parallelism rework
|
- [ ] Network Parallelism rework
|
||||||
|
|
||||||
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/Documentation.md)
|
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/docs/Documentation.md)
|
||||||
-----
|
-----
|
||||||
|
|
||||||
You can run tests in 2 ways:
|
You can run tests in 2 ways:
|
||||||
|
|||||||
+143
-3
@@ -1,7 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
Table of contents
|
Table of contents
|
||||||
---
|
---
|
||||||
[Update 16.0.1 - Bug fix](#update-1531---bug-fix)</br>
|
[Update 16.2.0 - TimeStamps and UUIDs](#update-1620---timestamps-and-uuids-and-bugfixes)</br>
|
||||||
|
[Update 16.1.0 - The Flow State](#update-1610---the-flow-state)</br>
|
||||||
|
[Update 16.0.1 - Bug fix](#update-1601---bug-fix)</br>
|
||||||
[Update 16.0.0 - Connecting the dots](#update-1600---getting-the-priorities-straight)</br>
|
[Update 16.0.0 - Connecting the dots](#update-1600---getting-the-priorities-straight)</br>
|
||||||
[Update 15.3.1 - Bug fix](#update-1531---bug-fix)</br>
|
[Update 15.3.1 - Bug fix](#update-1531---bug-fix)</br>
|
||||||
[Update 15.3.0 - A world of connections](#update-1530---a-world-of-connections)</br>
|
[Update 15.3.0 - A world of connections](#update-1530---a-world-of-connections)</br>
|
||||||
@@ -59,6 +61,142 @@ Table of contents
|
|||||||
[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</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)
|
[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different)
|
||||||
|
|
||||||
|
# Update 16.2.0 - TimeStamps and UUIDs and bugfixes
|
||||||
|
Added
|
||||||
|
---
|
||||||
|
- threadedfunctions, multiobjs and threads contain new method: `GetCreationTimestamp()` With will return a string formated date time using ISO 8601
|
||||||
|
|
||||||
|
Changed
|
||||||
|
---
|
||||||
|
- Internal uuid functions to not use bitwise operators
|
||||||
|
|
||||||
|
Fixed
|
||||||
|
---
|
||||||
|
- [Bitwise operations break lua 5.1/luajit](https://github.com/rayaman/multi/issues/73)
|
||||||
|
|
||||||
|
# Update 16.1.0 - The Flow State
|
||||||
|
Added
|
||||||
|
---
|
||||||
|
- `multi.UUID()` generates a uuid7, if chronos is installed that will be used as the initial time seed
|
||||||
|
- `More control over processors`
|
||||||
|
- `multi:newProcessor(name, opts, priority)` -- Now accepts a opts table. Old param still works
|
||||||
|
|
||||||
|
| Option | Description | Default |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Attach | If true a hook will be attached to the parent process and will run when Start is called or Start is set | false |
|
||||||
|
| MaxObjects | Maximum number of objects that a processor can spawn | -1 (disabled) |
|
||||||
|
| MaxThreads | Maximum number of threads that a processor can spawn | -1 (disabled) |
|
||||||
|
| Start | If true the processor will start instantlly | false |
|
||||||
|
| Priority | If true the processor will use the priority handler | false |
|
||||||
|
| TaskDelay | Sets the task delay in seconds between each tasks execution | 0 |
|
||||||
|
| TashHandler | If false will disable the task feature of a processor | true |
|
||||||
|
- `proc:newThread()` returns nil, "errorstring" if it was unable to create a thread
|
||||||
|
- `proc:new[Object]` now returns {unscheduled}, "errorstring", used to just return the {scheduledObject} and no errorstring
|
||||||
|
- `proc:getMaxThreads()` -- returns the max thread limit
|
||||||
|
- `proc:setMaxThreads(n)` -- sets the max thread limit
|
||||||
|
- `proc:getMaxObjects()` -- gets the max object limit
|
||||||
|
- `proc:setMaxObjects(n)` -- sets the max object limit
|
||||||
|
- `proc.Status` -- A table that contains all status errors that occured in a process
|
||||||
|
Example:
|
||||||
|
```lua
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
|
||||||
|
proc = multi:newProcessor("thread test",{
|
||||||
|
Start = true,
|
||||||
|
MaxThreads = 1,
|
||||||
|
MaxObjects = 1,
|
||||||
|
Attach = true,
|
||||||
|
TaskDelay = .1,
|
||||||
|
Priority = true,
|
||||||
|
TaskHandler = false
|
||||||
|
})
|
||||||
|
|
||||||
|
print(proc:newThread("testing",function()
|
||||||
|
while true do
|
||||||
|
print("STATUS:\n---")
|
||||||
|
for i,v in ipairs(proc.Status) do
|
||||||
|
print(i,v)
|
||||||
|
end
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end))
|
||||||
|
proc:newThread("testing 2",function()
|
||||||
|
while true do
|
||||||
|
print("testing 2...")
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
proc:newThread("testing 3",function()
|
||||||
|
while true do
|
||||||
|
print("testing 3...")
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
proc:newLoop(function()
|
||||||
|
--
|
||||||
|
end)
|
||||||
|
|
||||||
|
print(proc:newLoop(function()
|
||||||
|
--
|
||||||
|
end))
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
- `multi.hasType(typ)` returns true if a type has been registered
|
||||||
|
- `multi.isMultiObj(obj)` returns true if the object is a multi object
|
||||||
|
- `multi.forwardConnection(src, dest)` forwards events from one connection to another connection. Doesn't modify anything and both connections are triggered when src is Fired, but not when dest is fired.
|
||||||
|
- `multi.isTimeout(res)` returns true if the response it gets is a timeout type or a string equal to `multi.TIMEOUT`'s value
|
||||||
|
- `multi:newTimeout(seconds)` returns a connection that will trigger after a certain amount of time. See example below:
|
||||||
|
```lua
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
|
||||||
|
data = multi:newConnection()
|
||||||
|
|
||||||
|
-- This alarm takes too long... We will timeout
|
||||||
|
multi:newAlarm(4):OnRing(function()
|
||||||
|
data:Fire({Type="request"},"data is tasty")
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:newThread(function()
|
||||||
|
res, data = thread.hold(data + multi:newTimeout(3)) -- combined connections allow this to work
|
||||||
|
if multi.isTimeout(res) then
|
||||||
|
print("We timed out!")
|
||||||
|
else
|
||||||
|
print("We got the data:", data)
|
||||||
|
end
|
||||||
|
os.exit()
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
- `connection % function` can now modify the arguments of a connection. See above example modified below
|
||||||
|
```lua
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
|
||||||
|
local data = multi:newAlarm(1).OnRing % function() return {Type="request"}, "data is tasty" end
|
||||||
|
|
||||||
|
multi:newThread(function()
|
||||||
|
res, data = thread.hold(data + multi:newTimeout(3))
|
||||||
|
if multi.isTimeout(res) then
|
||||||
|
print("We timed out!")
|
||||||
|
else
|
||||||
|
print("We got the data:", data)
|
||||||
|
end
|
||||||
|
os.exit()
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
|
||||||
|
If the alarm takes longer the the timeout: `We timed out!` If the alarm is shorter: `We got the data: data is tasty`
|
||||||
|
|
||||||
|
Changed
|
||||||
|
---
|
||||||
|
- `multi:newBase(tp,ins,callback)` now accepts a tp param and a callback function. Callback is expected to return true/false, errorstring. If callback is false it will cancel scheduling of an object. If type is set the type of the object will be set.
|
||||||
|
|
||||||
|
**Note:** This is all internal functionality
|
||||||
|
|
||||||
# Update 16.0.1 - Bug fix
|
# Update 16.0.1 - Bug fix
|
||||||
Fixed
|
Fixed
|
||||||
---
|
---
|
||||||
@@ -491,13 +629,15 @@ Added
|
|||||||
|
|
||||||
Output:
|
Output:
|
||||||
```
|
```
|
||||||
I run before all and control if things go!
|
I run before all and control if execution should continue!
|
||||||
Hi 3
|
Hi 3
|
||||||
Hi 1
|
Hi 1
|
||||||
|
I run before all and control if execution should continue!
|
||||||
|
Hi 3
|
||||||
|
Hi 2
|
||||||
Test 1
|
Test 1
|
||||||
Test 2
|
Test 2
|
||||||
Test 3
|
Test 3
|
||||||
I run after it all!
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note:** Concat of connections does modify internal events on both connections depending on the direction func .. conn or conn .. func See implemention below:
|
**Note:** Concat of connections does modify internal events on both connections depending on the direction func .. conn or conn .. func See implemention below:
|
||||||
|
|||||||
@@ -76,17 +76,23 @@ end
|
|||||||
|
|
||||||
local types = {}
|
local types = {}
|
||||||
function multi.registerType(typ, p)
|
function multi.registerType(typ, p)
|
||||||
if multi[typ:upper():gsub("_","")] then return typ end
|
if multi["$"..typ:upper():gsub("_","")] then return typ end
|
||||||
multi[typ:upper():gsub("_","")] = typ
|
multi["$"..typ:upper():gsub("_","")] = typ
|
||||||
table.insert(types, {typ, p or typ})
|
table.insert(types, {typ, p or typ})
|
||||||
return typ
|
return typ
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function multi.hasType(typ)
|
||||||
|
if multi["$"..typ:upper():gsub("_","")] then
|
||||||
|
return multi["$"..typ:upper():gsub("_","")]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function multi.getTypes()
|
function multi.getTypes()
|
||||||
return types
|
return types
|
||||||
end
|
end
|
||||||
|
|
||||||
multi.Version = "16.0.1"
|
multi.Version = "16.2.0"
|
||||||
multi.Name = "root"
|
multi.Name = "root"
|
||||||
multi.NIL = {Type="NIL"}
|
multi.NIL = {Type="NIL"}
|
||||||
local NIL = multi.NIL
|
local NIL = multi.NIL
|
||||||
@@ -95,7 +101,7 @@ multi.Children = {}
|
|||||||
multi.Active = true
|
multi.Active = true
|
||||||
multi.Type = multi.registerType("rootprocess")
|
multi.Type = multi.registerType("rootprocess")
|
||||||
multi.LinkedPath = multi
|
multi.LinkedPath = multi
|
||||||
multi.TIMEOUT = "TIMEOUT"
|
multi.TIMEOUT = multi.registerType("TIMEOUT", "timeouts")
|
||||||
multi.TID = 0
|
multi.TID = 0
|
||||||
multi.defaultSettings = {}
|
multi.defaultSettings = {}
|
||||||
|
|
||||||
@@ -185,9 +191,29 @@ function multi.randomString(n)
|
|||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function multi.isMulitObj(obj)
|
||||||
|
if type(obj)=="table" then
|
||||||
|
if obj.Type ~= nil then
|
||||||
|
return multi.hasType(obj.Type) ~= nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function multi.forwardConnection(src, dest)
|
||||||
|
if multi.isMulitObj(src) and multi.isMulitObj(dest) then
|
||||||
|
src(function(...)
|
||||||
|
dest:Fire(...)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
multi.error("Cannot forward non-connection objects")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local optimization_stats = {}
|
local optimization_stats = {}
|
||||||
local ignoreconn = true
|
local ignoreconn = true
|
||||||
local empty_func = function() end
|
local empty_func = function() end
|
||||||
|
|
||||||
function multi:newConnection(protect,func,kill)
|
function multi:newConnection(protect,func,kill)
|
||||||
local processor = self
|
local processor = self
|
||||||
local c={}
|
local c={}
|
||||||
@@ -221,6 +247,7 @@ function multi:newConnection(protect,func,kill)
|
|||||||
for i = #conns, 1, -1 do
|
for i = #conns, 1, -1 do
|
||||||
obj.rawadd = true
|
obj.rawadd = true
|
||||||
obj(conns[i])
|
obj(conns[i])
|
||||||
|
obj.rawadd = false
|
||||||
end
|
end
|
||||||
return obj
|
return obj
|
||||||
end,
|
end,
|
||||||
@@ -230,6 +257,22 @@ function multi:newConnection(protect,func,kill)
|
|||||||
obj2(function(...)
|
obj2(function(...)
|
||||||
cn:Fire(obj1(...))
|
cn:Fire(obj1(...))
|
||||||
end)
|
end)
|
||||||
|
elseif type(obj1) == "table" and type(obj2) == "function" then
|
||||||
|
local conns = obj1:Bind({})
|
||||||
|
for i = 1,#conns do
|
||||||
|
obj1(function(...)
|
||||||
|
conns[i](obj2(...))
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
obj1.__connectionAdded = function(conn, func)
|
||||||
|
obj1:Unconnect(conn)
|
||||||
|
obj1.rawadd = true
|
||||||
|
obj1:Connect(function(...)
|
||||||
|
func(obj2(...))
|
||||||
|
end)
|
||||||
|
obj1.rawadd = false
|
||||||
|
end
|
||||||
|
return obj1
|
||||||
else
|
else
|
||||||
error("Invalid mod!", type(obj1), type(obj2),"Expected function, connection(table)")
|
error("Invalid mod!", type(obj1), type(obj2),"Expected function, connection(table)")
|
||||||
end
|
end
|
||||||
@@ -277,6 +320,7 @@ function multi:newConnection(protect,func,kill)
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
return obj1
|
||||||
elseif type(obj1) == "table" and type(obj2) == "table" then
|
elseif type(obj1) == "table" and type(obj2) == "table" then
|
||||||
--
|
--
|
||||||
else
|
else
|
||||||
@@ -492,6 +536,10 @@ function multi:newConnection(protect,func,kill)
|
|||||||
return temp
|
return temp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function c:Get()
|
||||||
|
return fast
|
||||||
|
end
|
||||||
|
|
||||||
function c:Remove()
|
function c:Remove()
|
||||||
local temp = fast
|
local temp = fast
|
||||||
fast={}
|
fast={}
|
||||||
@@ -554,8 +602,7 @@ end
|
|||||||
-- Advance Timer stuff
|
-- Advance Timer stuff
|
||||||
function multi:SetTime(n)
|
function multi:SetTime(n)
|
||||||
if not n then n=3 end
|
if not n then n=3 end
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("timemaster"))
|
||||||
c.Type=multi.registerType("timemaster")
|
|
||||||
c.timer=self:newTimer()
|
c.timer=self:newTimer()
|
||||||
c.timer:Start()
|
c.timer:Start()
|
||||||
c.set=n
|
c.set=n
|
||||||
@@ -571,7 +618,7 @@ function multi:SetTime(n)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self
|
return self,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:ResolveTimer(...)
|
function multi:ResolveTimer(...)
|
||||||
@@ -651,12 +698,25 @@ function multi:isDone()
|
|||||||
return self.Active~=true
|
return self.Active~=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local time = os.time
|
||||||
|
local ok, chronos = pcall(require, "chronos") -- hpc
|
||||||
|
|
||||||
|
if ok then
|
||||||
|
math.randomseed(chronos.nanotime()*100000000)
|
||||||
|
else
|
||||||
|
math.randomseed(time())
|
||||||
|
end
|
||||||
|
|
||||||
function multi:create(ref)
|
function multi:create(ref)
|
||||||
ref.UID = "U"..multi.randomString(12)
|
ref.UID = multi.generate_uuid7()
|
||||||
self.OnObjectCreated:Fire(ref, self)
|
self.OnObjectCreated:Fire(ref, self)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function multi:GetCreationTimestamp()
|
||||||
|
return multi.extract_uuid7_timestamp(self.UID).iso8601
|
||||||
|
end
|
||||||
|
|
||||||
function multi:setName(name)
|
function multi:setName(name)
|
||||||
self.Name = name
|
self.Name = name
|
||||||
return self
|
return self
|
||||||
@@ -664,7 +724,7 @@ end
|
|||||||
|
|
||||||
--Constructors [CORE]
|
--Constructors [CORE]
|
||||||
local _tid = 0
|
local _tid = 0
|
||||||
function multi:newBase(ins)
|
function multi:newBase(tp,ins,callback)
|
||||||
if not(self.Type==multi.registerType("rootprocess") or self.Type==multi.registerType("process", "processes")) then multi.error('Can only create an object on multi or an interface obj') return false end
|
if not(self.Type==multi.registerType("rootprocess") or self.Type==multi.registerType("process", "processes")) then multi.error('Can only create an object on multi or an interface obj') return false end
|
||||||
local c = {}
|
local c = {}
|
||||||
if self.Type==multi.registerType("process", "processes") then
|
if self.Type==multi.registerType("process", "processes") then
|
||||||
@@ -682,6 +742,7 @@ function multi:newBase(ins)
|
|||||||
c.Act=function() end
|
c.Act=function() end
|
||||||
c.Parent=self
|
c.Parent=self
|
||||||
c.creationTime = clock()
|
c.creationTime = clock()
|
||||||
|
c.Type = tp
|
||||||
|
|
||||||
function c:Pause()
|
function c:Pause()
|
||||||
c.Parent.Pause(self)
|
c.Parent.Pause(self)
|
||||||
@@ -693,15 +754,29 @@ function multi:newBase(ins)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_tid = _tid + 1 -- Even if the task isn't scheduled, we want to increment this
|
||||||
|
|
||||||
|
if type(callback) == "function" then
|
||||||
|
local res, err = callback(tp)
|
||||||
|
if not res then
|
||||||
|
return c, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if ins then
|
if ins then
|
||||||
table.insert(self.Mainloop,ins,c)
|
table.insert(self.Mainloop,ins,c)
|
||||||
else
|
else
|
||||||
table.insert(self.Mainloop,c)
|
table.insert(self.Mainloop,c)
|
||||||
end
|
end
|
||||||
_tid = _tid + 1
|
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function multi:newTimeout(timeout)
|
||||||
|
local c={}
|
||||||
|
c.Type = multi.registerType(multi.TIMEOUT, "timeouts")
|
||||||
|
return function(self) self:Destroy() return c end % self:newAlarm(timeout).OnRing
|
||||||
|
end
|
||||||
|
|
||||||
function multi:newTimer()
|
function multi:newTimer()
|
||||||
local c={}
|
local c={}
|
||||||
c.Type=multi.registerType("timer", "timers")
|
c.Type=multi.registerType("timer", "timers")
|
||||||
@@ -736,8 +811,7 @@ end
|
|||||||
|
|
||||||
--Core Actors
|
--Core Actors
|
||||||
function multi:newEvent(task, func)
|
function multi:newEvent(task, func)
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("event", "events"))
|
||||||
c.Type=multi.registerType("event", "events")
|
|
||||||
local task = task or function() end
|
local task = task or function() end
|
||||||
function c:Act()
|
function c:Act()
|
||||||
local t = task(self)
|
local t = task(self)
|
||||||
@@ -759,12 +833,11 @@ function multi:newEvent(task, func)
|
|||||||
self:setPriority("core")
|
self:setPriority("core")
|
||||||
c:setName(c.Type)
|
c:setName(c.Type)
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newUpdater(skip, func)
|
function multi:newUpdater(skip, func)
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("updater", "updaters"))
|
||||||
c.Type=multi.registerType("updater", "updaters")
|
|
||||||
local pos = 1
|
local pos = 1
|
||||||
local skip = skip or 1
|
local skip = skip or 1
|
||||||
function c:Act()
|
function c:Act()
|
||||||
@@ -785,12 +858,11 @@ function multi:newUpdater(skip, func)
|
|||||||
c.OnUpdate(func)
|
c.OnUpdate(func)
|
||||||
end
|
end
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newAlarm(set, func)
|
function multi:newAlarm(set, func)
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("alarm", "alarms"))
|
||||||
c.Type=multi.registerType("alarm", "alarms")
|
|
||||||
c:setPriority("Low")
|
c:setPriority("Low")
|
||||||
c.set=set or 0
|
c.set=set or 0
|
||||||
local count = 0
|
local count = 0
|
||||||
@@ -826,12 +898,11 @@ function multi:newAlarm(set, func)
|
|||||||
end
|
end
|
||||||
c:setName(c.Type)
|
c:setName(c.Type)
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newLoop(func, notime)
|
function multi:newLoop(func, notime)
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("loop", "loops"))
|
||||||
c.Type = multi.registerType("loop", "loops")
|
|
||||||
local start=clock()
|
local start=clock()
|
||||||
if notime then
|
if notime then
|
||||||
function c:Act()
|
function c:Act()
|
||||||
@@ -853,13 +924,12 @@ function multi:newLoop(func, notime)
|
|||||||
|
|
||||||
self:create(c)
|
self:create(c)
|
||||||
c:setName(c.Type)
|
c:setName(c.Type)
|
||||||
return c
|
return c,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newStep(start,reset,count,skip)
|
function multi:newStep(start,reset,count,skip)
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("step", "steps"))
|
||||||
think=1
|
think=1
|
||||||
c.Type=multi.registerType("step", "steps")
|
|
||||||
c.pos=start or 1
|
c.pos=start or 1
|
||||||
c.endAt=reset or math.huge
|
c.endAt=reset or math.huge
|
||||||
c.skip=skip or 0
|
c.skip=skip or 0
|
||||||
@@ -913,12 +983,11 @@ function multi:newStep(start,reset,count,skip)
|
|||||||
end
|
end
|
||||||
c:setName(c.Type)
|
c:setName(c.Type)
|
||||||
self:create(c)
|
self:create(c)
|
||||||
return c
|
return c,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newTLoop(func, set)
|
function multi:newTLoop(func, set)
|
||||||
local c=self:newBase()
|
local c,err=self:newBase(multi.registerType("tloop", "tloops"))
|
||||||
c.Type=multi.registerType("tloop", "tloops")
|
|
||||||
c.set=set or 0
|
c.set=set or 0
|
||||||
c.timer=self:newTimer()
|
c.timer=self:newTimer()
|
||||||
c.life=0
|
c.life=0
|
||||||
@@ -959,7 +1028,7 @@ function multi:newTLoop(func, set)
|
|||||||
|
|
||||||
self:create(c)
|
self:create(c)
|
||||||
|
|
||||||
return c
|
return c,err
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:setTimeout(func, t)
|
function multi:setTimeout(func, t)
|
||||||
@@ -1079,10 +1148,38 @@ end
|
|||||||
|
|
||||||
local sandcount = 1
|
local sandcount = 1
|
||||||
|
|
||||||
function multi:newProcessor(name, nothread, priority)
|
function multi:newProcessor(name, opts, priority)
|
||||||
|
local nothread, attach
|
||||||
|
if type(opts) ~= "table" then
|
||||||
|
attach = not opts
|
||||||
|
nothread = opts -- support old params
|
||||||
|
end
|
||||||
local c = {}
|
local c = {}
|
||||||
|
c.Status = {}
|
||||||
setmetatable(c,{__index = multi})
|
setmetatable(c,{__index = multi})
|
||||||
local name = name or "Processor_" .. sandcount
|
local name = name or "Processor_" .. sandcount
|
||||||
|
local maxThreads = -1
|
||||||
|
local maxObjects = -1
|
||||||
|
local taskhandler = true
|
||||||
|
|
||||||
|
rootBase = multi.newBase
|
||||||
|
|
||||||
|
local function setStatus(status)
|
||||||
|
table.insert(c.Status,status)
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
|
||||||
|
local callback = function(tp)
|
||||||
|
if maxObjects <0 or #c.Mainloop < maxObjects then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false, setStatus(string.format("Unable to create [%s]: MAX_OBJECTS: '%d' current scheduled objects: '%d'", tp, maxObjects, #c.Mainloop))
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:newBase(tp,ins)
|
||||||
|
return rootBase(self,tp,ins,callback)
|
||||||
|
end
|
||||||
|
|
||||||
sandcount = sandcount + 1
|
sandcount = sandcount + 1
|
||||||
c.Mainloop = {}
|
c.Mainloop = {}
|
||||||
c.Type = multi.registerType("process", "processes")
|
c.Type = multi.registerType("process", "processes")
|
||||||
@@ -1098,13 +1195,25 @@ function multi:newProcessor(name, nothread, priority)
|
|||||||
local boost = 1
|
local boost = 1
|
||||||
local handler
|
local handler
|
||||||
|
|
||||||
|
if type(opts) == "table" then
|
||||||
|
priority = opts.Priority or false
|
||||||
|
Active = opts.Start or false
|
||||||
|
maxThreads = opts.MaxThreads or -1
|
||||||
|
maxObjects = opts.MaxObjects or -1
|
||||||
|
task_delay = opts.TaskDelay or 0
|
||||||
|
attach = opts.Attach or false
|
||||||
|
if opts.TaskHandler == false then -- The default was true
|
||||||
|
taskhandler = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if priority then
|
if priority then
|
||||||
handler = c:createPriorityHandler(c)
|
handler = c:createPriorityHandler(c)
|
||||||
else
|
else
|
||||||
handler = c:createHandler(c)
|
handler = c:createHandler(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not nothread then -- Don't create a loop if we are triggering this manually
|
if attach then -- Don't create a loop if we are triggering this manually
|
||||||
c.process = self:newLoop(function()
|
c.process = self:newLoop(function()
|
||||||
if Active then
|
if Active then
|
||||||
c:uManager(true)
|
c:uManager(true)
|
||||||
@@ -1138,7 +1247,10 @@ function multi:newProcessor(name, nothread, priority)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function c:newThread(name, func,...)
|
function c:newThread(name, func,...)
|
||||||
return thread.newThread(c, name, func, ...)
|
if maxThreads < 0 or (#c.threads+#c.startme < maxThreads) then
|
||||||
|
return thread.newThread(c, name, func, ...)
|
||||||
|
end
|
||||||
|
return nil, setStatus(string.format("Unable to create [thread]: '%s' MAX_THREADS: '%d' current scheduled threads: '%d'",name,maxThreads,#c.threads+#c.startme))
|
||||||
end
|
end
|
||||||
|
|
||||||
function c:newFunction(func, holdme)
|
function c:newFunction(func, holdme)
|
||||||
@@ -1147,6 +1259,24 @@ function multi:newProcessor(name, nothread, priority)
|
|||||||
end, holdme)()
|
end, holdme)()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function c:getMaxThreads()
|
||||||
|
return maxThreads
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:setMaxThreads(n)
|
||||||
|
maxThreads = n
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:getMaxObjects()
|
||||||
|
return maxObjects
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:setMaxObjects(n)
|
||||||
|
maxObjects = n
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
|
||||||
function c:boost(count)
|
function c:boost(count)
|
||||||
boost = count or 1
|
boost = count or 1
|
||||||
if boost > 1 then
|
if boost > 1 then
|
||||||
@@ -1202,22 +1332,24 @@ function multi:newProcessor(name, nothread, priority)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
c:newThread("Task Handler", function()
|
if taskhandler then
|
||||||
local self = multi:getCurrentProcess()
|
c:newThread("Task Handler", function()
|
||||||
local function task_holder()
|
local self = multi:getCurrentProcess()
|
||||||
return #self.tasks > 0
|
local function task_holder()
|
||||||
end
|
return #self.tasks > 0
|
||||||
while true do
|
|
||||||
if #self.tasks > 0 then
|
|
||||||
table.remove(self.tasks,1)()
|
|
||||||
else
|
|
||||||
thread.hold(task_holder)
|
|
||||||
end
|
end
|
||||||
if task_delay~=0 then
|
while true do
|
||||||
thread.hold(task_delay)
|
if #self.tasks > 0 then
|
||||||
|
table.remove(self.tasks,1)()
|
||||||
|
else
|
||||||
|
thread.hold(task_holder)
|
||||||
|
end
|
||||||
|
if task_delay~=0 then
|
||||||
|
thread.hold(task_delay)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end).OnError(multi.error)
|
||||||
end).OnError(multi.error)
|
end
|
||||||
|
|
||||||
table.insert(processes,c)
|
table.insert(processes,c)
|
||||||
self:create(c)
|
self:create(c)
|
||||||
@@ -1442,7 +1574,10 @@ end
|
|||||||
|
|
||||||
function thread:newFunctionBase(generator, holdme, TYPE)
|
function thread:newFunctionBase(generator, holdme, TYPE)
|
||||||
return function()
|
return function()
|
||||||
local tfunc = {}
|
local UID = multi.generate_uuid7()
|
||||||
|
local tfunc = {
|
||||||
|
GetCreationTimestamp = function() return multi.extract_uuid7_timestamp(UID).iso8601 end,
|
||||||
|
}
|
||||||
tfunc.Active = true
|
tfunc.Active = true
|
||||||
function tfunc:Pause()
|
function tfunc:Pause()
|
||||||
self.Active = false
|
self.Active = false
|
||||||
@@ -1650,6 +1785,10 @@ function thread:newThread(name, func, ...)
|
|||||||
return self._isPaused
|
return self._isPaused
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function c:GetCreationTimestamp()
|
||||||
|
return multi.extract_uuid7_timestamp(self.UID).iso8601
|
||||||
|
end
|
||||||
|
|
||||||
local resumed = false
|
local resumed = false
|
||||||
function c:Pause()
|
function c:Pause()
|
||||||
if not self._isPaused then
|
if not self._isPaused then
|
||||||
@@ -2228,6 +2367,13 @@ end
|
|||||||
-- UTILS
|
-- UTILS
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
function multi.isTimeout(res)
|
||||||
|
if type(res) == "table" then
|
||||||
|
return res.Type == multi.TIMEOUT
|
||||||
|
end
|
||||||
|
return res == multi.TIMEOUT
|
||||||
|
end
|
||||||
|
|
||||||
function table.merge(t1, t2)
|
function table.merge(t1, t2)
|
||||||
for k,v in pairs(t2) do
|
for k,v in pairs(t2) do
|
||||||
if type(v) == 'table' then
|
if type(v) == 'table' then
|
||||||
@@ -2510,6 +2656,144 @@ function multi.success(...)
|
|||||||
io.write("\x1b[92mSUCCESS:\x1b[0m " .. table.concat(t," ") .. "\n")
|
io.write("\x1b[92mSUCCESS:\x1b[0m " .. table.concat(t," ") .. "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- UUID Handling
|
||||||
|
local function get_timestamp_ms()
|
||||||
|
-- os.time() gives seconds, we need milliseconds
|
||||||
|
-- For sub-second precision, we'd need a C extension in real use
|
||||||
|
-- Here we'll use seconds * 1000 + a pseudo-random millisecond component
|
||||||
|
local sec = os.time()
|
||||||
|
return sec * 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert number to hex string with specified length
|
||||||
|
local function to_hex(num, len)
|
||||||
|
local hex = string.format("%x", num)
|
||||||
|
return string.rep("0", len - #hex) .. hex
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate random hex string of specified length
|
||||||
|
local function random_hex(len)
|
||||||
|
local result = ""
|
||||||
|
for i = 1, len do
|
||||||
|
result = result .. string.format("%x", math.random(0, 15))
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
multi.generate_uuid7 = function()
|
||||||
|
-- Seed random number generator with current time
|
||||||
|
math.randomseed(os.time() * os.clock() * 1000000)
|
||||||
|
|
||||||
|
-- Get timestamp in milliseconds
|
||||||
|
local timestamp_ms = get_timestamp_ms()
|
||||||
|
|
||||||
|
-- Convert timestamp to 12 hex characters (48 bits)
|
||||||
|
-- Split into high and low parts
|
||||||
|
local high = math.floor(timestamp_ms / 16777216) -- Upper 24 bits
|
||||||
|
local low = timestamp_ms % 16777216 -- Lower 24 bits
|
||||||
|
|
||||||
|
local time_high = to_hex(high, 6)
|
||||||
|
local time_low = to_hex(low, 6)
|
||||||
|
|
||||||
|
-- Version and random bits (4 bits version + 12 bits random = 16 bits = 4 hex)
|
||||||
|
local ver_rand = random_hex(3)
|
||||||
|
local version_field = "7" .. ver_rand -- Version 7
|
||||||
|
|
||||||
|
-- Variant and random bits (2 bits variant + 14 bits random = 16 bits = 4 hex)
|
||||||
|
local rand_val = math.random(0, 16383) -- 14 bits of random
|
||||||
|
local variant_field = to_hex(0x8000 + rand_val, 4) -- Set variant bits to 10
|
||||||
|
|
||||||
|
-- Remaining random bits (48 bits = 12 hex)
|
||||||
|
local random_field = random_hex(12)
|
||||||
|
|
||||||
|
-- Assemble UUID: xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx
|
||||||
|
local uuid = string.format("%s%s-%s-%s-%s-%s",
|
||||||
|
time_high:sub(1, 2),
|
||||||
|
time_high:sub(3, 6) .. time_low:sub(1, 2),
|
||||||
|
time_low:sub(3, 6),
|
||||||
|
version_field,
|
||||||
|
variant_field,
|
||||||
|
random_field
|
||||||
|
)
|
||||||
|
return uuid
|
||||||
|
end
|
||||||
|
|
||||||
|
local function is_leap(y)
|
||||||
|
return (y % 4 == 0 and y % 100 ~= 0) or (y % 400 == 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function format_date(seconds)
|
||||||
|
local days = math.floor(seconds / 86400)
|
||||||
|
local remainder = seconds % 86400
|
||||||
|
local hours = math.floor(remainder / 3600)
|
||||||
|
remainder = remainder % 3600
|
||||||
|
local minutes = math.floor(remainder / 60)
|
||||||
|
local secs = remainder % 60
|
||||||
|
|
||||||
|
-- Calculate year, month, day from days since epoch (1970-01-01)
|
||||||
|
local year = 1970
|
||||||
|
local month = 1
|
||||||
|
local day = 1 + days
|
||||||
|
|
||||||
|
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local days_in_year = is_leap(year) and 366 or 365
|
||||||
|
if day <= days_in_year then break end
|
||||||
|
day = day - days_in_year
|
||||||
|
year = year + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
local dim = days_in_month[month]
|
||||||
|
if month == 2 and is_leap(year) then dim = 29 end
|
||||||
|
if day <= dim then break end
|
||||||
|
day = day - dim
|
||||||
|
month = month + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return string.format("%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
|
year, month, day, hours, minutes, secs)
|
||||||
|
end
|
||||||
|
|
||||||
|
multi.extract_uuid7_timestamp = function(uuid_str)
|
||||||
|
-- Remove hyphens from UUID
|
||||||
|
local hex = uuid_str:gsub("-", "")
|
||||||
|
|
||||||
|
-- Validate length
|
||||||
|
if #hex ~= 32 then
|
||||||
|
return nil, "Invalid UUID length"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Extract first 12 hex characters (48 bits = timestamp in ms)
|
||||||
|
local timestamp_hex = hex:sub(1, 12)
|
||||||
|
|
||||||
|
-- Convert hex to decimal - need to handle large numbers
|
||||||
|
-- Break into two parts to avoid overflow
|
||||||
|
local high = tonumber(timestamp_hex:sub(1, 6), 16)
|
||||||
|
local low = tonumber(timestamp_hex:sub(7, 12), 16)
|
||||||
|
local timestamp_ms = high * 16777216 + low -- 16^6 = 16777216
|
||||||
|
|
||||||
|
if not timestamp_ms then
|
||||||
|
return nil, "Failed to parse timestamp"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert milliseconds to seconds
|
||||||
|
local timestamp_sec = math.floor(timestamp_ms / 1000)
|
||||||
|
local ms_remainder = timestamp_ms % 1000
|
||||||
|
|
||||||
|
-- Manual date calculation for large timestamps
|
||||||
|
|
||||||
|
local date_str = format_date(timestamp_sec)
|
||||||
|
|
||||||
|
return {
|
||||||
|
milliseconds = timestamp_ms,
|
||||||
|
seconds = timestamp_sec,
|
||||||
|
date = date_str,
|
||||||
|
iso8601 = date_str:gsub(" ", "T") .. string.format(".%03dZ", ms_remainder)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
-- Old things for compatability
|
-- Old things for compatability
|
||||||
multi.GetType = multi.getType
|
multi.GetType = multi.getType
|
||||||
multi.IsPaused = multi.isPaused
|
multi.IsPaused = multi.isPaused
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
-- Allows the creation of states
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package = "multi"
|
||||||
|
version = "16.1-0"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/rayaman/multi.git",
|
||||||
|
tag = "v16.1.0",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Lua Multi tasking library",
|
||||||
|
detailed = [[
|
||||||
|
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
|
||||||
|
Check github for documentation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/rayaman/multi",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["multi"] = "init.lua",
|
||||||
|
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
|
||||||
|
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
|
||||||
|
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
|
||||||
|
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
|
||||||
|
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
|
||||||
|
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
|
||||||
|
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
|
||||||
|
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
|
||||||
|
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
|
||||||
|
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
|
||||||
|
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
|
||||||
|
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
|
||||||
|
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
|
||||||
|
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
|
||||||
|
["multi.integration.threading"] = "integration/threading.lua",
|
||||||
|
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
|
||||||
|
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
|
||||||
|
--["multi.integration.networkManager"] = "integration/networkManager.lua",
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package = "multi"
|
||||||
|
version = "16.2-0"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/rayaman/multi.git",
|
||||||
|
tag = "v16.2.0",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Lua Multi tasking library",
|
||||||
|
detailed = [[
|
||||||
|
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
|
||||||
|
Check github for documentation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/rayaman/multi",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["multi"] = "init.lua",
|
||||||
|
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
|
||||||
|
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
|
||||||
|
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
|
||||||
|
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
|
||||||
|
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
|
||||||
|
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
|
||||||
|
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
|
||||||
|
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
|
||||||
|
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
|
||||||
|
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
|
||||||
|
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
|
||||||
|
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
|
||||||
|
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
|
||||||
|
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
|
||||||
|
["multi.integration.threading"] = "integration/threading.lua",
|
||||||
|
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
|
||||||
|
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
|
||||||
|
--["multi.integration.networkManager"] = "integration/networkManager.lua",
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ local multi, thread = require("multi"):init{print=true,warn=true,error=true}--{p
|
|||||||
local good = false
|
local good = false
|
||||||
local proc = multi:newProcessor("Test")
|
local proc = multi:newProcessor("Test")
|
||||||
|
|
||||||
|
print("Version: "..multi.Version)
|
||||||
|
|
||||||
proc.Start()
|
proc.Start()
|
||||||
|
|
||||||
proc:newAlarm(3):OnRing(function()
|
proc:newAlarm(3):OnRing(function()
|
||||||
|
|||||||
-298
@@ -1,298 +0,0 @@
|
|||||||
package.path = "../?/init.lua;../?.lua;"..package.path
|
|
||||||
multi, thread = require("multi"):init{print=true,warn=true,debugging=true}
|
|
||||||
-- for i,v in pairs(thread) do
|
|
||||||
-- print(i,v)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- require("multi.integration.priorityManager")
|
|
||||||
|
|
||||||
-- multi.debugging.OnObjectCreated(function(obj, process)
|
|
||||||
-- multi.print("Created:", obj.Type, "in", process.Type, process:getFullName())
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi.debugging.OnObjectDestroyed(function(obj, process)
|
|
||||||
-- multi.print("Destroyed:", obj.Type, "in", process.Type, process:getFullName())
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
|
|
||||||
-- test = multi:newProcessor("Test")
|
|
||||||
-- test:setPriorityScheme(multi.priorityScheme.TimeBased)
|
|
||||||
|
|
||||||
-- test:newUpdater(10000000):OnUpdate(function()
|
|
||||||
-- print("Print is slowish")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- print("Running...")
|
|
||||||
|
|
||||||
-- local conn1, conn2 = multi:newConnection(), multi:newConnection()
|
|
||||||
-- conn3 = conn1 + conn2
|
|
||||||
|
|
||||||
-- conn1(function()
|
|
||||||
-- print("Hi 1")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- conn2(function()
|
|
||||||
-- print("Hi 2")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- conn3(function()
|
|
||||||
-- print("Hi 3")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- function test(a,b,c)
|
|
||||||
-- print("I run before all and control if execution should continue!")
|
|
||||||
-- return a>b
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- conn4 = test .. conn1
|
|
||||||
|
|
||||||
-- conn5 = conn2 .. function() print("I run after it all!") end
|
|
||||||
|
|
||||||
-- conn4:Fire(3,2,3)
|
|
||||||
-- -- This second one won't trigger the Hi's
|
|
||||||
-- conn4:Fire(1,2,3)
|
|
||||||
|
|
||||||
-- conn5(function()
|
|
||||||
-- print("Test 1")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- conn5(function()
|
|
||||||
-- print("Test 2")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- conn5(function()
|
|
||||||
-- print("Test 3")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- conn5:Fire()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- multi.print("Testing thread:newProcessor()")
|
|
||||||
|
|
||||||
-- proc = thread:newProcessor("Test")
|
|
||||||
|
|
||||||
-- proc:newLoop(function()
|
|
||||||
-- multi.print("Running...")
|
|
||||||
-- thread.sleep(1)
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- proc:newThread(function()
|
|
||||||
-- while true do
|
|
||||||
-- multi.warn("Everything is a thread in this proc!")
|
|
||||||
-- thread.sleep(1)
|
|
||||||
-- end
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- proc:newAlarm(5):OnRing(function(a)
|
|
||||||
-- multi.print(";) Goodbye")
|
|
||||||
-- a:Destroy()
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local func = thread:newFunction(function()
|
|
||||||
-- thread.sleep(4)
|
|
||||||
-- print("Hello!")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi:newTLoop(func, 1)
|
|
||||||
|
|
||||||
-- multi:mainloop()
|
|
||||||
|
|
||||||
-- multi:setTaskDelay(.05)
|
|
||||||
-- multi:newTask(function()
|
|
||||||
-- for i = 1, 10 do
|
|
||||||
-- multi:newTask(function()
|
|
||||||
-- print("Task "..i)
|
|
||||||
-- end)
|
|
||||||
-- end
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local conn = multi:newConnection()
|
|
||||||
-- conn(function() print("Test 1") end)
|
|
||||||
-- conn(function() print("Test 2") end)
|
|
||||||
-- conn(function() print("Test 3") end)
|
|
||||||
-- conn(function() print("Test 4") end)
|
|
||||||
|
|
||||||
-- print("Fire 1")
|
|
||||||
-- conn:Fire()
|
|
||||||
-- conn = -conn
|
|
||||||
-- print("Fire 2")
|
|
||||||
-- conn:Fire()
|
|
||||||
|
|
||||||
-- print(#conn)
|
|
||||||
|
|
||||||
-- thread:newThread("Test thread", function()
|
|
||||||
-- print("Starting thread!")
|
|
||||||
-- thread.defer(function() -- Runs when the thread finishes execution
|
|
||||||
-- print("Clean up time!")
|
|
||||||
-- end)
|
|
||||||
-- --[[
|
|
||||||
-- Do lot's of stuff
|
|
||||||
-- ]]
|
|
||||||
-- thread.sleep(3)
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
multi:mainloop()
|
|
||||||
|
|
||||||
-- local conn1, conn2, conn3 = multi:newConnection(nil,nil,true), multi:newConnection(), multi:newConnection()
|
|
||||||
|
|
||||||
-- local link = conn1(function()
|
|
||||||
-- print("Conn1, first")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local link2 = conn1(function()
|
|
||||||
-- print("Conn1, second")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local link3 = conn1(function()
|
|
||||||
-- print("Conn1, third")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local link4 = conn2(function()
|
|
||||||
-- print("Conn2, first")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local link5 = conn2(function()
|
|
||||||
-- print("Conn2, second")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- local link6 = conn2(function()
|
|
||||||
-- print("Conn2, third")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- print("Links 1-6",link,link2,link3,link4,link5,link6)
|
|
||||||
-- conn1:Lock(link)
|
|
||||||
-- print("All conns\n-------------")
|
|
||||||
-- conn1:Fire()
|
|
||||||
-- conn2:Fire()
|
|
||||||
|
|
||||||
-- conn1:Unlock(link)
|
|
||||||
|
|
||||||
-- conn1:Unconnect(link3)
|
|
||||||
-- conn2:Unconnect(link6)
|
|
||||||
-- print("All conns Edit\n---------------------")
|
|
||||||
-- conn1:Fire()
|
|
||||||
-- conn2:Fire()
|
|
||||||
|
|
||||||
-- thread:newThread(function()
|
|
||||||
-- print("Awaiting status")
|
|
||||||
-- thread.hold(conn1 + (conn2 * conn3))
|
|
||||||
-- print("Conn or Conn2 and Conn3")
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi:newAlarm(1):OnRing(function()
|
|
||||||
-- print("Conn")
|
|
||||||
-- conn1:Fire()
|
|
||||||
-- end)
|
|
||||||
-- multi:newAlarm(2):OnRing(function()
|
|
||||||
-- print("Conn2")
|
|
||||||
-- conn2:Fire()
|
|
||||||
-- end)
|
|
||||||
-- multi:newAlarm(3):OnRing(function()
|
|
||||||
-- print("Conn3")
|
|
||||||
-- conn3:Fire()
|
|
||||||
-- os.exit()
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
|
|
||||||
-- local conn = multi:newSystemThreadedConnection("conn"):init()
|
|
||||||
|
|
||||||
-- multi:newSystemThread("Thread_Test_1", function()
|
|
||||||
-- local multi, thread = require("multi"):init()
|
|
||||||
-- local conn = GLOBAL["conn"]:init()
|
|
||||||
-- local console = THREAD.getConsole()
|
|
||||||
-- conn(function(a,b,c)
|
|
||||||
-- console.print(THREAD:getName().." was triggered!",a,b,c)
|
|
||||||
-- end)
|
|
||||||
-- multi:mainloop()
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi:newSystemThread("Thread_Test_2", function()
|
|
||||||
-- local multi, thread = require("multi"):init()
|
|
||||||
-- local conn = GLOBAL["conn"]:init()
|
|
||||||
-- local console = THREAD.getConsole()
|
|
||||||
-- conn(function(a,b,c)
|
|
||||||
-- console.print(THREAD:getName().." was triggered!",a,b,c)
|
|
||||||
-- end)
|
|
||||||
-- multi:newAlarm(2):OnRing(function()
|
|
||||||
-- console.print("Fire 2!!!")
|
|
||||||
-- conn:Fire(4,5,6)
|
|
||||||
-- THREAD.kill()
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi:mainloop()
|
|
||||||
-- end)
|
|
||||||
-- local console = THREAD.getConsole()
|
|
||||||
-- conn(function(a,b,c)
|
|
||||||
-- console.print("Mainloop conn got triggered!",a,b,c)
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- alarm = multi:newAlarm(1)
|
|
||||||
-- alarm:OnRing(function()
|
|
||||||
-- console.print("Fire 1!!!")
|
|
||||||
-- conn:Fire(1,2,3)
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- alarm = multi:newAlarm(3):OnRing(function()
|
|
||||||
-- multi:newSystemThread("Thread_Test_3",function()
|
|
||||||
-- local multi, thread = require("multi"):init()
|
|
||||||
-- local conn = GLOBAL["conn"]:init()
|
|
||||||
-- local console = THREAD.getConsole()
|
|
||||||
-- conn(function(a,b,c)
|
|
||||||
-- console.print(THREAD:getName().." was triggered!",a,b,c)
|
|
||||||
-- end)
|
|
||||||
-- multi:newAlarm(4):OnRing(function()
|
|
||||||
-- console.print("Fire 3!!!")
|
|
||||||
-- conn:Fire(7,8,9)
|
|
||||||
-- end)
|
|
||||||
-- multi:mainloop()
|
|
||||||
-- end)
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi:newSystemThread("Thread_Test_4",function()
|
|
||||||
-- local multi, thread = require("multi"):init()
|
|
||||||
-- local conn = GLOBAL["conn"]:init()
|
|
||||||
-- local conn2 = multi:newConnection()
|
|
||||||
-- local console = THREAD.getConsole()
|
|
||||||
-- multi:newAlarm(2):OnRing(function()
|
|
||||||
-- conn2:Fire()
|
|
||||||
-- end)
|
|
||||||
-- multi:newThread(function()
|
|
||||||
-- console.print("Conn Test!")
|
|
||||||
-- thread.hold(conn + conn2)
|
|
||||||
-- console.print("It held!")
|
|
||||||
-- end)
|
|
||||||
-- multi:mainloop()
|
|
||||||
-- end)
|
|
||||||
|
|
||||||
-- multi:mainloop()
|
|
||||||
--[[
|
|
||||||
newFunction function: 0x00fad170
|
|
||||||
waitFor function: 0x00fad0c8
|
|
||||||
request function: 0x00fa4f10
|
|
||||||
newThread function: 0x00fad1b8
|
|
||||||
--__threads table: 0x00fa4dc8
|
|
||||||
defer function: 0x00fa4f98
|
|
||||||
isThread function: 0x00facd40
|
|
||||||
holdFor function: 0x00fa5058
|
|
||||||
yield function: 0x00faccf8
|
|
||||||
hold function: 0x00fa51a0
|
|
||||||
chain function: 0x00fa5180
|
|
||||||
__CORES 32
|
|
||||||
newISOThread function: 0x00fad250
|
|
||||||
newFunctionBase function: 0x00fad128
|
|
||||||
requests table: 0x00fa4e68
|
|
||||||
newProcessor function: 0x00fad190
|
|
||||||
exec function: 0x00fa50e8
|
|
||||||
pushStatus function: 0x00fad108
|
|
||||||
kill function: 0x00faccd8
|
|
||||||
get function: 0x00fad0a8
|
|
||||||
set function: 0x00fad088
|
|
||||||
getCores function: 0x00facd60
|
|
||||||
skip function: 0x00faccb0
|
|
||||||
--_Requests function: 0x00fa50a0
|
|
||||||
getRunningThread function: 0x00fa4fb8
|
|
||||||
holdWithin function: 0x00facc80
|
|
||||||
sleep function: 0x00fa4df0
|
|
||||||
]]
|
|
||||||
Reference in New Issue
Block a user