18 Commits
Author SHA1 Message Date
server 8b5d10cbb6 updated tests and added check in connections 2026-06-09 23:04:02 -07:00
server 0796788fcb removed dup func 2026-06-08 11:04:25 -07:00
server ee5e3bde7f fixed int issue with lua 5.5 2026-05-30 21:21:32 -07:00
server c86413351c updated opt for connections 2026-05-14 22:29:34 -07:00
server 4a52cd5e14 working on new documentation 2026-04-04 01:00:50 -07:00
server 14beeb686a making some changes 2026-04-01 22:22:05 -07:00
server 60783fdb16 remove luajit and 5.5 not supported with current actions 2026-03-23 22:07:57 -07:00
server b1a7e61c03 added lua 5.5 and using luajit 2026-03-23 22:06:18 -07:00
server 9fa0e7c2cb changed branch to master 2026-03-23 22:01:52 -07:00
server ef243f87d4 removed love2d test 2026-03-23 22:01:12 -07:00
server 178283e0b4 Merge branch 'master' into v16.3.0 2026-03-23 22:00:29 -07:00
server 0501f068e4 testing new action 2026-03-23 21:55:35 -07:00
server ffd7ac15f6 added new unit tests 2026-03-23 21:52:56 -07:00
server 869368af56 updated docs 2026-03-23 21:26:40 -07:00
server eeb75490dc default priority is normal 2026-03-23 21:18:27 -07:00
server 2fec5b39b8 fixing bugs 2026-03-23 20:40:58 -07:00
server 0a92890290 working on task management 2026-03-15 01:13:00 -07:00
server 40de9a8d22 Improving tests 2026-01-12 23:15:31 -08:00
98 changed files with 30508 additions and 28894 deletions
-25
View File
@@ -1,25 +0,0 @@
name: Build & Run tests Love2d
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
strategy:
fail-fast: false
runs-on: "ubuntu-latest"
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Install love2d
run: |
sudo apt install fuse
wget https://github.com/love2d/love/releases/download/11.4/love-11.4-x86_64.AppImage -O love.AppImage
sudo chmod +x love.AppImage
- name: Run Tests
run: |
./love.AppImage tests
+31 -31
View File
@@ -1,32 +1,32 @@
name: Lua Unit Tests (Matrix) name: Lua Unit Tests (Matrix)
on: on:
push: push:
branches: [ main ] branches: [ master ]
pull_request: pull_request:
branches: [ main ] branches: [ master ]
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
luaVersion: ["5.1", "5.2", "5.3", "5.4", "luajit-2.1.0-beta3"] luaVersion: ["5.1", "5.2", "5.3", "5.4"]
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Lua - name: Setup Lua
uses: leafo/gh-actions-lua@v10 uses: leafo/gh-actions-lua@v10
with: with:
luaVersion: ${{ matrix.luaVersion }} luaVersion: ${{ matrix.luaVersion }}
- name: Verify Lua version - name: Verify Lua version
run: lua -v run: lua -v
- name: Run unit tests - name: Run unit tests
run: | run: |
# Replace with your actual test file # Replace with your actual test file
lua tests/multi_test.lua lua tests/multi_test.lua
+2 -2
View File
@@ -1,3 +1,3 @@
*.code-workspace *.code-workspace
lua5.4/* lua5.4/*
test.lua test.lua
+21 -21
View File
@@ -1,21 +1,21 @@
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
+25 -25
View File
@@ -1,26 +1,26 @@
# NTHREAD Namespace # NTHREAD Namespace
- [ ] NTHREAD.set(name, val) - [ ] NTHREAD.set(name, val)
- [ ] NTHREAD.get(name, val) - [ ] NTHREAD.get(name, val)
- [ ] NTHREAD.waitFor(name) - [ ] NTHREAD.waitFor(name)
- [ ] NTHREAD.getCores()* - [ ] NTHREAD.getCores()*
- [ ] NTHREAD.getConsole() - [ ] NTHREAD.getConsole()
- [ ] NTHREAD.getThreads() - [ ] NTHREAD.getThreads()
- [ ] NTHREAD.kill() - [ ] NTHREAD.kill()
- [ ] NTHREAD.getName() - [ ] NTHREAD.getName()
- [ ] NTHREAD.getID() - [ ] NTHREAD.getID()
- [ ] NTHREAD.pushStatus(...) - [ ] NTHREAD.pushStatus(...)
- [ ] NTHREAD.sleep(n) - [ ] NTHREAD.sleep(n)
- [ ] NTHREAD.hold(n) - [ ] NTHREAD.hold(n)
- [ ] NTHREAD.setENV(env) - [ ] NTHREAD.setENV(env)
- [ ] NTHREAD.getENV() - [ ] NTHREAD.getENV()
# Extensions # Extensions
- [ ] multi:newNetworkThreadedQueue(name) - [ ] multi:newNetworkThreadedQueue(name)
- [ ] multi:newNetworkThreadedTable(name) - [ ] multi:newNetworkThreadedTable(name)
- [ ] multi:newNetworkThreadedJobQueue(n) - [ ] multi:newNetworkThreadedJobQueue(n)
- [ ] multi:newNetworkThreadedConnection(name) - [ ] multi:newNetworkThreadedConnection(name)
# Core # Core
- [ ] NTHREAD:newFunction(func, holdme) - [ ] NTHREAD:newFunction(func, holdme)
- [ ] NTHREAD:newNetworkThread(name, func, ...) - [ ] NTHREAD:newNetworkThread(name, func, ...)
- [ ] mulit:newNetworkThread(name, func, ...) - [ ] mulit:newNetworkThread(name, func, ...)
+100 -100
View File
@@ -1,100 +1,100 @@
# Multi Version: 16.1.0 - The Flow State # Multi Version: 16.3.0 -
**Key Changes** **Key Changes**
- Updated Processors to have more controlled over scheduled processes - Fixed connection multiplying
- Forwarding connections - Optimizing the library
- New Timeout handling - Updated task management support
Refer to the [Change Log](https://github.com/rayaman/multi/blob/master/docs/changes.md) for more infromation 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!
My multitasking library for lua. It is a pure lua binding, with exceptions of the integrations. My multitasking library for lua. It is a pure lua binding, with exceptions of the integrations.
</br> </br>
Progress is being made in [v16.2.0](https://github.com/rayaman/multi/tree/v16.2.0) Progress is being made in [v16.3.0](https://github.com/rayaman/multi/tree/v16.3.0)
--- ---
</br> </br>
INSTALLING INSTALLING
---------- ----------
Link to optional dependencies: Link to optional dependencies:
- [lanes](https://github.com/LuaLanes/lanes) `luarocks install lanes` - [lanes](https://github.com/LuaLanes/lanes) `luarocks install lanes`
- [chronos](https://github.com/ldrumm/chronos) `luarocks install chronos` - [chronos](https://github.com/ldrumm/chronos) `luarocks install chronos`
- [love2d](https://love2d.org/) - [love2d](https://love2d.org/)
When using love2d add multi:uManager() or any processor to love.update() When using love2d add multi:uManager() or any processor to love.update()
```lua ```lua
function love.update(dt) function love.update(dt)
multi:uManager() multi:uManager()
end end
``` ```
To install copy the multi folder into your environment and you are good to go</br> To install copy the multi folder into your environment and you are good to go</br>
If you want to use the system threads, then you'll need to install lanes or love2d game engine! If you want to use the system threads, then you'll need to install lanes or love2d game engine!
``` ```
luarocks install multi luarocks install multi
``` ```
Discord Discord
------- -------
Have a question or need realtime assistance? Feel free to join the discord!</br> Have a question or need realtime assistance? Feel free to join the discord!</br>
https://discord.gg/U8UspuA https://discord.gg/U8UspuA
Planned features/TODO 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/docs/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:
``` ```
lua tests/runtests.lua (Runs all tests, attempts to use lanes) lua tests/runtests.lua (Runs all tests, attempts to use lanes)
love tests (Runs all tests in love2d env) love tests (Runs all tests in love2d env)
``` ```
```lua ```lua
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
GLOBAL, THREAD = require("multi.integration.threading"):init() GLOBAL, THREAD = require("multi.integration.threading"):init()
multi:newSystemThread("System Thread",function() multi:newSystemThread("System Thread",function()
while true do while true do
THREAD.sleep(.1) THREAD.sleep(.1)
io.write(" World") io.write(" World")
THREAD.kill() THREAD.kill()
end end
end) end)
multi:newThread("Coroutine Based Thread",function() multi:newThread("Coroutine Based Thread",function()
while true do while true do
io.write("Hello") io.write("Hello")
thread.sleep(.1) thread.sleep(.1)
thread.kill() thread.kill()
end end
end) end)
multi:newTLoop(function(loop) multi:newTLoop(function(loop)
print("!") print("!")
loop:Destroy() loop:Destroy()
os.exit() os.exit()
end,.3) end,.3)
multi:mainloop() multi:mainloop()
--[[ --[[
while true do while true do
multi:uManager() multi:uManager()
end end
]] ]]
``` ```
Known Bugs/Issues Known Bugs/Issues
----------------- -----------------
Check the [Issues tab](https://github.com/rayaman/multi/issues) for issues Check the [Issues tab](https://github.com/rayaman/multi/issues) for issues
+971 -971
View File
File diff suppressed because it is too large Load Diff
+3698 -3675
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2993 -2865
View File
File diff suppressed because it is too large Load Diff
+106 -106
View File
@@ -1,106 +1,106 @@
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
multi.defaultSettings.debugging = true multi.defaultSettings.debugging = true
local dbg = {} local dbg = {}
dbg.__index = dbg dbg.__index = dbg
dbg.processors = {} dbg.processors = {}
-- Hooks to all on object created events! -- Hooks to all on object created events!
local c_cache = {} local c_cache = {}
local d_cache = {} local d_cache = {}
local proc = multi:newProcessor("Debug_Processor").Start() local proc = multi:newProcessor("Debug_Processor").Start()
dbg.OnObjectCreated = function(obj, process) dbg.OnObjectCreated = function(obj, process)
if c_cache[obj] then if c_cache[obj] then
return false return false
else else
c_cache[obj] = true c_cache[obj] = true
proc:newTask(function() proc:newTask(function()
c_cache[obj] = false c_cache[obj] = false
end) end)
return true return true
end end
end .. multi:newConnection() end .. multi:newConnection()
dbg.OnObjectDestroyed = function(obj, process) dbg.OnObjectDestroyed = function(obj, process)
if d_cache[obj] then if d_cache[obj] then
return false return false
else else
d_cache[obj] = true d_cache[obj] = true
proc:newTask(function() proc:newTask(function()
d_cache[obj] = false d_cache[obj] = false
end) end)
return true return true
end end
end .. multi:newConnection() end .. multi:newConnection()
local creation_hook, destruction_hook local creation_hook, destruction_hook
local types local types
local objects = {} local objects = {}
creation_hook = function(obj, process) creation_hook = function(obj, process)
types = multi:getTypes() types = multi:getTypes()
if obj.Type == multi.PROCESS and not dbg.processors[obj] then if obj.Type == multi.PROCESS and not dbg.processors[obj] then
obj.OnObjectCreated(creation_hook) obj.OnObjectCreated(creation_hook)
obj.OnObjectDestroyed(destruction_hook) obj.OnObjectDestroyed(destruction_hook)
end end
table.insert(objects, obj) table.insert(objects, obj)
dbg.OnObjectCreated:Fire(obj, process) dbg.OnObjectCreated:Fire(obj, process)
end end
destruction_hook = function(obj, process) destruction_hook = function(obj, process)
for i = 1, #objects do for i = 1, #objects do
if objects[i] == obj then if objects[i] == obj then
table.remove(objects, i) table.remove(objects, i)
break break
end end
end end
dbg.OnObjectDestroyed:Fire(obj, process) dbg.OnObjectDestroyed:Fire(obj, process)
end end
function dbg:getObjects(typ) function dbg:getObjects(typ)
if type(typ) == "string" then if type(typ) == "string" then
local objs = {} local objs = {}
for i = 1, #objects do for i = 1, #objects do
if objects[i].Type == typ then if objects[i].Type == typ then
objs[#objs+1] = objects[i] objs[#objs+1] = objects[i]
end end
end end
return objs return objs
elseif type(typ) == "table" then -- Process elseif type(typ) == "table" then -- Process
local objs = {} local objs = {}
for i = 1, #objects do for i = 1, #objects do
if objects[i].Parent == typ then if objects[i].Parent == typ then
objs[#objs+1] = objects[i] objs[#objs+1] = objects[i]
end end
end end
return objs return objs
elseif type(typ) == "function" then elseif type(typ) == "function" then
local objs = {} local objs = {}
-- Keep objects local/private, return true to add to list, false to reject, "break" to break loop -- Keep objects local/private, return true to add to list, false to reject, "break" to break loop
for i = 1, #objects do for i = 1, #objects do
local ret = typ(objects[i]) local ret = typ(objects[i])
if ret then if ret then
objs[#objs+1] = objects[i] objs[#objs+1] = objects[i]
elseif ret == "break" then elseif ret == "break" then
break break
end end
end end
return objs return objs
end end
end end
local debug_stats = {} local debug_stats = {}
local tmulti = multi:getThreadManagerProcess() local tmulti = multi:getThreadManagerProcess()
multi.OnObjectCreated(creation_hook) multi.OnObjectCreated(creation_hook)
tmulti.OnObjectCreated(creation_hook) tmulti.OnObjectCreated(creation_hook)
multi.OnObjectDestroyed(destroction_hook) multi.OnObjectDestroyed(destroction_hook)
tmulti.OnObjectDestroyed(destroction_hook) tmulti.OnObjectDestroyed(destroction_hook)
-- We write to a debug interface in the multi namespace -- We write to a debug interface in the multi namespace
multi.debugging = dbg multi.debugging = dbg
+45 -45
View File
@@ -1,46 +1,46 @@
local multi, thread = require("multi"):init{error=true} local multi, thread = require("multi"):init{error=true}
multi.error("Currntly not supported!") multi.error("Currntly not supported!")
os.exit(1) os.exit(1)
local effil = require("effil") local effil = require("effil")
-- I like some of the things that this library offers. -- I like some of the things that this library offers.
-- Current limitations prevent me from being able to use effil, -- Current limitations prevent me from being able to use effil,
-- but I might fork and work on it myself. -- but I might fork and work on it myself.
-- Configs -- Configs
effil.allow_table_upvalues(false) effil.allow_table_upvalues(false)
local GLOBAL,THREAD = require("multi.integration.effilManager.threads").init() local GLOBAL,THREAD = require("multi.integration.effilManager.threads").init()
local count = 1 local count = 1
local started = false local started = false
local livingThreads = {} local livingThreads = {}
function multi:newSystemThread(name, func, ...) function multi:newSystemThread(name, func, ...)
local name = name or multi.randomString(16) local name = name or multi.randomString(16)
local rand = math.random(1, 10000000) local rand = math.random(1, 10000000)
c = {} c = {}
c.name = name c.name = name
c.Name = name c.Name = name
c.Id = count c.Id = count
end end
function THREAD:newFunction(func, holdme) function THREAD:newFunction(func, holdme)
return thread:newFunctionBase(function(...) return thread:newFunctionBase(function(...)
return multi:newSystemThread("TempSystemThread",func,...) return multi:newSystemThread("TempSystemThread",func,...)
end, holdme, multi.SFUNCTION)() end, holdme, multi.SFUNCTION)()
end end
THREAD.newSystemThread = function(...) THREAD.newSystemThread = function(...)
multi:newSystemThread(...) multi:newSystemThread(...)
end end
multi.print("Integrated Effil Threading!") multi.print("Integrated Effil Threading!")
multi.integration = {} -- for module creators multi.integration = {} -- for module creators
multi.integration.GLOBAL = GLOBAL multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD multi.integration.THREAD = THREAD
require("multi.integration.effilManager.extensions") require("multi.integration.effilManager.extensions")
return { return {
init = function() init = function()
return GLOBAL, THREAD return GLOBAL, THREAD
end end
} }
+396 -392
View File
@@ -1,393 +1,397 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
if not (GLOBAL and THREAD) then if not (GLOBAL and THREAD) then
GLOBAL, THREAD = multi.integration.GLOBAL, multi.integration.THREAD GLOBAL, THREAD = multi.integration.GLOBAL, multi.integration.THREAD
else else
lanes = require("lanes") lanes = require("lanes")
end end
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local name = name or multi.randomString(16) local name = name or multi.randomString(16)
local c = {} local c = {}
c.Name = name c.Name = name
c.linda = lanes.linda() c.linda = lanes.linda()
c.Type = multi.registerType("s_queue") c.Type = multi.registerType("s_queue")
function c:push(v) function c:push(v)
self.linda:send("Q", v) self.linda:send("Q", v)
end end
function c:pop() function c:pop()
return ({self.linda:receive(0, "Q")})[2] return ({self.linda:receive(0, "Q")})[2]
end end
function c:peek() function c:peek()
return self.linda:get("Q") return self.linda:get("Q")
end end
function c:init() function c:init()
return self return self
end end
if multi.isMainThread then if multi.isMainThread then
multi.integration.GLOBAL[name] = c multi.integration.GLOBAL[name] = c
else else
GLOBAL[name] = c GLOBAL[name] = c
end end
function c:Hold(opt) local peek = function()
local multi, thread = require("multi"):init() return c:peek()
if opt.peek then end
return thread.hold(function()
return self:peek() local pop = function()
end) return c:pop()
else end
return thread.hold(function()
return self:pop() function c:Hold(opt)
end) local multi, thread = require("multi"):init()
end if opt.peek then
end return thread.hold(peek)
else
self:create(c) return thread.hold(pop)
end
return c end
end
self:create(c)
function multi:newSystemThreadedTable(name)
local name = name or multi.randomString(16) return c
local c = {} end
c.link = lanes.linda()
c.Name = name function multi:newSystemThreadedTable(name)
c.Type = multi.registerType("s_table") local name = name or multi.randomString(16)
local c = {}
function c:init() c.link = lanes.linda()
return self c.Name = name
end c.Type = multi.registerType("s_table")
setmetatable(c,{ function c:init()
__index = function(t,k) return self
return c.link:get(k) end
end,
__newindex = function(t,k,v) setmetatable(c,{
c.link:set(k, v) __index = function(t,k)
end return c.link:get(k)
}) end,
__newindex = function(t,k,v)
if multi.isMainThread then c.link:set(k, v)
multi.integration.GLOBAL[name] = c end
else })
GLOBAL[name] = c
end if multi.isMainThread then
multi.integration.GLOBAL[name] = c
function c:Hold(opt) else
local multi, thread = require("multi"):init() GLOBAL[name] = c
if opt.key then end
return thread.hold(function()
return self.tab[opt.key] function c:Hold(opt)
end) local multi, thread = require("multi"):init()
else if opt.key then
multi.error("Must provide a key to check opt.key = 'key'") return thread.hold(function()
end return self.tab[opt.key]
end end)
else
self:create(c) multi.error("Must provide a key to check opt.key = 'key'")
end
return c end
end
self:create(c)
function multi:newSystemThreadedJobQueue(n)
local c = {} return c
c.cores = n or THREAD.getCores()*2 end
c.Type = multi.registerType("s_jobqueue")
c.OnJobCompleted = multi:newConnection() function multi:newSystemThreadedJobQueue(n)
local funcs = multi:newSystemThreadedTable() local c = {}
local queueJob = multi:newSystemThreadedQueue() c.cores = n or THREAD.getCores()*2
local queueReturn = multi:newSystemThreadedQueue() c.Type = multi.registerType("s_jobqueue")
local doAll = multi:newSystemThreadedQueue() c.OnJobCompleted = multi:newConnection()
local ID=1 local funcs = multi:newSystemThreadedTable()
local jid = 1 local queueJob = multi:newSystemThreadedQueue()
function c:isEmpty() local queueReturn = multi:newSystemThreadedQueue()
return queueJob:peek()==nil local doAll = multi:newSystemThreadedQueue()
end local ID=1
function c:doToAll(func,...) local jid = 1
for i=1,c.cores do function c:isEmpty()
doAll:push{ID,func,...} return queueJob:peek()==nil
end end
ID = ID + 1 function c:doToAll(func,...)
return self for i=1,c.cores do
end doAll:push{ID,func,...}
function c:registerFunction(name,func) end
funcs[name]=func ID = ID + 1
return self return self
end end
function c:pushJob(name,...) function c:registerFunction(name,func)
queueJob:push{name,jid,multi.pack(...)} funcs[name]=func
jid = jid + 1 return self
return jid-1 end
end function c:pushJob(name,...)
local nFunc = 0 queueJob:push{name,jid,multi.pack(...)}
function c:newFunction(name, func, holup) -- This registers with the queue jid = jid + 1
if type(name)=="function" then return jid-1
holup = func end
func = name local nFunc = 0
name = "JQ_Function_"..nFunc function c:newFunction(name, func, holup) -- This registers with the queue
end if type(name)=="function" then
nFunc = nFunc + 1 holup = func
c:registerFunction(name,func) func = name
return thread:newFunction(function(...) name = "JQ_Function_"..nFunc
local id = c:pushJob(name,...) end
local link nFunc = nFunc + 1
local rets c:registerFunction(name,func)
link = c.OnJobCompleted(function(jid,...) return thread:newFunction(function(...)
if id==jid then local id = c:pushJob(name,...)
rets = multi.pack(...) local link
end local rets
end) link = c.OnJobCompleted(function(jid,...)
return thread.hold(function() if id==jid then
if rets then rets = multi.pack(...)
if #rets == 0 then end
return multi.NIL end)
else return thread.hold(function()
return multi.unpack(rets) if rets then
end if #rets == 0 then
end return multi.NIL
end) else
end, holup), name return multi.unpack(rets)
end end
thread:newThread("JobQueueManager",function() end
while true do end)
local job = thread.hold(function() end, holup), name
return queueReturn:pop() end
end) thread:newThread("JobQueueManager",function()
if job then while true do
local id = table.remove(job,1) local job = thread.hold(function()
c.OnJobCompleted:Fire(id,multi.unpack(job)) return queueReturn:pop()
end end)
end if job then
end) local id = table.remove(job,1)
for i=1,c.cores do c.OnJobCompleted:Fire(id,multi.unpack(job))
multi:newSystemThread("STJQ_"..multi.randomString(8),function(queue) end
local multi, thread = require("multi"):init() end
local idle = os.clock() end)
local clock = os.clock for i=1,c.cores do
local ref = 0 multi:newSystemThread("STJQ_"..multi.randomString(8),function(queue)
_G["__QR"] = queueReturn local multi, thread = require("multi"):init()
setmetatable(_G,{__index = funcs}) local idle = os.clock()
thread:newThread("JobHandler",function() local clock = os.clock
while true do local ref = 0
local dat = thread.hold(function() _G["__QR"] = queueReturn
return queueJob:pop() setmetatable(_G,{__index = funcs})
end) thread:newThread("JobHandler",function()
idle = clock() while true do
thread:newThread("JobQueue-Spawn",function() local dat = thread.hold(function()
local name = table.remove(dat, 1) return queueJob:pop()
local jid = table.remove(dat, 1) end)
local args = table.remove(dat, 1) idle = clock()
queueReturn:push{jid, funcs[name](args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]), queue} thread:newThread("JobQueue-Spawn",function()
end) local name = table.remove(dat, 1)
end local jid = table.remove(dat, 1)
end) local args = table.remove(dat, 1)
thread:newThread("DoAllHandler",function() queueReturn:push{jid, funcs[name](args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]), queue}
while true do end)
local dat = thread.hold(function() end
return doAll:peek() end)
end) thread:newThread("DoAllHandler",function()
if dat then while true do
if dat[1]>ref then local dat = thread.hold(function()
ref = table.remove(dat, 1) return doAll:peek()
func = table.remove(dat, 1) end)
idle = clock() if dat then
func(unpack(dat)) if dat[1]>ref then
doAll:pop() ref = table.remove(dat, 1)
end func = table.remove(dat, 1)
end idle = clock()
end func(unpack(dat))
end) doAll:pop()
thread:newThread("IdleHandler",function() end
while true do end
thread.hold(function() end
return clock()-idle>3 end)
end) thread:newThread("IdleHandler",function()
THREAD.sleep(.01) while true do
end thread.hold(function()
end) return clock()-idle>3
multi:mainloop() end)
end,i) THREAD.sleep(.01)
end end
end)
function c:Hold(opt) multi:mainloop()
return thread.hold(self.OnJobCompleted) end,i)
end end
self:create(c) function c:Hold(opt)
return thread.hold(self.OnJobCompleted)
return c end
end
self:create(c)
function multi:newSystemThreadedConnection(name)
local name = name or multi.randomString(16) return c
local c = {} end
c.Type = multi.registerType("s_connection")
c.CONN = 0x00 function multi:newSystemThreadedConnection(name)
c.TRIG = 0x01 local name = name or multi.randomString(16)
c.PING = 0x02 local c = {}
c.PONG = 0x03 c.Type = multi.registerType("s_connection")
local function remove(a, b) c.CONN = 0x00
local ai = {} c.TRIG = 0x01
local r = {} c.PING = 0x02
for k,v in pairs(a) do ai[v]=true end c.PONG = 0x03
for k,v in pairs(b) do local function remove(a, b)
if ai[v]==nil then table.insert(r,a[k]) end local ai = {}
end local r = {}
return r for k,v in pairs(a) do ai[v]=true end
end for k,v in pairs(b) do
c.CID = THREAD_ID if ai[v]==nil then table.insert(r,a[k]) end
c.subscribe = multi:newSystemThreadedQueue("SUB_STC_"..self.Name):init() end
c.Name = name return r
c.links = {} -- All triggers sent from main connection. When a connection is triggered on another thread, they speak to the main then send stuff out. end
-- Locals will only live in the thread that creates the original object c.CID = THREAD_ID
local ping c.subscribe = multi:newSystemThreadedQueue("SUB_STC_"..self.Name):init()
local pong = function(link, links) c.Name = name
local res = thread.hold(function() c.links = {} -- All triggers sent from main connection. When a connection is triggered on another thread, they speak to the main then send stuff out.
return link:peek()[1] == c.PONG -- Locals will only live in the thread that creates the original object
end,{sleep=3}) local ping
local pong = function(link, links)
if not res then local res = thread.hold(function()
for i=1,#links do return link:peek()[1] == c.PONG
if links[i] == link then end,{sleep=3})
table.remove(links,i,link)
break if not res then
end for i=1,#links do
end if links[i] == link then
else table.remove(links,i,link)
link:pop() break
end end
end end
else
ping = thread:newFunction(function(self) link:pop()
ping:Pause() end
multi.ForEach(self.links, function(link) -- Sync new connections end
link:push{self.PING}
multi:newThread("pong Thread", pong, link, self.links) ping = thread:newFunction(function(self)
end) ping:Pause()
multi.ForEach(self.links, function(link) -- Sync new connections
thread.sleep(3) link:push{self.PING}
multi:newThread("pong Thread", pong, link, self.links)
ping:Resume() end)
end,false)
thread.sleep(3)
local function fire(...)
for _, link in pairs(c.links) do ping:Resume()
link:push {c.TRIG, multi.pack(...)} end,false)
end
end local function fire(...)
for _, link in pairs(c.links) do
thread:newThread("STC_SUB_MAN"..name,function() link:push {c.TRIG, multi.pack(...)}
local item end
local sub_func = function() -- This will keep things held up until there is something to process end
return c.subscribe:pop()
end thread:newThread("STC_SUB_MAN"..name,function()
while true do local item
thread.yield() local sub_func = function() -- This will keep things held up until there is something to process
-- We need to check on broken connections return c.subscribe:pop()
ping(c) -- Should return instantlly and process this in another thread end
item = thread.hold(sub_func) while true do
if item[1] == c.CONN then thread.yield()
multi.ForEach(c.links, function(link) -- Sync new connections -- We need to check on broken connections
item[2]:push{c.CONN, link} ping(c) -- Should return instantlly and process this in another thread
end) item = thread.hold(sub_func)
c.links[#c.links+1] = item[2] if item[1] == c.CONN then
elseif item[1] == c.TRIG then multi.ForEach(c.links, function(link) -- Sync new connections
fire(multi.unpack(item[2])) item[2]:push{c.CONN, link}
c.proxy_conn:Fire(multi.unpack(item[2])) end)
end c.links[#c.links+1] = item[2]
end elseif item[1] == c.TRIG then
end) fire(multi.unpack(item[2]))
--- ^^^ This will only exist in the init thread c.proxy_conn:Fire(multi.unpack(item[2]))
end
function c:Fire(...) end
local args = multi.pack(...) end)
if self.CID == THREAD_ID then -- Host Call --- ^^^ This will only exist in the init thread
for _, link in pairs(self.links) do
link:push {self.TRIG, args} function c:Fire(...)
end local args = multi.pack(...)
self.proxy_conn:Fire(...) if self.CID == THREAD_ID then -- Host Call
else for _, link in pairs(self.links) do
self.subscribe:push {self.TRIG, args} link:push {self.TRIG, args}
end end
end self.proxy_conn:Fire(...)
else
function c:init() self.subscribe:push {self.TRIG, args}
local multi, thread = require("multi"):init() end
self.links = {} end
self.proxy_conn = multi:newConnection()
local mt = getmetatable(self.proxy_conn) function c:init()
local tempMT = {} local multi, thread = require("multi"):init()
for i,v in pairs(mt) do self.links = {}
tempMT[i] = v self.proxy_conn = multi:newConnection()
end local mt = getmetatable(self.proxy_conn)
tempMT.__index = self.proxy_conn local tempMT = {}
tempMT.__call = function(t,func) self.proxy_conn(func) end for i,v in pairs(mt) do
setmetatable(self, tempMT) tempMT[i] = v
if self.CID == THREAD_ID then return self end end
thread:newThread("STC_CONN_MAN"..name,function() tempMT.__index = self.proxy_conn
local item tempMT.__call = function(t,func) self.proxy_conn(func) end
local link_self_ref = multi:newSystemThreadedQueue() setmetatable(self, tempMT)
self.subscribe:push{self.CONN, link_self_ref} if self.CID == THREAD_ID then return self end
while true do thread:newThread("STC_CONN_MAN"..name,function()
item = thread.hold(function() local item
return link_self_ref:peek() local link_self_ref = multi:newSystemThreadedQueue()
end) self.subscribe:push{self.CONN, link_self_ref}
if item[1] == self.PING then while true do
link_self_ref:push{self.PONG} item = thread.hold(function()
link_self_ref:pop() return link_self_ref:peek()
elseif item[1] == self.CONN then end)
if item[2].Name ~= link_self_ref.Name then if item[1] == self.PING then
table.insert(self.links, item[2]) link_self_ref:push{self.PONG}
end link_self_ref:pop()
link_self_ref:pop() elseif item[1] == self.CONN then
elseif item[1] == self.TRIG then if item[2].Name ~= link_self_ref.Name then
self.proxy_conn:Fire(multi.unpack(item[2])) table.insert(self.links, item[2])
link_self_ref:pop() end
else link_self_ref:pop()
-- This shouldn't be the case elseif item[1] == self.TRIG then
end self.proxy_conn:Fire(multi.unpack(item[2]))
end link_self_ref:pop()
end) else
return self -- This shouldn't be the case
end end
end
if multi.isMainThread then end)
multi.integration.GLOBAL[name] = c return self
else end
GLOBAL[name] = c
end if multi.isMainThread then
multi.integration.GLOBAL[name] = c
self:create(c) else
GLOBAL[name] = c
return c end
end
self:create(c)
return c
end
require("multi.integration.sharedExtensions") require("multi.integration.sharedExtensions")
+205 -205
View File
@@ -1,205 +1,205 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
package.path = "?/init.lua;?.lua;" .. package.path package.path = "?/init.lua;?.lua;" .. package.path
multi, thread = require("multi"):init() -- get it all and have it on all lanes multi, thread = require("multi"):init() -- get it all and have it on all lanes
if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassle if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassle
return { return {
init = function() init = function()
return multi.integration.GLOBAL, multi.integration.THREAD return multi.integration.GLOBAL, multi.integration.THREAD
end end
} }
end end
-- Step 1 get lanes -- Step 1 get lanes
lanes = require("lanes").configure() lanes = require("lanes").configure()
multi.SystemThreads = {} multi.SystemThreads = {}
multi.isMainThread = true multi.isMainThread = true
_G.THREAD_NAME = "MAIN_THREAD" _G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0 _G.THREAD_ID = 0
function multi:canSystemThread() function multi:canSystemThread()
return true return true
end end
function multi:getPlatform() function multi:getPlatform()
return "lanes" return "lanes"
end end
-- 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
local __SleepingLinda = lanes.linda() -- handles sleeping stuff local __SleepingLinda = lanes.linda() -- handles sleeping stuff
local __ConsoleLinda = lanes.linda() -- handles console stuff local __ConsoleLinda = lanes.linda() -- handles console stuff
local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions
local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda, __ConsoleLinda) local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda, __ConsoleLinda)
local count = 1 local count = 1
local started = false local started = false
local livingThreads = {} local livingThreads = {}
function THREAD:newFunction(func, holdme) function THREAD:newFunction(func, holdme)
return thread:newFunctionBase(function(...) return thread:newFunctionBase(function(...)
return multi:newSystemThread("TempSystemThread",func,...) return multi:newSystemThread("TempSystemThread",func,...)
end, holdme, multi.registerType("s_function"))() end, holdme, multi.registerType("s_function"))()
end end
function multi:newSystemThread(name, func, ...) function multi:newSystemThread(name, func, ...)
local name = name or multi.randomString(16) local name = name or multi.randomString(16)
multi.InitSystemThreadErrorHandler() multi.InitSystemThreadErrorHandler()
local rand = math.random(1, 10000000) local rand = math.random(1, 10000000)
local return_linda = lanes.linda() local return_linda = lanes.linda()
c = {} c = {}
c.Name = name c.Name = name
c.ID = count c.ID = count
c.loadString = {"base","package","os","io","math","table","string","coroutine"} c.loadString = {"base","package","os","io","math","table","string","coroutine"}
livingThreads[count] = {true, name} livingThreads[count] = {true, name}
c.returns = return_linda c.returns = return_linda
c.Type = multi.registerType("s_thread") c.Type = multi.registerType("s_thread")
c.creationTime = os.clock() c.creationTime = os.clock()
c.alive = true c.alive = true
c.priority = THREAD.Priority_Normal c.priority = THREAD.Priority_Normal
local multi_settings = multi.defaultSettings local multi_settings = multi.defaultSettings
local globe = { local globe = {
THREAD_NAME = name, THREAD_NAME = name,
THREAD_ID = count, THREAD_ID = count,
THREAD = THREAD, THREAD = THREAD,
GLOBAL = GLOBAL, GLOBAL = GLOBAL,
_Console = __ConsoleLinda, _Console = __ConsoleLinda,
_DEFER = {} _DEFER = {}
} }
if GLOBAL["__env"] then if GLOBAL["__env"] then
for i,v in pairs(GLOBAL["__env"]) do for i,v in pairs(GLOBAL["__env"]) do
globe[i] = v globe[i] = v
end end
end end
c.thread = lanes.gen("*", c.thread = lanes.gen("*",
{ {
globals = globe, globals = globe,
priority = c.priority priority = c.priority
},function(...) },function(...)
multi, thread = require("multi"):init(multi_settings) multi, thread = require("multi"):init(multi_settings)
require("multi.integration.lanesManager.extensions") require("multi.integration.lanesManager.extensions")
require("multi.integration.sharedExtensions") require("multi.integration.sharedExtensions")
local has_error = true local has_error = true
returns = {pcall(func, ...)} returns = {pcall(func, ...)}
return_linda:set("returns", returns) return_linda:set("returns", returns)
for i,v in pairs(_DEFER) do for i,v in pairs(_DEFER) do
pcall(v) pcall(v)
end end
has_error = false has_error = false
end)(...) end)(...)
count = count + 1 count = count + 1
function c:getName() function c:getName()
return c.Name return c.Name
end end
function c:kill() function c:kill()
self.thread:cancel() self.thread:cancel()
self.alive = false self.alive = false
end end
table.insert(multi.SystemThreads, c) table.insert(multi.SystemThreads, c)
c.OnDeath = multi:newConnection() c.OnDeath = multi:newConnection()
c.OnError = multi:newConnection() c.OnError = multi:newConnection()
GLOBAL["__THREADS__"] = livingThreads GLOBAL["__THREADS__"] = livingThreads
c.OnError(multi.error) c.OnError(multi.error)
if self.isActor then if self.isActor then
self:create(c) self:create(c)
else else
multi.create(multi, c) multi.create(multi, c)
end end
return c return c
end end
THREAD.newSystemThread = function(...) THREAD.newSystemThread = function(...)
multi:newSystemThread(...) multi:newSystemThread(...)
end end
function multi.InitSystemThreadErrorHandler() function multi.InitSystemThreadErrorHandler()
if started == true then if started == true then
return return
end end
started = true started = true
thread:newThread("SystemThreadScheduler",function() thread:newThread("SystemThreadScheduler",function()
local threads = multi.SystemThreads local threads = multi.SystemThreads
local _,data,status,push,temp local _,data,status,push,temp
while true do while true do
thread.yield() thread.yield()
_,data = __ConsoleLinda:receive(0, "Q") _,data = __ConsoleLinda:receive(0, "Q")
if data then if data then
--print(data[1]) --print(data[1])
end end
for i = #threads, 1, -1 do for i = #threads, 1, -1 do
temp = threads[i] temp = threads[i]
status = temp.thread.status status = temp.thread.status
push = __StatusLinda:get(temp.ID) push = __StatusLinda:get(temp.ID)
if push then if push then
temp.statusconnector:Fire(multi.unpack(({__StatusLinda:receive(nil, temp.ID)})[2])) temp.statusconnector:Fire(multi.unpack(({__StatusLinda:receive(nil, temp.ID)})[2]))
end end
if status == "done" or temp.returns:get("returns") then if status == "done" or temp.returns:get("returns") then
returns = ({temp.returns:receive(0, "returns")})[2] returns = ({temp.returns:receive(0, "returns")})[2]
livingThreads[temp.ID] = {false, temp.Name} livingThreads[temp.ID] = {false, temp.Name}
temp.alive = false temp.alive = false
if returns[1] == false then if returns[1] == false then
temp.OnError:Fire(temp, returns[2]) temp.OnError:Fire(temp, returns[2])
else else
table.remove(returns,1) table.remove(returns,1)
temp.OnDeath:Fire(multi.unpack(returns)) temp.OnDeath:Fire(multi.unpack(returns))
end end
GLOBAL["__THREADS__"] = livingThreads GLOBAL["__THREADS__"] = livingThreads
table.remove(threads, i) table.remove(threads, i)
elseif status == "running" then elseif status == "running" then
-- --
elseif status == "waiting" then elseif status == "waiting" then
-- --
elseif status == "error" then elseif status == "error" then
-- The thread never really errors, we handle this through our linda object -- The thread never really errors, we handle this through our linda object
elseif status == "cancelled" then elseif status == "cancelled" then
livingThreads[temp.ID] = {false, temp.Name} livingThreads[temp.ID] = {false, temp.Name}
temp.alive = false temp.alive = false
temp.OnError:Fire(temp,"thread_cancelled") temp.OnError:Fire(temp,"thread_cancelled")
GLOBAL["__THREADS__"] = livingThreads GLOBAL["__THREADS__"] = livingThreads
table.remove(threads, i) table.remove(threads, i)
elseif status == "killed" then elseif status == "killed" then
livingThreads[temp.ID] = {false, temp.Name} livingThreads[temp.ID] = {false, temp.Name}
temp.alive = false temp.alive = false
temp.OnError:Fire(temp,"thread_killed") temp.OnError:Fire(temp,"thread_killed")
GLOBAL["__THREADS__"] = livingThreads GLOBAL["__THREADS__"] = livingThreads
table.remove(threads, i) table.remove(threads, i)
end end
end end
end end
end).OnError(multi.error) end).OnError(multi.error)
end end
multi.print("Integrated Lanes Threading!") multi.print("Integrated Lanes Threading!")
multi.integration = {} -- for module creators multi.integration = {} -- for module creators
multi.integration.GLOBAL = GLOBAL multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD multi.integration.THREAD = THREAD
require("multi.integration.lanesManager.extensions") require("multi.integration.lanesManager.extensions")
return { return {
init = function() init = function()
return GLOBAL, THREAD return GLOBAL, THREAD
end end
} }
+150 -150
View File
@@ -1,151 +1,151 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local function getOS() local function getOS()
if package.config:sub(1, 1) == "\\" then if package.config:sub(1, 1) == "\\" then
return "windows" return "windows"
else else
return "unix" return "unix"
end end
end end
local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda, __Console) local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda, __Console)
local THREAD = {} local THREAD = {}
THREAD.Priority_Core = 3 THREAD.Priority_Core = 3
THREAD.Priority_High = 2 THREAD.Priority_High = 2
THREAD.Priority_Above_Normal = 1 THREAD.Priority_Above_Normal = 1
THREAD.Priority_Normal = 0 THREAD.Priority_Normal = 0
THREAD.Priority_Below_Normal = -1 THREAD.Priority_Below_Normal = -1
THREAD.Priority_Low = -2 THREAD.Priority_Low = -2
THREAD.Priority_Idle = -3 THREAD.Priority_Idle = -3
function THREAD.set(name, val) function THREAD.set(name, val)
__GlobalLinda:set(name, val) __GlobalLinda:set(name, val)
end end
function THREAD.get(name) function THREAD.get(name)
return __GlobalLinda:get(name) return __GlobalLinda:get(name)
end end
function THREAD.waitFor(name) function THREAD.waitFor(name)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
return multi.hold(function() return multi.hold(function()
math.randomseed(os.time()) math.randomseed(os.time())
__SleepingLinda:receive(.001, "__non_existing_variable") __SleepingLinda:receive(.001, "__non_existing_variable")
return __GlobalLinda:get(name) return __GlobalLinda:get(name)
end) end)
end end
function THREAD.getCores() function THREAD.getCores()
return THREAD.__CORES return THREAD.__CORES
end end
function THREAD.getConsole() function THREAD.getConsole()
local c = {} local c = {}
c.queue = __Console c.queue = __Console
function c.print(...) function c.print(...)
c.queue:push("Q", table.concat(multi.pack(...), "\t")) c.queue:push("Q", table.concat(multi.pack(...), "\t"))
end end
function c.error(err) function c.error(err)
c.queue:push("Q", "Error in <"..THREAD_NAME..":" .. THREAD_ID .. ">: ".. err) c.queue:push("Q", "Error in <"..THREAD_NAME..":" .. THREAD_ID .. ">: ".. err)
multi.error(err) multi.error(err)
end end
return c return c
end end
function THREAD.getThreads() function THREAD.getThreads()
return GLOBAL.__THREADS__ return GLOBAL.__THREADS__
end end
if os.getOS() == "windows" then if os.getOS() == "windows" then
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
else else
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
end end
function THREAD.kill() -- trigger the lane destruction function THREAD.kill() -- trigger the lane destruction
error("Thread was killed!\1") error("Thread was killed!\1")
end end
function THREAD.sync() function THREAD.sync()
-- Maybe do something... -- Maybe do something...
end end
function THREAD.pushStatus(...) function THREAD.pushStatus(...)
local args = multi.pack(...) local args = multi.pack(...)
__StatusLinda:send(nil,THREAD_ID, args) __StatusLinda:send(nil,THREAD_ID, args)
end end
_G.THREAD_ID = 0 _G.THREAD_ID = 0
function THREAD.sleep(n) function THREAD.sleep(n)
math.randomseed(os.time()) math.randomseed(os.time())
__SleepingLinda:receive(n, "__non_existing_variable") __SleepingLinda:receive(n, "__non_existing_variable")
end end
function THREAD.hold(n) function THREAD.hold(n)
local function wait() local function wait()
math.randomseed(os.time()) math.randomseed(os.time())
__SleepingLinda:receive(.001, "__non_existing_variable") __SleepingLinda:receive(.001, "__non_existing_variable")
end end
repeat repeat
wait() wait()
until n() until n()
end end
local GLOBAL = {} local GLOBAL = {}
setmetatable(GLOBAL, { setmetatable(GLOBAL, {
__index = function(t, k) __index = function(t, k)
return __GlobalLinda:get(k) return __GlobalLinda:get(k)
end, end,
__newindex = function(t, k, v) __newindex = function(t, k, v)
__GlobalLinda:set(k, v) __GlobalLinda:set(k, v)
end end
}) })
function THREAD.setENV(env, name) function THREAD.setENV(env, name)
GLOBAL[name or "__env"] = env GLOBAL[name or "__env"] = env
end end
function THREAD.getENV(name) function THREAD.getENV(name)
return GLOBAL[name or "__env"] return GLOBAL[name or "__env"]
end end
function THREAD.exposeENV(name) function THREAD.exposeENV(name)
name = name or "__env" name = name or "__env"
local env = THREAD.getENV(name) local env = THREAD.getENV(name)
for i,v in pairs(env) do for i,v in pairs(env) do
_G[i] = v _G[i] = v
end end
end end
function THREAD.defer(func) function THREAD.defer(func)
table.insert(_DEFER, func) table.insert(_DEFER, func)
end end
return GLOBAL, THREAD return GLOBAL, THREAD
end end
return {init = function(g,s,st,c,onexit) return {init = function(g,s,st,c,onexit)
return INIT(g,s,st,c,onexit) return INIT(g,s,st,c,onexit)
end} end}
+243 -243
View File
@@ -1,244 +1,244 @@
if not ISTHREAD then if not ISTHREAD then
multi, thread = require("multi").init() multi, thread = require("multi").init()
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
end end
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local name = name or multi.randomString(16) local name = name or multi.randomString(16)
local c = {} local c = {}
c.Name = name c.Name = name
c.Type = multi.registerType("s_queue") c.Type = multi.registerType("s_queue")
c.chan = love.thread.getChannel(name) c.chan = love.thread.getChannel(name)
function c:push(dat) function c:push(dat)
self.chan:push(THREAD.packValue(dat)) self.chan:push(THREAD.packValue(dat))
end end
function c:pop() function c:pop()
return THREAD.unpackValue(self.chan:pop()) return THREAD.unpackValue(self.chan:pop())
end end
function c:peek() function c:peek()
return THREAD.unpackValue(self.chan:peek()) return THREAD.unpackValue(self.chan:peek())
end end
function c:init() function c:init()
self.chan = love.thread.getChannel(self.Name) self.chan = love.thread.getChannel(self.Name)
return self return self
end end
function c:Hold(opt) function c:Hold(opt)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
if opt.peek then if opt.peek then
return thread.hold(function() return thread.hold(function()
return self:peek() return self:peek()
end) end)
else else
return thread.hold(function() return thread.hold(function()
return self:pop() return self:pop()
end) end)
end end
end end
GLOBAL[name] = c GLOBAL[name] = c
self:create(c) self:create(c)
return c return c
end end
function multi:newSystemThreadedTable(name) function multi:newSystemThreadedTable(name)
local name = name or multi.randomString(16) local name = name or multi.randomString(16)
local c = {} local c = {}
c.Name = name c.Name = name
c.Type = multi.registerType("s_table") c.Type = multi.registerType("s_table")
c.tab = THREAD.createTable(name) c.tab = THREAD.createTable(name)
function c:init() function c:init()
self.tab = THREAD.createTable(self.Name) self.tab = THREAD.createTable(self.Name)
setmetatable(self,{ setmetatable(self,{
__index = function(t, k) __index = function(t, k)
return self.tab[k] return self.tab[k]
end, end,
__newindex = function(t,k,v) __newindex = function(t,k,v)
self.tab[k] = v self.tab[k] = v
end end
}) })
return self return self
end end
c.__init = c.init c.__init = c.init
function c:Hold(opt) function c:Hold(opt)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
if opt.key then if opt.key then
return thread.hold(function() return thread.hold(function()
return self.tab[opt.key] return self.tab[opt.key]
end) end)
else else
multi.error("Must provide a key to check opt.key = 'key'") multi.error("Must provide a key to check opt.key = 'key'")
end end
end end
setmetatable(c,{ setmetatable(c,{
__index = function(t, k) __index = function(t, k)
return c.tab[k] return c.tab[k]
end, end,
__newindex = function(t,k,v) __newindex = function(t,k,v)
c.tab[k] = v c.tab[k] = v
end end
}) })
GLOBAL[name] = c GLOBAL[name] = c
self:create(c) self:create(c)
return c return c
end end
local jqc = 1 local jqc = 1
function multi:newSystemThreadedJobQueue(n) function multi:newSystemThreadedJobQueue(n)
local c = {} local c = {}
c.cores = n or THREAD.getCores() c.cores = n or THREAD.getCores()
c.registerQueue = {} c.registerQueue = {}
c.Type = multi.registerType("s_jobqueue") c.Type = multi.registerType("s_jobqueue")
c.funcs = THREAD.createTable("__JobQueue_"..jqc.."_table") c.funcs = THREAD.createTable("__JobQueue_"..jqc.."_table")
c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue") c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue")
c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn") c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn")
c.queueAll = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueAll") c.queueAll = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueAll")
c.id = 0 c.id = 0
c.OnJobCompleted = multi:newConnection() c.OnJobCompleted = multi:newConnection()
local allfunc = 0 local allfunc = 0
function c:doToAll(func) function c:doToAll(func)
for i = 1, self.cores do for i = 1, self.cores do
self.queueAll:push({allfunc, func}) self.queueAll:push({allfunc, func})
end end
allfunc = allfunc + 1 allfunc = allfunc + 1
end end
function c:registerFunction(name, func) function c:registerFunction(name, func)
if self.funcs[name] then if self.funcs[name] then
multi.error("A function by the name "..name.." has already been registered!") multi.error("A function by the name "..name.." has already been registered!")
end end
self.funcs[name] = func self.funcs[name] = func
end end
function c:pushJob(name,...) function c:pushJob(name,...)
self.id = self.id + 1 self.id = self.id + 1
self.queue:push{name,self.id,...} self.queue:push{name,self.id,...}
return self.id return self.id
end end
function c:isEmpty() function c:isEmpty()
return queueJob:peek()==nil return queueJob:peek()==nil
end end
local nFunc = 0 local nFunc = 0
function c:newFunction(name,func,holup) -- This registers with the queue function c:newFunction(name,func,holup) -- This registers with the queue
if type(name)=="function" then if type(name)=="function" then
holup = func holup = func
func = name func = name
name = "JQ_Function_"..nFunc name = "JQ_Function_"..nFunc
end end
nFunc = nFunc + 1 nFunc = nFunc + 1
c:registerFunction(name,func) c:registerFunction(name,func)
return thread:newFunction(function(...) return thread:newFunction(function(...)
local id = c:pushJob(name,...) local id = c:pushJob(name,...)
local link local link
local rets local rets
link = c.OnJobCompleted(function(jid,...) link = c.OnJobCompleted(function(jid,...)
if id==jid then if id==jid then
rets = multi.pack(...) rets = multi.pack(...)
end end
end) end)
return thread.hold(function() return thread.hold(function()
if rets then if rets then
return multi.unpack(rets) or multi.NIL return multi.unpack(rets) or multi.NIL
end end
end) end)
end,holup),name end,holup),name
end end
thread:newThread("jobManager",function() thread:newThread("jobManager",function()
while true do while true do
thread.yield() thread.yield()
local dat = c.queueReturn:pop() local dat = c.queueReturn:pop()
if dat then if dat then
c.OnJobCompleted:Fire(multi.unpack(dat)) c.OnJobCompleted:Fire(multi.unpack(dat))
end end
end end
end) end)
for i=1,c.cores do for i=1,c.cores do
multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc) multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
require("love.timer") require("love.timer")
love.timer.sleep(1) love.timer.sleep(1)
local clock = os.clock local clock = os.clock
local funcs = THREAD.createTable("__JobQueue_"..jqc.."_table") local funcs = THREAD.createTable("__JobQueue_"..jqc.."_table")
local queue = THREAD.waitFor("__JobQueue_"..jqc.."_queue") local queue = THREAD.waitFor("__JobQueue_"..jqc.."_queue")
local queueReturn = THREAD.waitFor("__JobQueue_"..jqc.."_queueReturn") local queueReturn = THREAD.waitFor("__JobQueue_"..jqc.."_queueReturn")
local lastProc = clock() local lastProc = clock()
local queueAll = THREAD.waitFor("__JobQueue_"..jqc.."_queueAll") local queueAll = THREAD.waitFor("__JobQueue_"..jqc.."_queueAll")
local registry = {} local registry = {}
_G["__QR"] = queueReturn _G["__QR"] = queueReturn
setmetatable(_G,{__index = funcs}) setmetatable(_G,{__index = funcs})
thread:newThread("startUp",function() thread:newThread("startUp",function()
while true do while true do
thread.yield() thread.yield()
local all = queueAll:peek() local all = queueAll:peek()
if all and not registry[all[1]] then if all and not registry[all[1]] then
lastProc = os.clock() lastProc = os.clock()
queueAll:pop()[2]() queueAll:pop()[2]()
end end
end end
end) end)
thread:newThread("runner",function() thread:newThread("runner",function()
thread.sleep(.1) thread.sleep(.1)
while true do while true do
thread.yield() thread.yield()
local all = queueAll:peek() local all = queueAll:peek()
if all and not registry[all[1]] then if all and not registry[all[1]] then
lastProc = os.clock() lastProc = os.clock()
queueAll:pop()[2]() queueAll:pop()[2]()
end end
local dat = thread.hold(queue) local dat = thread.hold(queue)
if dat then if dat then
multi:newThread("Test",function() multi:newThread("Test",function()
lastProc = os.clock() lastProc = os.clock()
local name = table.remove(dat,1) local name = table.remove(dat,1)
local id = table.remove(dat,1) local id = table.remove(dat,1)
local tab = {funcs[name](multi.unpack(dat))} local tab = {funcs[name](multi.unpack(dat))}
table.insert(tab,1,id) table.insert(tab,1,id)
--local test = queueReturn.push --local test = queueReturn.push
queueReturn:push(tab) queueReturn:push(tab)
end) end)
end end
end end
end) end)
thread:newThread("Idler",function() thread:newThread("Idler",function()
while true do while true do
thread.yield() thread.yield()
if clock()-lastProc> 2 then if clock()-lastProc> 2 then
THREAD.sleep(.05) THREAD.sleep(.05)
else else
THREAD.sleep(.001) THREAD.sleep(.001)
end end
end end
end) end)
multi:mainloop() multi:mainloop()
end,jqc) end,jqc)
end end
function c:Hold(opt) function c:Hold(opt)
return thread.hold(self.OnJobCompleted) return thread.hold(self.OnJobCompleted)
end end
jqc = jqc + 1 jqc = jqc + 1
self:create(c) self:create(c)
return c return c
end end
+137 -137
View File
@@ -1,137 +1,137 @@
if ISTHREAD then if ISTHREAD then
error("You cannot require the loveManager from within a thread!") error("You cannot require the loveManager from within a thread!")
end end
local ThreadFileData = [[ local ThreadFileData = [[
ISTHREAD = true ISTHREAD = true
args = {...} args = {...}
THREAD_ID = args[1] THREAD_ID = args[1]
THREAD_NAME = args[2] THREAD_NAME = args[2]
GLOBAL, THREAD, DEFER = require("multi.integration.loveManager.threads"):init() GLOBAL, THREAD, DEFER = require("multi.integration.loveManager.threads"):init()
__FUNC = THREAD.unpackValue(args[3]) __FUNC = THREAD.unpackValue(args[3])
ARGS = THREAD.unpackValue(args[4]) ARGS = THREAD.unpackValue(args[4])
settings = args[5] settings = args[5]
if ARGS == nil then ARGS = {} end if ARGS == nil then ARGS = {} end
math.randomseed(THREAD_ID) math.randomseed(THREAD_ID)
math.random() math.random()
math.random() math.random()
math.random() math.random()
stab = THREAD.createTable(THREAD_NAME .. THREAD_ID) stab = THREAD.createTable(THREAD_NAME .. THREAD_ID)
if GLOBAL["__env"] then if GLOBAL["__env"] then
local env = THREAD.getENV() local env = THREAD.getENV()
for i,v in pairs(env) do for i,v in pairs(env) do
_G[i] = v _G[i] = v
end end
end end
multi, thread = require("multi"):init{error=true, warning=true, print=true, priority=true} multi, thread = require("multi"):init{error=true, warning=true, print=true, priority=true}
multi.defaultSettings.print = true multi.defaultSettings.print = true
require("multi.integration.loveManager.extensions") require("multi.integration.loveManager.extensions")
require("multi.integration.sharedExtensions") require("multi.integration.sharedExtensions")
local returns = {pcall(__FUNC, multi.unpack(ARGS))} local returns = {pcall(__FUNC, multi.unpack(ARGS))}
table.remove(returns,1) table.remove(returns,1)
stab["returns"] = returns stab["returns"] = returns
for i,v in pairs(DEFER) do for i,v in pairs(DEFER) do
pcall(v) pcall(v)
end end
]] ]]
_G.THREAD_NAME = "MAIN_THREAD" _G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0 _G.THREAD_ID = 0
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local GLOBAL, THREAD = require("multi.integration.loveManager.threads"):init() local GLOBAL, THREAD = require("multi.integration.loveManager.threads"):init()
multi.registerType("s_function") multi.registerType("s_function")
multi.registerType("s_thread") multi.registerType("s_thread")
multi.integration = {} multi.integration = {}
multi.isMainThread = true multi.isMainThread = true
local threads = {} local threads = {}
local tid = 0 local tid = 0
function multi:newSystemThread(name, func, ...) function multi:newSystemThread(name, func, ...)
multi.InitSystemThreadErrorHandler() multi.InitSystemThreadErrorHandler()
local name = name or multi.randomString(16) local name = name or multi.randomString(16)
tid = tid + 1 tid = tid + 1
local c = {} local c = {}
c.Type = multi.STHREAD c.Type = multi.STHREAD
c.Name = name c.Name = name
c.ID = tid c.ID = tid
c.thread = love.thread.newThread(ThreadFileData) c.thread = love.thread.newThread(ThreadFileData)
c.thread:start(c.ID, c.Name, THREAD.packValue(func), THREAD.packValue({...}), multi.defaultSettings) c.thread:start(c.ID, c.Name, THREAD.packValue(func), THREAD.packValue({...}), multi.defaultSettings)
c.stab = THREAD.createTable(name .. c.ID) c.stab = THREAD.createTable(name .. c.ID)
c.creationTime = os.clock() c.creationTime = os.clock()
c.OnDeath = multi:newConnection() c.OnDeath = multi:newConnection()
c.OnError = multi:newConnection() c.OnError = multi:newConnection()
c.status_channel = love.thread.getChannel("__status_channel__" .. c.ID) c.status_channel = love.thread.getChannel("__status_channel__" .. c.ID)
function c:getName() return c.name end function c:getName() return c.name end
table.insert(threads, c) table.insert(threads, c)
c.OnError(multi.error) c.OnError(multi.error)
if self.isActor then if self.isActor then
self:create(c) self:create(c)
else else
multi.create(multi, c) multi.create(multi, c)
end end
return c return c
end end
local started = false local started = false
local console_channel = love.thread.getChannel("__console_channel__") local console_channel = love.thread.getChannel("__console_channel__")
function THREAD:newFunction(func, holdme) function THREAD:newFunction(func, holdme)
return thread:newFunctionBase(function(...) return thread:newFunctionBase(function(...)
return multi:newSystemThread("SystemThreaded Function Handler", func, ...) return multi:newSystemThread("SystemThreaded Function Handler", func, ...)
end, holdme, multi.SFUNCTION)() end, holdme, multi.SFUNCTION)()
end end
function love.threaderror(thread, errorstr) function love.threaderror(thread, errorstr)
multi.error("Thread error! " .. errorstr) multi.error("Thread error! " .. errorstr)
end end
function multi.InitSystemThreadErrorHandler() function multi.InitSystemThreadErrorHandler()
if started == true then return end if started == true then return end
started = true started = true
thread:newThread("Love System Thread Handler", function() thread:newThread("Love System Thread Handler", function()
while true do while true do
thread.yield() thread.yield()
for i = #threads, 1, -1 do for i = #threads, 1, -1 do
local th = threads[i] local th = threads[i]
if th.status_channel:peek() ~= nil then if th.status_channel:peek() ~= nil then
th.statusconnector:Fire(multi.unpack(th.status_channel:pop())) th.statusconnector:Fire(multi.unpack(th.status_channel:pop()))
end end
local th_err = th.thread:getError() local th_err = th.thread:getError()
if th_err == "Thread Killed!\1" then if th_err == "Thread Killed!\1" then
th.OnDeath:Fire("Thread Killed!") th.OnDeath:Fire("Thread Killed!")
table.remove(threads, i) table.remove(threads, i)
elseif th_err then elseif th_err then
th.OnError:Fire(th, th_err) th.OnError:Fire(th, th_err)
table.remove(threads, i) table.remove(threads, i)
elseif th.stab.returns then elseif th.stab.returns then
th.OnDeath:Fire(multi.unpack(th.stab.returns)) th.OnDeath:Fire(multi.unpack(th.stab.returns))
th.stab.returns = nil th.stab.returns = nil
table.remove(threads, i) table.remove(threads, i)
end end
end end
end end
end) end)
end end
THREAD.newSystemThread = function(...) THREAD.newSystemThread = function(...)
multi:newSystemThread(...) multi:newSystemThread(...)
end end
multi.integration.GLOBAL = GLOBAL multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD multi.integration.THREAD = THREAD
require("multi.integration.loveManager.extensions") require("multi.integration.loveManager.extensions")
require("multi.integration.sharedExtensions") require("multi.integration.sharedExtensions")
multi.print("Integrated Love Threading!") multi.print("Integrated Love Threading!")
return { return {
init = function() init = function()
return GLOBAL, THREAD return GLOBAL, THREAD
end end
} }
+227 -227
View File
@@ -1,228 +1,228 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
require("love.timer") require("love.timer")
require("love.system") require("love.system")
require("love.data") require("love.data")
require("love.thread") require("love.thread")
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
-- Checks if the given value is a LOVE2D object (i.e. has metatable with __index field) and if that __index field contains functions typical of LOVE2D objects -- Checks if the given value is a LOVE2D object (i.e. has metatable with __index field) and if that __index field contains functions typical of LOVE2D objects
function isLoveObject(value) function isLoveObject(value)
-- Check if the value has metatable -- Check if the value has metatable
if type(value) == "userdata" and getmetatable(value) then if type(value) == "userdata" and getmetatable(value) then
-- Check if the metatable has the __index field -- Check if the metatable has the __index field
local index = getmetatable(value).__index local index = getmetatable(value).__index
if type(index) == "table" then if type(index) == "table" then
-- Check if the metatable's __index table contains functions typical of LOVE2D objects -- Check if the metatable's __index table contains functions typical of LOVE2D objects
if index.draw or index.update or index.getWidth or index.getHeight or index.getString or index.getPointer then if index.draw or index.update or index.getWidth or index.getHeight or index.getString or index.getPointer then
return true return true
end end
end end
end end
return false return false
end end
-- Converts any function values in a table to a string with the value "\1\2:func:<function_string>" where <function_string> is the Lua stringified version of the function -- Converts any function values in a table to a string with the value "\1\2:func:<function_string>" where <function_string> is the Lua stringified version of the function
function tableToFunctionString(t) function tableToFunctionString(t)
if type(t) == "nil" then return "\1\2:nil:" end if type(t) == "nil" then return "\1\2:nil:" end
if type(t) == "function" then return "\1\2:func:"..string.dump(t) end if type(t) == "function" then return "\1\2:func:"..string.dump(t) end
if type(t) ~= "table" then return t end if type(t) ~= "table" then return t end
local newtable = {} local newtable = {}
for k, v in pairs(t) do for k, v in pairs(t) do
if type(v) == "function" then if type(v) == "function" then
newtable[k] = "\1\2:func:"..string.dump(v) newtable[k] = "\1\2:func:"..string.dump(v)
elseif type(v) == "table" then elseif type(v) == "table" then
newtable[k] = tableToFunctionString(v) newtable[k] = tableToFunctionString(v)
elseif isLoveObject(v) then elseif isLoveObject(v) then
newtable[k] = v newtable[k] = v
elseif type(v) == "userdata" then elseif type(v) == "userdata" then
newtable[k] = tostring(v) newtable[k] = tostring(v)
else else
newtable[k] = v newtable[k] = v
end end
end end
return newtable return newtable
end end
-- Converts strings with the value "\1\2:func:<function_string>" back to functions -- Converts strings with the value "\1\2:func:<function_string>" back to functions
function functionStringToTable(t) function functionStringToTable(t)
if type(t) == "string" and t:sub(1, 8) == "\1\2:func:" then return loadstring(t:sub(9, -1)) end if type(t) == "string" and t:sub(1, 8) == "\1\2:func:" then return loadstring(t:sub(9, -1)) end
if type(t) == "string" and t:sub(1, 7) == "\1\2:nil:" then return nil end if type(t) == "string" and t:sub(1, 7) == "\1\2:nil:" then return nil end
if type(t) ~= "table" then return t end if type(t) ~= "table" then return t end
for k, v in pairs(t) do for k, v in pairs(t) do
if type(v) == "string" then if type(v) == "string" then
if v:sub(1, 8) == "\1\2:func:" then if v:sub(1, 8) == "\1\2:func:" then
t[k] = loadstring(v:sub(9, -1)) t[k] = loadstring(v:sub(9, -1))
else else
t[k] = v t[k] = v
end end
elseif type(v) == "table" then elseif type(v) == "table" then
t[k] = functionStringToTable(v) t[k] = functionStringToTable(v)
else else
t[k] = v t[k] = v
end end
end end
if t.init then if t.init then
t:init() t:init()
end end
return t return t
end end
local function packValue(t) local function packValue(t)
return tableToFunctionString(t) return tableToFunctionString(t)
end end
local function unpackValue(t) local function unpackValue(t)
return functionStringToTable(t) return functionStringToTable(t)
end end
local function createTable(n) local function createTable(n)
if not n then if not n then
n = "STAB"..multi.randomString(8) n = "STAB"..multi.randomString(8)
end end
local __proxy = {} local __proxy = {}
local function set(name, val) local function set(name, val)
local chan = love.thread.getChannel(n .. name) local chan = love.thread.getChannel(n .. name)
if chan:getCount() == 1 then chan:pop() end if chan:getCount() == 1 then chan:pop() end
__proxy[name] = true __proxy[name] = true
chan:push(packValue(val)) chan:push(packValue(val))
end end
local function get(name) local function get(name)
return unpackValue(love.thread.getChannel(n .. name):peek()) return unpackValue(love.thread.getChannel(n .. name):peek())
-- if type(data) == "table" and data.init then -- if type(data) == "table" and data.init then
-- return data:init() -- return data:init()
-- else -- else
-- return data -- return data
-- end -- end
end end
return setmetatable({}, return setmetatable({},
{ {
__index = function(t, k) __index = function(t, k)
return get(k) return get(k)
end, end,
__newindex = function(t, k, v) __newindex = function(t, k, v)
set(k,v) set(k,v)
end end
} }
) )
end end
function INIT() function INIT()
local GLOBAL, THREAD, DEFER = createTable("__GLOBAL__"), {}, {} local GLOBAL, THREAD, DEFER = createTable("__GLOBAL__"), {}, {}
local status_channel, console_channel = love.thread.getChannel("__status_channel__" .. THREAD_ID), local status_channel, console_channel = love.thread.getChannel("__status_channel__" .. THREAD_ID),
love.thread.getChannel("__console_channel__") love.thread.getChannel("__console_channel__")
-- Non portable methods, shouldn't be used unless you know what you are doing -- Non portable methods, shouldn't be used unless you know what you are doing
THREAD.packValue = packValue THREAD.packValue = packValue
THREAD.unpackValue = unpackValue THREAD.unpackValue = unpackValue
THREAD.createTable = createTable THREAD.createTable = createTable
function THREAD.set(name, val) function THREAD.set(name, val)
GLOBAL[name] = val GLOBAL[name] = val
end end
function THREAD.get(name, val) function THREAD.get(name, val)
return GLOBAL[name] return GLOBAL[name]
end end
THREAD.waitFor = thread:newFunction(function(name) THREAD.waitFor = thread:newFunction(function(name)
local function wait() local function wait()
math.randomseed(os.time()) math.randomseed(os.time())
thread.yield() thread.yield()
end end
repeat repeat
wait() wait()
until GLOBAL[name] ~= nil until GLOBAL[name] ~= nil
return GLOBAL[name] return GLOBAL[name]
end, true) end, true)
function THREAD.getCores() function THREAD.getCores()
return love.system.getProcessorCount() return love.system.getProcessorCount()
end end
function THREAD.getConsole() function THREAD.getConsole()
local c = {} local c = {}
c.queue = console_channel c.queue = console_channel
function c.print(...) function c.print(...)
c.queue:push(table.concat(multi.pack(...), "\t")) c.queue:push(table.concat(multi.pack(...), "\t"))
end end
function c.error(err) function c.error(err)
c.queue:push("Error in <"..THREAD_NAME..":" .. THREAD_ID .. ">: ".. err) c.queue:push("Error in <"..THREAD_NAME..":" .. THREAD_ID .. ">: ".. err)
multi.error(err) multi.error(err)
end end
return c return c
end end
function THREAD.getThreads() function THREAD.getThreads()
-- --
end end
function THREAD.kill() -- trigger the lane destruction function THREAD.kill() -- trigger the lane destruction
error("Thread was killed!\1") error("Thread was killed!\1")
end end
function THREAD.pushStatus(...) function THREAD.pushStatus(...)
status_channel:push(multi.pack(...)) status_channel:push(multi.pack(...))
end end
function THREAD.sleep(n) function THREAD.sleep(n)
love.timer.sleep(n) love.timer.sleep(n)
end end
THREAD.hold = thread:newFunction(function(n) THREAD.hold = thread:newFunction(function(n)
thread.hold(n) thread.hold(n)
end, true) end, true)
function THREAD.setENV(env, name) function THREAD.setENV(env, name)
GLOBAL[name or "__env"] = env GLOBAL[name or "__env"] = env
end end
function THREAD.getENV(name) function THREAD.getENV(name)
return GLOBAL[name or "__env"] return GLOBAL[name or "__env"]
end end
function THREAD.exposeENV(name) function THREAD.exposeENV(name)
name = name or "__env" name = name or "__env"
local env = THREAD.getENV(name) local env = THREAD.getENV(name)
for i,v in pairs(env) do for i,v in pairs(env) do
_G[i] = v _G[i] = v
end end
end end
function THREAD.defer(func) function THREAD.defer(func)
table.insert(DEFER, func) table.insert(DEFER, func)
end end
function THREAD.sync() function THREAD.sync()
-- Maybe do something... -- Maybe do something...
end end
return GLOBAL, THREAD, DEFER return GLOBAL, THREAD, DEFER
end end
return { return {
init = function() init = function()
return INIT() return INIT()
end end
} }
+203 -203
View File
@@ -1,204 +1,204 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi").init() local multi, thread = require("multi").init()
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local c = {} local c = {}
c.Name = name c.Name = name
local fRef = {"func",nil} local fRef = {"func",nil}
function c:init() function c:init()
local q = {} local q = {}
q.chan = lovr.thread.getChannel(self.Name) q.chan = lovr.thread.getChannel(self.Name)
function q:push(dat) function q:push(dat)
if type(dat) == "function" then if type(dat) == "function" then
fRef[2] = THREAD.dump(dat) fRef[2] = THREAD.dump(dat)
self.chan:push(fRef) self.chan:push(fRef)
return return
else else
self.chan:push(dat) self.chan:push(dat)
end end
end end
function q:pop() function q:pop()
local dat = self.chan:pop() local dat = self.chan:pop()
if type(dat)=="table" and dat[1]=="func" then if type(dat)=="table" and dat[1]=="func" then
return THREAD.loadDump(dat[2]) return THREAD.loadDump(dat[2])
else else
return dat return dat
end end
end end
function q:peek() function q:peek()
local dat = self.chan:peek() local dat = self.chan:peek()
if type(dat)=="table" and dat[1]=="func" then if type(dat)=="table" and dat[1]=="func" then
return THREAD.loadDump(dat[2]) return THREAD.loadDump(dat[2])
else else
return dat return dat
end end
end end
return q return q
end end
THREAD.package(name,c) THREAD.package(name,c)
return c return c
end end
function multi:newSystemThreadedTable(name) function multi:newSystemThreadedTable(name)
local c = {} local c = {}
c.name = name c.name = name
function c:init() function c:init()
return THREAD.createTable(self.name) return THREAD.createTable(self.name)
end end
THREAD.package(name,c) THREAD.package(name,c)
return c return c
end end
local jqc = 1 local jqc = 1
function multi:newSystemThreadedJobQueue(n) function multi:newSystemThreadedJobQueue(n)
local c = {} local c = {}
c.cores = n or THREAD.getCores() c.cores = n or THREAD.getCores()
c.registerQueue = {} c.registerQueue = {}
c.funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table") c.funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table")
c.queue = lovr.thread.getChannel("__JobQueue_"..jqc.."_queue") c.queue = lovr.thread.getChannel("__JobQueue_"..jqc.."_queue")
c.queueReturn = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueReturn") c.queueReturn = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueReturn")
c.queueAll = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueAll") c.queueAll = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueAll")
c.id = 0 c.id = 0
c.OnJobCompleted = multi:newConnection() c.OnJobCompleted = multi:newConnection()
local allfunc = 0 local allfunc = 0
function c:doToAll(func) function c:doToAll(func)
local f = THREAD.dump(func) local f = THREAD.dump(func)
for i = 1, self.cores do for i = 1, self.cores do
self.queueAll:push({allfunc,f}) self.queueAll:push({allfunc,f})
end end
allfunc = allfunc + 1 allfunc = allfunc + 1
end end
function c:registerFunction(name,func) function c:registerFunction(name,func)
if self.funcs[name] then if self.funcs[name] then
error("A function by the name "..name.." has already been registered!") error("A function by the name "..name.." has already been registered!")
end end
self.funcs[name] = func self.funcs[name] = func
end end
function c:pushJob(name,...) function c:pushJob(name,...)
self.id = self.id + 1 self.id = self.id + 1
self.queue:push{name,self.id,...} self.queue:push{name,self.id,...}
return self.id return self.id
end end
function c:isEmpty() function c:isEmpty()
return queueJob:peek()==nil return queueJob:peek()==nil
end end
local nFunc = 0 local nFunc = 0
function c:newFunction(name,func,holup) -- This registers with the queue function c:newFunction(name,func,holup) -- This registers with the queue
if type(name)=="function" then if type(name)=="function" then
holup = func holup = func
func = name func = name
name = "JQ_Function_"..nFunc name = "JQ_Function_"..nFunc
end end
nFunc = nFunc + 1 nFunc = nFunc + 1
c:registerFunction(name,func) c:registerFunction(name,func)
return thread:newFunction(function(...) return thread:newFunction(function(...)
local id = c:pushJob(name,...) local id = c:pushJob(name,...)
local link local link
local rets local rets
link = c.OnJobCompleted(function(jid,...) link = c.OnJobCompleted(function(jid,...)
if id==jid then if id==jid then
rets = multi.pack(...) rets = multi.pack(...)
link:Destroy() link:Destroy()
end end
end) end)
return thread.hold(function() return thread.hold(function()
if rets then if rets then
return multi.unpack(rets) or multi.NIL return multi.unpack(rets) or multi.NIL
end end
end) end)
end,holup),name end,holup),name
end end
thread:newThread("jobManager",function() thread:newThread("jobManager",function()
while true do while true do
thread.yield() thread.yield()
local dat = c.queueReturn:pop() local dat = c.queueReturn:pop()
if dat then if dat then
c.OnJobCompleted:Fire(multi.unpack(dat)) c.OnJobCompleted:Fire(multi.unpack(dat))
end end
end end
end) end)
for i=1,c.cores do for i=1,c.cores do
multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc) multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
require("lovr.timer") require("lovr.timer")
local function atomic(channel) local function atomic(channel)
return channel:pop() return channel:pop()
end end
local clock = os.clock local clock = os.clock
local funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table") local funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table")
local queue = lovr.thread.getChannel("__JobQueue_"..jqc.."_queue") local queue = lovr.thread.getChannel("__JobQueue_"..jqc.."_queue")
local queueReturn = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueReturn") local queueReturn = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueReturn")
local lastProc = clock() local lastProc = clock()
local queueAll = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueAll") local queueAll = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueAll")
local registry = {} local registry = {}
_G["__QR"] = queueReturn _G["__QR"] = queueReturn
setmetatable(_G,{__index = funcs}) setmetatable(_G,{__index = funcs})
thread:newThread("startUp",function() thread:newThread("startUp",function()
while true do while true do
thread.yield() thread.yield()
local all = queueAll:peek() local all = queueAll:peek()
if all and not registry[all[1]] then if all and not registry[all[1]] then
lastProc = os.clock() lastProc = os.clock()
THREAD.loadDump(queueAll:pop()[2])() THREAD.loadDump(queueAll:pop()[2])()
end end
end end
end) end)
thread:newThread("runner",function() thread:newThread("runner",function()
thread.sleep(.1) thread.sleep(.1)
while true do while true do
thread.yield() thread.yield()
local all = queueAll:peek() local all = queueAll:peek()
if all and not registry[all[1]] then if all and not registry[all[1]] then
lastProc = os.clock() lastProc = os.clock()
THREAD.loadDump(queueAll:pop()[2])() THREAD.loadDump(queueAll:pop()[2])()
end end
local dat = queue:performAtomic(atomic) local dat = queue:performAtomic(atomic)
if dat then if dat then
lastProc = os.clock() lastProc = os.clock()
local name = table.remove(dat,1) local name = table.remove(dat,1)
local id = table.remove(dat,1) local id = table.remove(dat,1)
local tab = {funcs[name](multi.unpack(dat))} local tab = {funcs[name](multi.unpack(dat))}
table.insert(tab,1,id) table.insert(tab,1,id)
queueReturn:push(tab) queueReturn:push(tab)
end end
end end
end):OnError(function(...) end):OnError(function(...)
error(...) error(...)
end) end)
thread:newThread("Idler",function() thread:newThread("Idler",function()
while true do while true do
thread.yield() thread.yield()
if clock()-lastProc> 2 then if clock()-lastProc> 2 then
THREAD.sleep(.05) THREAD.sleep(.05)
else else
THREAD.sleep(.001) THREAD.sleep(.001)
end end
end end
end) end)
multi:mainloop() multi:mainloop()
end,jqc) end,jqc)
end end
jqc = jqc + 1 jqc = jqc + 1
return c return c
end end
+97 -97
View File
@@ -1,98 +1,98 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
-- TODO make compatible with lovr -- TODO make compatible with lovr
if ISTHREAD then if ISTHREAD then
error("You cannot require the lovrManager from within a thread!") error("You cannot require the lovrManager from within a thread!")
end end
local ThreadFileData = [[ local ThreadFileData = [[
ISTHREAD = true ISTHREAD = true
THREAD = require("multi.integration.lovrManager.threads") -- order is important! THREAD = require("multi.integration.lovrManager.threads") -- order is important!
sThread = THREAD sThread = THREAD
__IMPORTS = {...} __IMPORTS = {...}
__FUNC__=table.remove(__IMPORTS,1) __FUNC__=table.remove(__IMPORTS,1)
__THREADID__=table.remove(__IMPORTS,1) __THREADID__=table.remove(__IMPORTS,1)
__THREADNAME__=table.remove(__IMPORTS,1) __THREADNAME__=table.remove(__IMPORTS,1)
stab = THREAD.createStaticTable(__THREADNAME__) stab = THREAD.createStaticTable(__THREADNAME__)
GLOBAL = THREAD.getGlobal() GLOBAL = THREAD.getGlobal()
multi, thread = require("multi").init() multi, thread = require("multi").init()
stab["returns"] = {THREAD.loadDump(__FUNC__)(multi.unpack(__IMPORTS))} stab["returns"] = {THREAD.loadDump(__FUNC__)(multi.unpack(__IMPORTS))}
]] ]]
local multi, thread = require("multi.compat.lovr2d"):init() local multi, thread = require("multi.compat.lovr2d"):init()
local THREAD = {} local THREAD = {}
__THREADID__ = 0 __THREADID__ = 0
__THREADNAME__ = "MainThread" __THREADNAME__ = "MainThread"
_G.THREAD_NAME = "MAIN_THREAD" _G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0 _G.THREAD_ID = 0
multi.integration={} multi.integration={}
multi.integration.lovr2d={} multi.integration.lovr2d={}
local THREAD = require("multi.integration.lovrManager.threads") local THREAD = require("multi.integration.lovrManager.threads")
local GLOBAL = THREAD.getGlobal() local GLOBAL = THREAD.getGlobal()
local THREAD_ID = 1 local THREAD_ID = 1
local OBJECT_ID = 0 local OBJECT_ID = 0
local stf = 0 local stf = 0
function THREAD:newFunction(func,holup) function THREAD:newFunction(func,holup)
stf = stf + 1 stf = stf + 1
return function(...) return function(...)
local t = multi:newSystemThread("STF"..stf,func,...) local t = multi:newSystemThread("STF"..stf,func,...)
return thread:newFunction(function() return thread:newFunction(function()
return thread.hold(function() return thread.hold(function()
if t.stab["returns"] then if t.stab["returns"] then
local dat = t.stab.returns local dat = t.stab.returns
t.stab.returns = nil t.stab.returns = nil
return multi.unpack(dat) return multi.unpack(dat)
end end
end) end)
end,holup)() end,holup)()
end end
end end
function multi:newSystemThread(name,func,...) function multi:newSystemThread(name,func,...)
local c = {} local c = {}
c.name = name c.name = name
c.ID=THREAD_ID c.ID=THREAD_ID
c.thread=lovr.thread.newThread(ThreadFileData) c.thread=lovr.thread.newThread(ThreadFileData)
c.thread:start(THREAD.dump(func),c.ID,c.name,...) c.thread:start(THREAD.dump(func),c.ID,c.name,...)
c.stab = THREAD.createStaticTable(name) c.stab = THREAD.createStaticTable(name)
GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread} GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread}
GLOBAL["__THREAD_COUNT"] = THREAD_ID GLOBAL["__THREAD_COUNT"] = THREAD_ID
THREAD_ID=THREAD_ID+1 THREAD_ID=THREAD_ID+1
if self.isActor then if self.isActor then
self:create(c) self:create(c)
else else
multi.create(multi, c) multi.create(multi, c)
end end
return c return c
end end
THREAD.newSystemThread = multi.newSystemThread THREAD.newSystemThread = multi.newSystemThread
function lovr.threaderror(thread, errorstr) function lovr.threaderror(thread, errorstr)
multi.print("Thread error!\n"..errorstr) multi.print("Thread error!\n"..errorstr)
end end
multi.integration.GLOBAL = GLOBAL multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD multi.integration.THREAD = THREAD
require("multi.integration.lovrManager.extensions") require("multi.integration.lovrManager.extensions")
multi.print("Integrated lovr Threading!") multi.print("Integrated lovr Threading!")
return {init=function() return {init=function()
return GLOBAL,THREAD return GLOBAL,THREAD
end} end}
+221 -221
View File
@@ -1,222 +1,222 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
-- TODO make compatible with lovr -- TODO make compatible with lovr
require("lovr.timer") require("lovr.timer")
require("lovr.system") require("lovr.system")
require("lovr.data") require("lovr.data")
local socket = require("socket") local socket = require("socket")
local multi, thread = require("multi").init() local multi, thread = require("multi").init()
local threads = {} local threads = {}
function threads.loadDump(d) function threads.loadDump(d)
return loadstring(d:getString()) return loadstring(d:getString())
end end
function threads.dump(func) function threads.dump(func)
return lovr.data.newByteData(string.dump(func)) return lovr.data.newByteData(string.dump(func))
end end
local fRef = {"func",nil} local fRef = {"func",nil}
local function manage(channel, value) local function manage(channel, value)
channel:clear() channel:clear()
if type(value) == "function" then if type(value) == "function" then
fRef[2] = THREAD.dump(value) fRef[2] = THREAD.dump(value)
channel:push(fRef) channel:push(fRef)
return return
else else
channel:push(value) channel:push(value)
end end
end end
local function RandomVariable(length) local function RandomVariable(length)
local res = {} local res = {}
math.randomseed(socket.gettime()*10000) math.randomseed(socket.gettime()*10000)
for i = 1, length do for i = 1, length do
res[#res+1] = string.char(math.random(97, 122)) res[#res+1] = string.char(math.random(97, 122))
end end
return table.concat(res) return table.concat(res)
end end
local GNAME = "__GLOBAL_" local GNAME = "__GLOBAL_"
local proxy = {} local proxy = {}
function threads.set(name,val) function threads.set(name,val)
if not proxy[name] then proxy[name] = lovr.thread.getChannel(GNAME..name) end if not proxy[name] then proxy[name] = lovr.thread.getChannel(GNAME..name) end
proxy[name]:performAtomic(manage, val) proxy[name]:performAtomic(manage, val)
end end
function threads.get(name) function threads.get(name)
if not proxy[name] then proxy[name] = lovr.thread.getChannel(GNAME..name) end if not proxy[name] then proxy[name] = lovr.thread.getChannel(GNAME..name) end
local dat = proxy[name]:peek() local dat = proxy[name]:peek()
if type(dat)=="table" and dat[1]=="func" then if type(dat)=="table" and dat[1]=="func" then
return THREAD.loadDump(dat[2]) return THREAD.loadDump(dat[2])
else else
return dat return dat
end end
end end
function threads.waitFor(name) function threads.waitFor(name)
if thread.isThread() then if thread.isThread() then
return thread.hold(function() return thread.hold(function()
return threads.get(name) return threads.get(name)
end) end)
end end
while threads.get(name)==nil do while threads.get(name)==nil do
lovr.timer.sleep(.001) lovr.timer.sleep(.001)
end end
local dat = threads.get(name) local dat = threads.get(name)
if type(dat) == "table" and dat.init then if type(dat) == "table" and dat.init then
dat.init = threads.loadDump(dat.init) dat.init = threads.loadDump(dat.init)
end end
return dat return dat
end end
function threads.package(name,val) function threads.package(name,val)
local init = val.init local init = val.init
val.init=threads.dump(val.init) val.init=threads.dump(val.init)
GLOBAL[name]=val GLOBAL[name]=val
val.init=init val.init=init
end end
function threads.getCores() function threads.getCores()
return lovr.system.getProcessorCount() return lovr.system.getProcessorCount()
end end
function threads.kill() function threads.kill()
error("Thread Killed!") error("Thread Killed!")
end end
function threads.getThreads() function threads.getThreads()
local t = {} local t = {}
for i=1,GLOBAL["__THREAD_COUNT"] do for i=1,GLOBAL["__THREAD_COUNT"] do
t[#t+1]=GLOBAL["__THREAD_"..i] t[#t+1]=GLOBAL["__THREAD_"..i]
end end
return t return t
end end
function threads.getThread(n) function threads.getThread(n)
return GLOBAL["__THREAD_"..n] return GLOBAL["__THREAD_"..n]
end end
function threads.getName() function threads.getName()
return __THREADNAME__ return __THREADNAME__
end end
function threads.getID() function threads.getID()
return __THREADID__ return __THREADID__
end end
function threads.sleep(n) function threads.sleep(n)
lovr.timer.sleep(n) lovr.timer.sleep(n)
end end
function threads.getGlobal() function threads.getGlobal()
return setmetatable({}, return setmetatable({},
{ {
__index = function(t, k) __index = function(t, k)
return THREAD.get(k) return THREAD.get(k)
end, end,
__newindex = function(t, k, v) __newindex = function(t, k, v)
THREAD.set(k,v) THREAD.set(k,v)
end end
} }
) )
end end
function threads.createTable(n) function threads.createTable(n)
local _proxy = {} local _proxy = {}
local function set(name,val) local function set(name,val)
if not _proxy[name] then _proxy[name] = lovr.thread.getChannel(n..name) end if not _proxy[name] then _proxy[name] = lovr.thread.getChannel(n..name) end
_proxy[name]:performAtomic(manage, val) _proxy[name]:performAtomic(manage, val)
end end
local function get(name) local function get(name)
if not _proxy[name] then _proxy[name] = lovr.thread.getChannel(n..name) end if not _proxy[name] then _proxy[name] = lovr.thread.getChannel(n..name) end
local dat = _proxy[name]:peek() local dat = _proxy[name]:peek()
if type(dat)=="table" and dat[1]=="func" then if type(dat)=="table" and dat[1]=="func" then
return THREAD.loadDump(dat[2]) return THREAD.loadDump(dat[2])
else else
return dat return dat
end end
end end
return setmetatable({}, return setmetatable({},
{ {
__index = function(t, k) __index = function(t, k)
return get(k) return get(k)
end, end,
__newindex = function(t, k, v) __newindex = function(t, k, v)
set(k,v) set(k,v)
end end
} }
) )
end end
function threads.getConsole() function threads.getConsole()
local c = {} local c = {}
c.queue = lovr.thread.getChannel("__CONSOLE__") c.queue = lovr.thread.getChannel("__CONSOLE__")
function c.print(...) function c.print(...)
c.queue:push(multi.pack(...)) c.queue:push(multi.pack(...))
end end
function c.error(err) function c.error(err)
c.queue:push{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__} c.queue:push{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__}
error(err) error(err)
end end
return c return c
end end
if not ISTHREAD then if not ISTHREAD then
local clock = os.clock local clock = os.clock
local lastproc = clock() local lastproc = clock()
local queue = lovr.thread.getChannel("__CONSOLE__") local queue = lovr.thread.getChannel("__CONSOLE__")
thread:newThread("consoleManager",function() thread:newThread("consoleManager",function()
while true do while true do
thread.yield() thread.yield()
dat = queue:pop() dat = queue:pop()
if dat then if dat then
lastproc = clock() lastproc = clock()
print(multi.unpack(dat)) print(multi.unpack(dat))
end end
if clock()-lastproc>2 then if clock()-lastproc>2 then
thread.sleep(.1) thread.sleep(.1)
end end
end end
end) end)
end end
function threads.createStaticTable(n) function threads.createStaticTable(n)
local __proxy = {} local __proxy = {}
local function set(name,val) local function set(name,val)
if __proxy[name] then return end if __proxy[name] then return end
local chan = lovr.thread.getChannel(n..name) local chan = lovr.thread.getChannel(n..name)
if chan:getCount()>0 then return end if chan:getCount()>0 then return end
chan:performAtomic(manage, val) chan:performAtomic(manage, val)
__proxy[name] = val __proxy[name] = val
end end
local function get(name) local function get(name)
if __proxy[name] then return __proxy[name] end if __proxy[name] then return __proxy[name] end
local dat = lovr.thread.getChannel(n..name):peek() local dat = lovr.thread.getChannel(n..name):peek()
if type(dat)=="table" and dat[1]=="func" then if type(dat)=="table" and dat[1]=="func" then
__proxy[name] = THREAD.loadDump(dat[2]) __proxy[name] = THREAD.loadDump(dat[2])
return __proxy[name] return __proxy[name]
else else
__proxy[name] = dat __proxy[name] = dat
return __proxy[name] return __proxy[name]
end end
end end
return setmetatable({}, return setmetatable({},
{ {
__index = function(t, k) __index = function(t, k)
return get(k) return get(k)
end, end,
__newindex = function(t, k, v) __newindex = function(t, k, v)
set(k,v) set(k,v)
end end
} }
) )
end end
function threads.hold(n) function threads.hold(n)
local dat local dat
while not(dat) do while not(dat) do
dat = n() dat = n()
end end
end end
return threads return threads
+138 -138
View File
@@ -1,138 +1,138 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
-- This module probably will not be maintained any longer! -- This module probably will not be maintained any longer!
package.path = "?/init.lua;?.lua;" .. package.path package.path = "?/init.lua;?.lua;" .. package.path
local function _INIT(luvitThread, timer) local function _INIT(luvitThread, timer)
-- lots of this stuff should be able to stay the same -- lots of this stuff should be able to stay the same
function os.getOS() function os.getOS()
if package.config:sub(1, 1) == "\\" then if package.config:sub(1, 1) == "\\" then
return "windows" return "windows"
else else
return "unix" return "unix"
end end
end end
-- Step 1 get setup threads on luvit... Sigh how do i even... -- Step 1 get setup threads on luvit... Sigh how do i even...
local multi, thread = require("multi").init() local multi, thread = require("multi").init()
multi.isMainThread = true multi.isMainThread = true
function multi:canSystemThread() function multi:canSystemThread()
return true return true
end end
function multi:getPlatform() function multi:getPlatform()
return "luvit" return "luvit"
end end
local multi = multi local multi = multi
-- Step 2 set up the Global table... is this possible? -- Step 2 set up the Global table... is this possible?
local GLOBAL = {} local GLOBAL = {}
setmetatable( setmetatable(
GLOBAL, GLOBAL,
{ {
__index = function(t, k) __index = function(t, k)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
return nil return nil
end, end,
__newindex = function(t, k, v) __newindex = function(t, k, v)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
} }
) )
local THREAD = {} local THREAD = {}
function THREAD.set(name, val) function THREAD.set(name, val)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
function THREAD.get(name) function THREAD.get(name)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
local function randomString(n) local function randomString(n)
local str = "" 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"} 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 for i = 1, n do
str = str .. "" .. strings[math.random(1, #strings)] str = str .. "" .. strings[math.random(1, #strings)]
end end
return str return str
end end
function THREAD.waitFor(name) function THREAD.waitFor(name)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
function THREAD.testFor(name, val, sym) function THREAD.testFor(name, val, sym)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
function THREAD.getCores() function THREAD.getCores()
return THREAD.__CORES return THREAD.__CORES
end end
if os.getOS() == "windows" then if os.getOS() == "windows" then
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
else else
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
end end
function THREAD.kill() -- trigger the thread destruction function THREAD.kill() -- trigger the thread destruction
error("Thread was Killed!") error("Thread was Killed!")
end end
-- hmmm if im cleaver I can get this to work... but since data passing isn't going to be a thing its probably not important -- hmmm if im cleaver I can get this to work... but since data passing isn't going to be a thing its probably not important
function THREAD.sleep(n) function THREAD.sleep(n)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
function THREAD.hold(n) function THREAD.hold(n)
--print("No Global table when using luvit integration!") --print("No Global table when using luvit integration!")
end end
-- Step 5 Basic Threads! -- Step 5 Basic Threads!
local function entry(path, name, func, ...) local function entry(path, name, func, ...)
local timer = require "timer" local timer = require "timer"
local luvitThread = require "thread" local luvitThread = require "thread"
package.path = path package.path = path
loadstring(func)(...) loadstring(func)(...)
end end
function multi:newSystemThread(name, func, ...) function multi:newSystemThread(name, func, ...)
local c = {} local c = {}
local __self = c local __self = c
c.name = name c.name = name
c.Type = multi.STHREAD c.Type = multi.STHREAD
c.thread = {} c.thread = {}
c.func = string.dump(func) c.func = string.dump(func)
function c:kill() function c:kill()
-- print("No Global table when using luvit integration!") -- print("No Global table when using luvit integration!")
end end
luvitThread.start(entry, package.path, name, c.func, ...) luvitThread.start(entry, package.path, name, c.func, ...)
return c return c
end end
THREAD.newSystemThread = multi.newSystemThread THREAD.newSystemThread = multi.newSystemThread
multi.print("Integrated Luvit!") multi.print("Integrated Luvit!")
multi.integration = {} -- for module creators multi.integration = {} -- for module creators
multi.integration.GLOBAL = GLOBAL multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD multi.integration.THREAD = THREAD
require("multi.integration.shared") require("multi.integration.shared")
-- Start the main mainloop... This allows you to process your multi objects, but the engine on the main thread will be limited to .001 or 1 millisecond sigh... -- Start the main mainloop... This allows you to process your multi objects, but the engine on the main thread will be limited to .001 or 1 millisecond sigh...
local interval = local interval =
timer.setInterval( timer.setInterval(
1, 1,
function() function()
multi:uManager() multi:uManager()
end end
) )
return multi return multi
end end
return {init = function(threadHandle, timerHandle) return {init = function(threadHandle, timerHandle)
local multi = _INIT(threadHandle, timerHandle) local multi = _INIT(threadHandle, timerHandle)
return GLOBAL, THREAD return GLOBAL, THREAD
end} end}
+33 -33
View File
@@ -1,34 +1,34 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
_G["__CHANNEL__"] = {} _G["__CHANNEL__"] = {}
local channel = {} local channel = {}
channel.__index = channel channel.__index = channel
-- Creates/Gets a channel of name -- Creates/Gets a channel of name
function channel:newChannel(name) function channel:newChannel(name)
local chan = _G["__CHANNEL__"] local chan = _G["__CHANNEL__"]
if chan then if chan then
end end
end end
+45 -45
View File
@@ -1,46 +1,46 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local cmd = require("multi.integration.networkManager.cmds") local cmd = require("multi.integration.networkManager.cmds")
local node = require("multi.integration.networkManager.node") local node = require("multi.integration.networkManager.node")
local net = require("net") local net = require("net")
local bin = require("bin") local bin = require("bin")
local child = {} local child = {}
child.__index = child child.__index = child
function multi:newChildNode(cd) function multi:newChildNode(cd)
local c = {} local c = {}
setmetatable(c,child) setmetatable(c,child)
local name local name
if cd then if cd then
if cd.name then if cd.name then
name = cd.name name = cd.name
end end
c.node = node:new(cd.nodePort or cmd.defaultPort,nil,name) c.node = node:new(cd.nodePort or cmd.defaultPort,nil,name)
if cd.managerHost then if cd.managerHost then
cd.managerPort = cd.managerPort or cmd.defaultManagerPort cd.managerPort = cd.managerPort or cmd.defaultManagerPort
c.node:registerWithManager(cd.managerHost,cd.managerPort) c.node:registerWithManager(cd.managerHost,cd.managerPort)
end end
end end
return c return c
end end
+34 -34
View File
@@ -1,35 +1,35 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
return function(self,data) return function(self,data)
local cmd,data = data:match("!(.-)!(.*)") local cmd,data = data:match("!(.-)!(.*)")
--print(">",cmd,data) --print(">",cmd,data)
if cmd == "PONG" then if cmd == "PONG" then
self:send("!PONG!") self:send("!PONG!")
elseif cmd == "CHANNEL" then elseif cmd == "CHANNEL" then
-- --
elseif cmd == "RETURNS" then elseif cmd == "RETURNS" then
local rets = bin.new(data):getBlock("t") local rets = bin.new(data):getBlock("t")
self.node.master.OnDataReturned:Fire(rets) self.node.master.OnDataReturned:Fire(rets)
end end
end end
+41 -41
View File
@@ -1,42 +1,42 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local cmds = { local cmds = {
defaultManagerPort = 0XDE2, defaultManagerPort = 0XDE2,
defaultWait = 0X002, defaultWait = 0X002,
defaultPort = 0X000, -- We will let the OS assign us one defaultPort = 0X000, -- We will let the OS assign us one
standardSkip = 0X018, standardSkip = 0X018,
ERROR = 0X000, ERROR = 0X000,
PING = 0X001, PING = 0X001,
PONG = 0X002, PONG = 0X002,
QUEUE = 0X003, QUEUE = 0X003,
TASK = 0X004, TASK = 0X004,
INITNODE = 0X005, INITNODE = 0X005,
INITMASTER = 0X006, INITMASTER = 0X006,
GLOBAL = 0X007, GLOBAL = 0X007,
LOAD = 0X008, LOAD = 0X008,
CALL = 0X009, CALL = 0X009,
REG = 0X00A, REG = 0X00A,
CONSOLE = 0X00B, CONSOLE = 0X00B,
} }
return cmds return cmds
+22 -22
View File
@@ -1,23 +1,23 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
+56 -56
View File
@@ -1,57 +1,57 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local net = require("net") local net = require("net")
--local bin = require("bin") --local bin = require("bin")
local char = string.char local char = string.char
local byte = string.byte local byte = string.byte
bin.setBitsInterface(infinabits) bin.setBitsInterface(infinabits)
--[[ --[[
--[=[ Pre reqs: --[=[ Pre reqs:
- Network contains nodes - Network contains nodes
- Network can broadcast/has nodemanager/ is simple and can be scanned - Network can broadcast/has nodemanager/ is simple and can be scanned
Outline: Outline:
- multi:newMasterNode(connectionDetails) - multi:newMasterNode(connectionDetails)
-- master:setDefaultNode(nodeName) -- Set default node -- master:setDefaultNode(nodeName) -- Set default node
-- master:newNetworkThread(nodeName,func,...) -- Thread is ran on a random node or the default one if set if nodeName is set to nil -- master:newNetworkThread(nodeName,func,...) -- Thread is ran on a random node or the default one if set if nodeName is set to nil
-- master:newNetworkChannel(nodeName) -- master:newNetworkChannel(nodeName)
-- master:sendTo(nodeName,data) -- master:sendTo(nodeName,data)
- multi:newNode(connectionDetails) - multi:newNode(connectionDetails)
- multi:newNodeManager(connectionDetails) -- This will be incharge of a lot of data handling - multi:newNodeManager(connectionDetails) -- This will be incharge of a lot of data handling
]=] ]=]
local nGLOBAL, nTHREAD = require("multi.integration.networkManager"):init() local nGLOBAL, nTHREAD = require("multi.integration.networkManager"):init()
local master = multi:newMasterNode() local master = multi:newMasterNode()
master:newNetworkThread("simpleNode",function(a,b,c) master:newNetworkThread("simpleNode",function(a,b,c)
print(a,b,c) print(a,b,c)
end,1,2,3) end,1,2,3)
]] ]]
-- The init file should provide the structure that all the other modules build off of -- The init file should provide the structure that all the other modules build off of
return { return {
init = function() init = function()
-- --
end end
} }
+162 -162
View File
@@ -1,163 +1,163 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local cmd = require("multi.integration.networkManager.cmds") local cmd = require("multi.integration.networkManager.cmds")
local node = require("multi.integration.networkManager.node") local node = require("multi.integration.networkManager.node")
local net = require("net") local net = require("net")
local bin = require("bin") local bin = require("bin")
local master = {} local master = {}
master.__index = master master.__index = master
function master:addNode(ip,port) function master:addNode(ip,port)
return node:new(ip,port) return node:new(ip,port)
end end
function master:getNodesFromBroadcast() function master:getNodesFromBroadcast()
net:newCastedClients("NODE_.+") net:newCastedClients("NODE_.+")
net.OnCastedClientInfo(function(client, n, ip, port) net.OnCastedClientInfo(function(client, n, ip, port)
self.nodes[n] = node:new(client) self.nodes[n] = node:new(client)
end) end)
end end
function master:getNodesFromManager(ip,port) function master:getNodesFromManager(ip,port)
local mn = self.nodes local mn = self.nodes
if not self.manager then if not self.manager then
self.manager = net:newTCPClient(ip,port) self.manager = net:newTCPClient(ip,port)
if not self.manager then if not self.manager then
error("Unable to connect to the node Manager! Is it running? Perhaps the hostname or port is incorrect!") error("Unable to connect to the node Manager! Is it running? Perhaps the hostname or port is incorrect!")
end end
end end
self.manager.OnDataRecieved(function(self,data,client) self.manager.OnDataRecieved(function(self,data,client)
local cmd = data:match("!(.+)!") local cmd = data:match("!(.+)!")
data = data:gsub("!"..cmd.."!","") data = data:gsub("!"..cmd.."!","")
if cmd == "NODE" then if cmd == "NODE" then
local n,h,p = data:match("(.-)|(.-)|(.+)") local n,h,p = data:match("(.-)|(.-)|(.+)")
mn[n] = node:new(h,tonumber(p)) mn[n] = node:new(h,tonumber(p))
end end
end) end)
self.manager:send("!NODES!") self.manager:send("!NODES!")
end end
function master:setDefaultNode(nodeName) function master:setDefaultNode(nodeName)
if self:nodeExists(nodeName) then if self:nodeExists(nodeName) then
self.defaultNode = nodeName self.defaultNode = nodeName
end end
end end
function master:getRandomNode() function master:getRandomNode()
local t = {} local t = {}
for i,v in pairs(self.nodes) do t[#t+1] = i end for i,v in pairs(self.nodes) do t[#t+1] = i end
return t[math.random(1,#t)] return t[math.random(1,#t)]
end end
local netID = 0 local netID = 0
function master:newNetworkThread(nodeName,func,...) function master:newNetworkThread(nodeName,func,...)
local args = {...} local args = {...}
local dat = bin.new() local dat = bin.new()
local ret local ret
local nID = netID local nID = netID
local conn = multi:newConnection() local conn = multi:newConnection()
thread:newthread(function() thread:newthread(function()
dat:addBlock{ dat:addBlock{
args = args, args = args,
func = func, func = func,
id = netID id = netID
} }
netID = netID + 1 netID = netID + 1
if type(nodeName) == "function" then if type(nodeName) == "function" then
func = nodeName func = nodeName
nodeName = self.defaultNode or self:getRandomNode() nodeName = self.defaultNode or self:getRandomNode()
if not func then if not func then
error("You must provide a function!") error("You must provide a function!")
end end
end end
self:sendTo(nodeName,"!N_THREAD!"..dat.data) self:sendTo(nodeName,"!N_THREAD!"..dat.data)
self.OnDataReturned(function(rets) self.OnDataReturned(function(rets)
if rets.ID == nID then if rets.ID == nID then
conn:Fire(unpack(rets.rets)) conn:Fire(unpack(rets.rets))
end end
end) end)
end) end)
return conn return conn
end end
function master:newNetworkChannel(nodeName) function master:newNetworkChannel(nodeName)
-- --
end end
function master:sendTo(nodeName,data) function master:sendTo(nodeName,data)
self:queue("send",nodeName,data) self:queue("send",nodeName,data)
end end
function master:demandNodeExistance(nodeName) function master:demandNodeExistance(nodeName)
if self.nodes[nodeName] then if self.nodes[nodeName] then
return multi.hold(self.nodes[nodeName]:ping().pong) return multi.hold(self.nodes[nodeName]:ping().pong)
else else
return false return false
end end
end end
function master:queue(c,...) function master:queue(c,...)
table.insert(self._queue,{c,{...}}) table.insert(self._queue,{c,{...}})
end end
function multi:newMasterNode(cd) function multi:newMasterNode(cd)
local c = {} local c = {}
setmetatable(c, master) setmetatable(c, master)
c.OnNodeDiscovered = multi:newConnection() c.OnNodeDiscovered = multi:newConnection()
c.OnNodeRemoved = multi:newConnection() c.OnNodeRemoved = multi:newConnection()
c.OnDataRecieved = multi:newConnection() c.OnDataRecieved = multi:newConnection()
c.OnDataReturned = multi:newConnection() c.OnDataReturned = multi:newConnection()
c.defaultNode = "" c.defaultNode = ""
c.nodes = {} c.nodes = {}
setmetatable(c.nodes, setmetatable(c.nodes,
{__newindex = function(t,k,v) {__newindex = function(t,k,v)
rawset(t,k,v) rawset(t,k,v)
v.master = c v.master = c
c.OnNodeDiscovered:Fire(k,v) c.OnNodeDiscovered:Fire(k,v)
end}) end})
c._queue = {} c._queue = {}
if cd then if cd then
if cd.nodeHost then if cd.nodeHost then
cd.nodePort = cd.nodePort or cmd.defaultPort cd.nodePort = cd.nodePort or cmd.defaultPort
local n,no = c:addNode(cd.nodeHost,cd.nodePort) local n,no = c:addNode(cd.nodeHost,cd.nodePort)
if n then if n then
c.nodes[n] = no c.nodes[n] = no
end end
elseif cd.managerHost then elseif cd.managerHost then
cd.managerPort = cd.managerPort or cmd.defaultManagerPort cd.managerPort = cd.managerPort or cmd.defaultManagerPort
c:getNodesFromManager(cd.managerHost,cd.managerPort) c:getNodesFromManager(cd.managerHost,cd.managerPort)
else else
c:getNodesFromBroadcast() c:getNodesFromBroadcast()
end end
else else
c:getNodesFromBroadcast() c:getNodesFromBroadcast()
end end
thread:newthread("CMDQueueProcessor",function() thread:newthread("CMDQueueProcessor",function()
while true do while true do
thread.skip(128) thread.skip(128)
local data = table.remove(c._queue,1) local data = table.remove(c._queue,1)
if data then if data then
local cmd = data[1] local cmd = data[1]
if cmd == "send" then if cmd == "send" then
local nodeName = data[2][1] local nodeName = data[2][1]
local dat = data[2][2] local dat = data[2][2]
c.nodes[nodeName]:send(dat) c.nodes[nodeName]:send(dat)
end end
end end
end end
end):OnError(function(...) end):OnError(function(...)
print(...) print(...)
end) end)
return c return c
end end
+126 -126
View File
@@ -1,127 +1,127 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local net = require("net") local net = require("net")
local cmd = require("multi.integration.networkManager.cmds") local cmd = require("multi.integration.networkManager.cmds")
local multi,thread = require("multi"):init() local multi,thread = require("multi"):init()
local node = {} local node = {}
node.__index = node node.__index = node
local rand = {} local rand = {}
for i = 65,90 do for i = 65,90 do
rand[#rand+1] = string.char(i) rand[#rand+1] = string.char(i)
end end
local function randName(n) local function randName(n)
local str = {} local str = {}
for i=1,(n or 10) do for i=1,(n or 10) do
str[#str+1] = rand[math.random(1,#rand)] str[#str+1] = rand[math.random(1,#rand)]
end end
return table.concat(str) return table.concat(str)
end end
local getNames = thread:newFunction(function(names) local getNames = thread:newFunction(function(names)
local listen = socket.udp() -- make a new socket local listen = socket.udp() -- make a new socket
listen:setsockname(net.getLocalIP(), 11111) listen:setsockname(net.getLocalIP(), 11111)
listen:settimeout(0) listen:settimeout(0)
local data, ip, port = listen:receivefrom() local data, ip, port = listen:receivefrom()
thread.holdWithin(1,function() thread.holdWithin(1,function()
if data then if data then
local n, tp, ip, port = data:match("(%S-)|(%S-)|(%S-):(%d+)") local n, tp, ip, port = data:match("(%S-)|(%S-)|(%S-):(%d+)")
if n then if n then
names[n]=true names[n]=true
end end
end end
end) end)
return multi.NIL return multi.NIL
end) end)
local function setName(ref,name) local function setName(ref,name)
if name then if name then
ref.name = "NODE_"..name ref.name = "NODE_"..name
ref.connection:broadcast(name) ref.connection:broadcast(name)
return return
end end
local names = {} local names = {}
getNames(names).wait() -- Prevents duplicate names from spawning! getNames(names).wait() -- Prevents duplicate names from spawning!
local name = randName() local name = randName()
while names["NODE_"..name] do while names["NODE_"..name] do
name = randName() name = randName()
end end
ref.name = "NODE_"..name ref.name = "NODE_"..name
ref.connection:broadcast(ref.name) ref.connection:broadcast(ref.name)
end end
node.ServerCode = require("multi.integration.networkManager.serverSide") node.ServerCode = require("multi.integration.networkManager.serverSide")
node.ClientCode = require("multi.integration.networkManager.clientSide") node.ClientCode = require("multi.integration.networkManager.clientSide")
function node.random() function node.random()
return randName(12) return randName(12)
end end
function node:registerWithManager(ip,port) function node:registerWithManager(ip,port)
if self.type ~= "server" then return end if self.type ~= "server" then return end
if not self.manager then if not self.manager then
self.manager = net:newTCPClient(ip,port) self.manager = net:newTCPClient(ip,port)
if not self.manager then if not self.manager then
error("Unable to connect to the node Manager! Is it running? Perhaps the hostname or port is incorrect!") error("Unable to connect to the node Manager! Is it running? Perhaps the hostname or port is incorrect!")
end end
end end
thread:newFunction(function() thread:newFunction(function()
thread.hold(function() return self.name end) thread.hold(function() return self.name end)
self.manager:send("!REG_NODE!"..self.name.."|"..net.getLocalIP().."|"..self.connection.port) self.manager:send("!REG_NODE!"..self.name.."|"..net.getLocalIP().."|"..self.connection.port)
end)() end)()
end end
function node:new(host,port,name) function node:new(host,port,name)
local c = {} local c = {}
c.links = {} c.links = {}
setmetatable(c,node) setmetatable(c,node)
if type(host)=="number" or type(host)=="nil" then if type(host)=="number" or type(host)=="nil" then
c.connection = net:newTCPServer(host or cmd.defaultPort) c.connection = net:newTCPServer(host or cmd.defaultPort)
c.connection:enableBinaryMode() c.connection:enableBinaryMode()
c.type = "server" c.type = "server"
c.connection.node = c c.connection.node = c
c.connection.OnDataRecieved(self.ServerCode) c.connection.OnDataRecieved(self.ServerCode)
setName(c) setName(c)
elseif type(host)=="table" and host.Type == "tcp" then elseif type(host)=="table" and host.Type == "tcp" then
c.connection = host c.connection = host
c.connection:enableBinaryMode() c.connection:enableBinaryMode()
c.type = "client" c.type = "client"
c.connection.node = c c.connection.node = c
c.connection.OnDataRecieved(self.ClientCode) c.connection.OnDataRecieved(self.ClientCode)
c.name = "MASTER_NODE" c.name = "MASTER_NODE"
elseif type(host) == "string" and type(port)=="number" then elseif type(host) == "string" and type(port)=="number" then
c.connection = net:newTCPClient(host, port) c.connection = net:newTCPClient(host, port)
c.connection:enableBinaryMode() c.connection:enableBinaryMode()
c.type = "client" c.type = "client"
c.connection.node = c c.connection.node = c
c.connection.OnDataRecieved(self.ClientCode) c.connection.OnDataRecieved(self.ClientCode)
c.name = "MASTER_NODE" c.name = "MASTER_NODE"
else else
error("Invalid arguments!") error("Invalid arguments!")
end end
return c return c
end end
function node:ping() function node:ping()
if self.type ~= "client" then return end if self.type ~= "client" then return end
self:send("!PING!") self:send("!PING!")
return {pong=self.connection.OnDataRecieved} return {pong=self.connection.OnDataRecieved}
end end
function node:send(data) function node:send(data)
if self.type ~= "client" then return end if self.type ~= "client" then return end
self.connection:send(data) self.connection:send(data)
end end
return node return node
+47 -47
View File
@@ -1,48 +1,48 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local cmd = require("multi.integration.networkManager.cmds") local cmd = require("multi.integration.networkManager.cmds")
local net = require("net") local net = require("net")
local bin = require("bin") local bin = require("bin")
local nodes = { -- Testing stuff local nodes = { -- Testing stuff
} }
function multi:newNodeManager(port) function multi:newNodeManager(port)
print("Running node manager on port: "..(port or cmd.defaultManagerPort)) print("Running node manager on port: "..(port or cmd.defaultManagerPort))
local server = net:newTCPServer(port or cmd.defaultManagerPort) local server = net:newTCPServer(port or cmd.defaultManagerPort)
server.OnDataRecieved(function(serv, data, client) server.OnDataRecieved(function(serv, data, client)
local cmd = data:match("!(.+)!") local cmd = data:match("!(.+)!")
data = data:gsub("!"..cmd.."!","") data = data:gsub("!"..cmd.."!","")
if cmd == "NODES" then if cmd == "NODES" then
for i,v in ipairs(nodes) do for i,v in ipairs(nodes) do
-- Sample data -- Sample data
serv:send(client, "!NODE!".. v[1].."|"..v[2].."|"..v[3]) serv:send(client, "!NODE!".. v[1].."|"..v[2].."|"..v[3])
end end
elseif cmd == "REG_NODE" then elseif cmd == "REG_NODE" then
local name, ip, port = data:match("(.-)|(.-)|(.+)") local name, ip, port = data:match("(.-)|(.-)|(.+)")
table.insert(nodes,{name,ip,port}) table.insert(nodes,{name,ip,port})
print("Registering Node:",name, ip, port) print("Registering Node:",name, ip, port)
end end
end) end)
end end
+46 -46
View File
@@ -1,47 +1,47 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local bin, bits = require("bin").init() local bin, bits = require("bin").init()
return function(self,data,client) return function(self,data,client)
local cmd,data = data:match("!(.-)!(.*)") local cmd,data = data:match("!(.-)!(.*)")
--print("SERVER",cmd,data) --print("SERVER",cmd,data)
if cmd == "PING" then if cmd == "PING" then
self:send(client,"!PONG!") self:send(client,"!PONG!")
elseif cmd == "N_THREAD" then elseif cmd == "N_THREAD" then
print(1) print(1)
local dat = bin.new(data) local dat = bin.new(data)
print(2) print(2)
local t = dat:getBlock("t") local t = dat:getBlock("t")
print(3) print(3)
local ret = bin.new() local ret = bin.new()
print(4) print(4)
ret:addBlock{ID = t.id,rets = {t.func(unpack(t.args))}} ret:addBlock{ID = t.id,rets = {t.func(unpack(t.args))}}
print(5) print(5)
print(client,"!RETURNS!"..ret:getData()) print(client,"!RETURNS!"..ret:getData())
self:send(client,"!RETURNS!"..ret:getData()) self:send(client,"!RETURNS!"..ret:getData())
print(6) print(6)
elseif cmd == "CHANNEL" then elseif cmd == "CHANNEL" then
local dat = bin.new(data):getBlock("t") local dat = bin.new(data):getBlock("t")
end end
end end
+22 -22
View File
@@ -1,23 +1,23 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
+26 -26
View File
@@ -1,27 +1,27 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local bin = require("bin") local bin = require("bin")
local utils = {} local utils = {}
-- Will contain data that handles sterilizing and managing data -- Will contain data that handles sterilizing and managing data
return utils return utils
+212 -212
View File
@@ -1,213 +1,213 @@
-- Advanced process management. Mutates the multi namespace -- Advanced process management. Mutates the multi namespace
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local ok, chronos = pcall(require, "chronos") -- hpc local ok, chronos = pcall(require, "chronos") -- hpc
if not ok then chronos = nil end if not ok then chronos = nil end
-- This is an integration, we cannot directly access locals that are in the main file. -- This is an integration, we cannot directly access locals that are in the main file.
local PList = { local PList = {
multi.Priority_Core, multi.Priority_Core,
multi.Priority_Very_High, multi.Priority_Very_High,
multi.Priority_High, multi.Priority_High,
multi.Priority_Above_Normal, multi.Priority_Above_Normal,
multi.Priority_Normal, multi.Priority_Normal,
multi.Priority_Below_Normal, multi.Priority_Below_Normal,
multi.Priority_Low, multi.Priority_Low,
multi.Priority_Very_Low, multi.Priority_Very_Low,
multi.Priority_Idle multi.Priority_Idle
} }
-- Restructered these functions since they rely on local variables from the core library -- Restructered these functions since they rely on local variables from the core library
local mainloop = multi.mainloopRef local mainloop = multi.mainloopRef
local mainloop_p = multi.mainloop_p local mainloop_p = multi.mainloop_p
local uManagerRef = multi.uManagerRef local uManagerRef = multi.uManagerRef
local uManagerRefP = multi.uManagerRefP1 local uManagerRefP = multi.uManagerRefP1
local PROFILE_COUNT = 5 local PROFILE_COUNT = 5
-- self:setCurrentProcess() a bit slower than using the local var, but there isn't another option -- self:setCurrentProcess() a bit slower than using the local var, but there isn't another option
local priorityManager = multi:newProcessor("Priority Manager", true) local priorityManager = multi:newProcessor("Priority Manager", true)
priorityManager.newThread = function() multi.warn("You cannot spawn threads on the priority manager!") end priorityManager.newThread = function() multi.warn("You cannot spawn threads on the priority manager!") end
priorityManager.setPriorityScheme = function() multi.warn("You cannot set priority on the priorityManager!") end priorityManager.setPriorityScheme = function() multi.warn("You cannot set priority on the priorityManager!") end
local function average(t) local function average(t)
local sum = 0 local sum = 0
for _,v in pairs(t) do for _,v in pairs(t) do
sum = sum + v sum = sum + v
end end
return sum / #t return sum / #t
end end
local function getPriority(obj) local function getPriority(obj)
local avg = average(obj.__profiling) local avg = average(obj.__profiling)
if avg < 0.0002 then if avg < 0.0002 then
return PList[1] return PList[1]
elseif avg < 0.0004 then elseif avg < 0.0004 then
return PList[2] return PList[2]
elseif avg < 0.0008 then elseif avg < 0.0008 then
return PList[3] return PList[3]
elseif avg < 0.001 then elseif avg < 0.001 then
return PList[4] return PList[4]
elseif avg < 0.0025 then elseif avg < 0.0025 then
return PList[5] return PList[5]
elseif avg < 0.005 then elseif avg < 0.005 then
return PList[6] return PList[6]
elseif avg < 0.008 then elseif avg < 0.008 then
return PList[7] return PList[7]
elseif avg < 0.01 then elseif avg < 0.01 then
return PList[8] return PList[8]
else else
return PList[9] return PList[9]
end end
end end
local start, stop local start, stop
priorityManager.uManager = function(self) priorityManager.uManager = function(self)
-- proc.run already checks if the processor is active -- proc.run already checks if the processor is active
self:setCurrentProcess() self:setCurrentProcess()
local Loop=self.Mainloop local Loop=self.Mainloop
local ctask local ctask
for _D=#Loop,1,-1 do for _D=#Loop,1,-1 do
ctask = Loop[_D] ctask = Loop[_D]
ctask:setCurrentTask() ctask:setCurrentTask()
start = chronos.nanotime() start = chronos.nanotime()
if ctask:Act() then if ctask:Act() then
stop = chronos.nanotime() stop = chronos.nanotime()
if ctask.__profiling then if ctask.__profiling then
table.insert(ctask.__profiling, stop - start) table.insert(ctask.__profiling, stop - start)
end end
if ctask.__profiling and #ctask.__profiling == PROFILE_COUNT then if ctask.__profiling and #ctask.__profiling == PROFILE_COUNT then
ctask:setPriority(getPriority(ctask)) ctask:setPriority(getPriority(ctask))
ctask:reallocate(ctask.__restoreProc) ctask:reallocate(ctask.__restoreProc)
ctask.__restoreProc = nil ctask.__restoreProc = nil
ctask.__profiling = nil ctask.__profiling = nil
end end
end end
self:setCurrentProcess() self:setCurrentProcess()
end end
end end
local function processHook(obj, proc) local function processHook(obj, proc)
if obj.Type == multi.registerType("process", "processes") or not(obj.IsAnActor) then return end if obj.Type == multi.registerType("process", "processes") or not(obj.IsAnActor) then return end
obj.__restoreProc = proc obj.__restoreProc = proc
obj.__profiling = {} obj.__profiling = {}
obj:reallocate(priorityManager) obj:reallocate(priorityManager)
end end
local function init() local function init()
local registry = {} local registry = {}
multi.priorityScheme = { multi.priorityScheme = {
RoundRobin = "RoundRobin", RoundRobin = "RoundRobin",
PriorityBased = "PriorityBased", PriorityBased = "PriorityBased",
TimeBased = "TimeBased" TimeBased = "TimeBased"
} }
function multi:setProfilerCount(count) function multi:setProfilerCount(count)
PROFILE_COUNT = count PROFILE_COUNT = count
end end
function multi:recalibrate() function multi:recalibrate()
if self.__processConn then if self.__processConn then
local items = self.Mainloop local items = self.Mainloop
for i,v in pairs(items) do for i,v in pairs(items) do
processHook(v, self) processHook(v, self)
end end
else else
multi.error("Cannot recalibrate the priority if not using Time based mangement!") multi.error("Cannot recalibrate the priority if not using Time based mangement!")
end end
end end
function multi:isRegistredScheme(scheme) function multi:isRegistredScheme(scheme)
return registry[name] ~= nil return registry[name] ~= nil
end end
function multi:getRegisteredScheme(scheme) function multi:getRegisteredScheme(scheme)
return registry[name].mainloop, registry[name].umanager, registry[name].condition return registry[name].mainloop, registry[name].umanager, registry[name].condition
end end
local empty_func = function() return true end local empty_func = function() return true end
function multi:registerScheme(name,options) function multi:registerScheme(name,options)
local mainloop = options.mainloop or multi.error("You must provide a mainloop option when registring a scheme!") local mainloop = options.mainloop or multi.error("You must provide a mainloop option when registring a scheme!")
local umanager = options.umanager or multi.error("You must provide a umanager option when registring a scheme!") local umanager = options.umanager or multi.error("You must provide a umanager option when registring a scheme!")
if not options.condition then if not options.condition then
multi.warn("You might want to use condition when registring a scheme! A function that returns true has been auto generated for you!") multi.warn("You might want to use condition when registring a scheme! A function that returns true has been auto generated for you!")
end end
local condition = options.condition or empty_func local condition = options.condition or empty_func
if registry[name] and not registry[name].static then if registry[name] and not registry[name].static then
multi.warn("A scheme named: \"" .. name .. "\" has already been registred, overriting!") multi.warn("A scheme named: \"" .. name .. "\" has already been registred, overriting!")
else else
multi.error("A scheme named: \"" .. name .. "\" has already been registred!") multi.error("A scheme named: \"" .. name .. "\" has already been registred!")
end end
registry[name] = { registry[name] = {
mainloop = mainloop, mainloop = mainloop,
umanager = umanger, umanager = umanger,
condition = condition, condition = condition,
static = options.static or false static = options.static or false
} }
multi.priorityScheme[name] = name multi.priorityScheme[name] = name
return true return true
end end
function multi:setPriorityScheme(scheme) function multi:setPriorityScheme(scheme)
if not self.Type == multi.registerType("process", "processes") or not self.Type == multi.registerType("rootprocess") then if not self.Type == multi.registerType("process", "processes") or not self.Type == multi.registerType("rootprocess") then
multi.warn("You should only invoke setPriorityScheme on a processor object!") multi.warn("You should only invoke setPriorityScheme on a processor object!")
end end
if scheme == multi.priorityScheme.RoundRobin then if scheme == multi.priorityScheme.RoundRobin then
if self.__processConn then self.OnObjectCreated:Unconnect(self.__processConn) self.__processConn = nil end if self.__processConn then self.OnObjectCreated:Unconnect(self.__processConn) self.__processConn = nil end
self.mainloop = mainloop self.mainloop = mainloop
self.uManager = uManagerRef self.uManager = uManagerRef
elseif scheme == multi.priorityScheme.PriorityBased then elseif scheme == multi.priorityScheme.PriorityBased then
if self.__processConn then self.OnObjectCreated:Unconnect(self.__processConn) self.__processConn = nil end if self.__processConn then self.OnObjectCreated:Unconnect(self.__processConn) self.__processConn = nil end
self.mainloop = mainloop_p self.mainloop = mainloop_p
self.uManager = uManagerRefP self.uManager = uManagerRefP
elseif scheme == multi.priorityScheme.TimeBased then elseif scheme == multi.priorityScheme.TimeBased then
if not chronos then return multi.warn("Unable to use TimeBased Priority without the chronos library!") end if not chronos then return multi.warn("Unable to use TimeBased Priority without the chronos library!") end
if self.__processConn then multi.warn("Already enabled TimeBased Priority!") end if self.__processConn then multi.warn("Already enabled TimeBased Priority!") end
self.__processConn = self.OnObjectCreated(processHook) self.__processConn = self.OnObjectCreated(processHook)
self.mainloop = mainloop_p self.mainloop = mainloop_p
self.uManager = uManagerRefP self.uManager = uManagerRefP
elseif self:isRegistredScheme(scheme) then elseif self:isRegistredScheme(scheme) then
local mainloop, umanager, condition = self:getRegisteredScheme(scheme) local mainloop, umanager, condition = self:getRegisteredScheme(scheme)
if condition() then if condition() then
self.mainloop = mainloop self.mainloop = mainloop
self.uManager = umanager self.uManager = umanager
end end
else else
self.error("Invalid priority scheme selected!") self.error("Invalid priority scheme selected!")
end end
end end
end end
local function init_chronos() local function init_chronos()
-- Let's implement a higher precision clock -- Let's implement a higher precision clock
multi.setClock(chronos.nanotime) -- This is also in .000 format. So a plug and play works. multi.setClock(chronos.nanotime) -- This is also in .000 format. So a plug and play works.
thread:newThread("System Priority Manager", function() thread:newThread("System Priority Manager", function()
while true do while true do
thread.yield() thread.yield()
priorityManager.run() priorityManager.run()
end end
end) end)
end end
if chronos then if chronos then
init_chronos() init_chronos()
else else
multi.warn("In order to have time based priority management, you need to install the chronos library!") multi.warn("In order to have time based priority management, you need to install the chronos library!")
end end
init() init()
+220 -220
View File
@@ -1,221 +1,221 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local GLOBAL, THREAD = multi.integration.GLOBAL, multi.integration.THREAD local GLOBAL, THREAD = multi.integration.GLOBAL, multi.integration.THREAD
local function stripUpValues(func) local function stripUpValues(func)
local dmp = string.dump(func) local dmp = string.dump(func)
if setfenv then if setfenv then
return loadstring(dmp,"IsolatedThread_PesudoThreading") return loadstring(dmp,"IsolatedThread_PesudoThreading")
else else
return load(dmp,"IsolatedThread_PesudoThreading","bt") return load(dmp,"IsolatedThread_PesudoThreading","bt")
end end
end end
function multi:newSystemThreadedQueue(name) function multi:newSystemThreadedQueue(name)
local c = {} local c = {}
c.data = {} c.data = {}
c.Type = multi.registerType("s_queue") c.Type = multi.registerType("s_queue")
function c:push(v) function c:push(v)
table.insert(self.data,v) table.insert(self.data,v)
end end
function c:pop() function c:pop()
return table.remove(self.data,1) return table.remove(self.data,1)
end end
function c:peek() function c:peek()
return self.data[1] return self.data[1]
end end
function c:init() function c:init()
return self return self
end end
function c:Hold(opt) function c:Hold(opt)
if opt.peek then if opt.peek then
return thread.hold(function() return thread.hold(function()
return self:peek() return self:peek()
end) end)
else else
return thread.hold(function() return thread.hold(function()
return self:pop() return self:pop()
end) end)
end end
end end
GLOBAL[name or "_"] = c GLOBAL[name or "_"] = c
return c return c
end end
function multi:newSystemThreadedTable(name) function multi:newSystemThreadedTable(name)
local c = {} local c = {}
c.Type = multi.registerType("s_table") c.Type = multi.registerType("s_table")
function c:init() function c:init()
return self return self
end end
function c:Hold(opt) function c:Hold(opt)
if opt.key then if opt.key then
return thread.hold(function() return thread.hold(function()
return self.tab[opt.key] return self.tab[opt.key]
end) end)
else else
multi.error("Must provide a key to check opt.key = 'key'") multi.error("Must provide a key to check opt.key = 'key'")
end end
end end
GLOBAL[name or "_"] = c GLOBAL[name or "_"] = c
return c return c
end end
local setfenv = multi.isolateFunction local setfenv = multi.isolateFunction
local jqc = 1 local jqc = 1
function multi:newSystemThreadedJobQueue(n) function multi:newSystemThreadedJobQueue(n)
local c = {} local c = {}
c.cores = n or THREAD.getCores() c.cores = n or THREAD.getCores()
c.registerQueue = {} c.registerQueue = {}
c.Type = multi.registerType("s_jobqueue") c.Type = multi.registerType("s_jobqueue")
c.funcs = multi:newSystemThreadedTable("__JobQueue_"..jqc.."_table") c.funcs = multi:newSystemThreadedTable("__JobQueue_"..jqc.."_table")
c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue") c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue")
c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn") c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn")
c.queueAll = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueAll") c.queueAll = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueAll")
c.id = 0 c.id = 0
c.OnJobCompleted = multi:newConnection() c.OnJobCompleted = multi:newConnection()
local allfunc = 0 local allfunc = 0
function c:doToAll(func) function c:doToAll(func)
for i = 1, self.cores do for i = 1, self.cores do
self.queueAll:push({allfunc, func}) self.queueAll:push({allfunc, func})
end end
allfunc = allfunc + 1 allfunc = allfunc + 1
end end
function c:registerFunction(name, func) function c:registerFunction(name, func)
if self.funcs[name] then if self.funcs[name] then
multi.error("A function by the name "..name.." has already been registered!") multi.error("A function by the name "..name.." has already been registered!")
end end
self.funcs[name] = func self.funcs[name] = func
end end
function c:pushJob(name,...) function c:pushJob(name,...)
self.id = self.id + 1 self.id = self.id + 1
self.queue:push{name,self.id,...} self.queue:push{name,self.id,...}
return self.id return self.id
end end
function c:isEmpty() function c:isEmpty()
return queueJob:peek()==nil return queueJob:peek()==nil
end end
local nFunc = 0 local nFunc = 0
function c:newFunction(name,func,holup) -- This registers with the queue function c:newFunction(name,func,holup) -- This registers with the queue
if type(name)=="function" then if type(name)=="function" then
holup = func holup = func
func = name func = name
name = "JQ_Function_"..nFunc name = "JQ_Function_"..nFunc
end end
nFunc = nFunc + 1 nFunc = nFunc + 1
c:registerFunction(name,func) c:registerFunction(name,func)
return thread:newFunction(function(...) return thread:newFunction(function(...)
local id = c:pushJob(name,...) local id = c:pushJob(name,...)
local link local link
local rets local rets
link = c.OnJobCompleted(function(jid,...) link = c.OnJobCompleted(function(jid,...)
if id==jid then if id==jid then
rets = multi.pack(...) rets = multi.pack(...)
end end
end) end)
return thread.hold(function() return thread.hold(function()
if rets then if rets then
return multi.unpack(rets) or multi.NIL return multi.unpack(rets) or multi.NIL
end end
end) end)
end,holup),name end,holup),name
end end
thread:newThread("jobManager",function() thread:newThread("jobManager",function()
while true do while true do
thread.yield() thread.yield()
local dat = c.queueReturn:pop() local dat = c.queueReturn:pop()
if dat then if dat then
c.OnJobCompleted:Fire(multi.unpack(dat)) c.OnJobCompleted:Fire(multi.unpack(dat))
end end
end end
end) end)
for i=1,c.cores do for i=1,c.cores do
multi:newSystemThread("STJQ_"..multi.randomString(8),function(jqc) multi:newSystemThread("STJQ_"..multi.randomString(8),function(jqc)
local GLOBAL, THREAD = require("multi.integration.pseudoManager"):init() local GLOBAL, THREAD = require("multi.integration.pseudoManager"):init()
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local clock = os.clock local clock = os.clock
local funcs = THREAD.waitFor("__JobQueue_"..jqc.."_table") local funcs = THREAD.waitFor("__JobQueue_"..jqc.."_table")
local queue = THREAD.waitFor("__JobQueue_"..jqc.."_queue") local queue = THREAD.waitFor("__JobQueue_"..jqc.."_queue")
local queueReturn = THREAD.waitFor("__JobQueue_"..jqc.."_queueReturn") local queueReturn = THREAD.waitFor("__JobQueue_"..jqc.."_queueReturn")
local queueAll = THREAD.waitFor("__JobQueue_"..jqc.."_queueAll") local queueAll = THREAD.waitFor("__JobQueue_"..jqc.."_queueAll")
local registry = {} local registry = {}
_G["__QR"] = queueReturn _G["__QR"] = queueReturn
setmetatable(_G,{__index = funcs}) setmetatable(_G,{__index = funcs})
thread:newThread("startUp",function() thread:newThread("startUp",function()
while true do while true do
thread.yield() thread.yield()
local all = queueAll:peek() local all = queueAll:peek()
if all and not registry[all[1]] then if all and not registry[all[1]] then
queueAll:pop()[2]() queueAll:pop()[2]()
end end
end end
end) end)
thread:newThread("runner",function() thread:newThread("runner",function()
thread.sleep(.1) thread.sleep(.1)
while true do while true do
thread.yield() thread.yield()
local all = queueAll:peek() local all = queueAll:peek()
if all and not registry[all[1]] then if all and not registry[all[1]] then
queueAll:pop()[2]() queueAll:pop()[2]()
end end
local dat = thread.hold(queue) local dat = thread.hold(queue)
if dat then if dat then
multi:newThread("JobSubRunner",function() multi:newThread("JobSubRunner",function()
local name = table.remove(dat,1) local name = table.remove(dat,1)
local id = table.remove(dat,1) local id = table.remove(dat,1)
local tab = {multi.isolateFunction(funcs[name],_G)(multi.unpack(dat))} local tab = {multi.isolateFunction(funcs[name],_G)(multi.unpack(dat))}
table.insert(tab,1,id) table.insert(tab,1,id)
queueReturn:push(tab) queueReturn:push(tab)
end) end)
end end
end end
end) end)
multi:mainloop() multi:mainloop()
end, jqc) end, jqc)
end end
function c:Hold(opt) function c:Hold(opt)
return thread.hold(self.OnJobCompleted) return thread.hold(self.OnJobCompleted)
end end
jqc = jqc + 1 jqc = jqc + 1
self:create(c) self:create(c)
return c return c
end end
function multi:newSystemThreadedConnection(name) function multi:newSystemThreadedConnection(name)
local conn = multi:newConnection() local conn = multi:newConnection()
conn.init = function(self) return self end conn.init = function(self) return self end
GLOBAL[name or "_"] = conn GLOBAL[name or "_"] = conn
return conn return conn
end end
require("multi.integration.sharedExtensions") require("multi.integration.sharedExtensions")
+121 -123
View File
@@ -1,123 +1,121 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2020 Ryan Ward Copyright (c) 2020 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
package.path = "?/init.lua;?.lua;" .. package.path package.path = "?/init.lua;?.lua;" .. package.path
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local pseudoProcessor = multi:newProcessor()
local pseudoProcessor = multi:newProcessor() if multi.integration then
return {
if multi.integration then init = function()
return { return multi.integration.GLOBAL, multi.integration.THREAD
init = function() end
return multi.integration.GLOBAL, multi.integration.THREAD }
end end
} multi.isMainThread = true
end local activator = require("multi.integration.pseudoManager.threads")
multi.isMainThread = true local GLOBAL, THREAD = activator.init(thread)
local activator = require("multi.integration.pseudoManager.threads")
local GLOBAL, THREAD = activator.init(thread) _G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0
_G.THREAD_NAME = "MAIN_THREAD"
_G.THREAD_ID = 0 function multi:canSystemThread() -- We are emulating system threading
return true
function multi:canSystemThread() -- We are emulating system threading end
return true
end function multi:getPlatform()
return "pesudo"
function multi:getPlatform() end
return "pesudo"
end local function split(str)
local tab = {}
local function split(str) for word in string.gmatch(str, '([^,]+)') do
local tab = {} table.insert(tab,word)
for word in string.gmatch(str, '([^,]+)') do end
table.insert(tab,word) return tab
end end
return tab
end local tab = [[_VERSION,io,os,require,load,debug,assert,collectgarbage,error,getfenv,getmetatable,ipairs,loadstring,module,next,pairs,pcall,print,rawequal,rawget,rawset,select,setfenv,setmetatable,tonumber,tostring,type,xpcall,math,coroutine,string,table]]
tab = split(tab)
local tab = [[_VERSION,io,os,require,load,debug,assert,collectgarbage,error,getfenv,getmetatable,ipairs,loadstring,module,next,pairs,pcall,print,rawequal,rawget,rawset,select,setfenv,setmetatable,tonumber,tostring,type,xpcall,math,coroutine,string,table]]
tab = split(tab) local id = 0
local id = 0 function multi:newSystemThread(name, func, ...)
local env
function multi:newSystemThread(name, func, ...) env = {
local env GLOBAL = GLOBAL,
env = { THREAD = THREAD,
GLOBAL = GLOBAL, THREAD_NAME = tostring(name),
THREAD = THREAD, __THREADNAME__ = tostring(name),
THREAD_NAME = tostring(name), THREAD_ID = id,
__THREADNAME__ = tostring(name), thread = thread,
THREAD_ID = id, multi = multi,
thread = thread, }
multi = multi,
} for i, v in pairs(_G) do
if not(env[i]) and not(i == "_G") and not(i == "local_global") then
for i, v in pairs(_G) do env[i] = v
if not(env[i]) and not(i == "_G") and not(i == "local_global") then else
env[i] = v multi.warn("skipping:",i)
else end
multi.warn("skipping:",i) end
end
end if GLOBAL["__env"] then
for i,v in pairs(GLOBAL["__env"]) do
if GLOBAL["__env"] then env[i] = v
for i,v in pairs(GLOBAL["__env"]) do end
env[i] = v end
end
end env._G = env
env._G = env local GLOBAL, THREAD = activator.init(thread, env)
local GLOBAL, THREAD = activator.init(thread, env) local th = pseudoProcessor:newISOThread(name, func, env, ...)
th.Type = multi.registerType("s_thread", "pseudoThreads")
local th = pseudoProcessor:newISOThread(name, func, env, ...) th.OnError(multi.error)
th.Type = multi.registerType("s_thread", "pseudoThreads")
th.OnError(multi.error) id = id + 1
id = id + 1 return th
end
return th
end THREAD.newSystemThread = multi.newSystemThread
-- System threads as implemented here cannot share memory, but use a message passing system.
THREAD.newSystemThread = multi.newSystemThread -- An isolated thread allows us to mimic that behavior so if access data from the "main" thread happens things will not work. This behavior is in line with how the system threading works
-- System threads as implemented here cannot share memory, but use a message passing system.
-- An isolated thread allows us to mimic that behavior so if access data from the "main" thread happens things will not work. This behavior is in line with how the system threading works function THREAD:newFunction(func,holdme)
return thread:newFunctionBase(function(...)
function THREAD:newFunction(func,holdme) return multi:newSystemThread("TempSystemThread",func,...)
return thread:newFunctionBase(function(...) end, holdme, multi.registerType("s_function", "pseudoFunctions"))()
return multi:newSystemThread("TempSystemThread",func,...) end
end, holdme, multi.registerType("s_function", "pseudoFunctions"))()
end multi.print("Integrated Pesudo Threading!")
multi.integration = {} -- for module creators
multi.print("Integrated Pesudo Threading!") multi.integration.GLOBAL = GLOBAL
multi.integration = {} -- for module creators multi.integration.THREAD = THREAD
multi.integration.GLOBAL = GLOBAL require("multi.integration.pseudoManager.extensions")
multi.integration.THREAD = THREAD require("multi.integration.sharedExtensions")
require("multi.integration.pseudoManager.extensions") return {
require("multi.integration.sharedExtensions") init = function()
return { return GLOBAL, THREAD
init = function() end
return GLOBAL, THREAD }
end
}
+121 -121
View File
@@ -1,122 +1,122 @@
--[[ --[[
MIT License MIT License
Copyright (c) 2022 Ryan Ward Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local function getOS() local function getOS()
if package.config:sub(1, 1) == "\\" then if package.config:sub(1, 1) == "\\" then
return "windows" return "windows"
else else
return "unix" return "unix"
end end
end end
local function INIT(thread) local function INIT(thread)
local THREAD = {} local THREAD = {}
local GLOBAL = {} local GLOBAL = {}
THREAD.Priority_Core = 3 THREAD.Priority_Core = 3
THREAD.Priority_High = 2 THREAD.Priority_High = 2
THREAD.Priority_Above_Normal = 1 THREAD.Priority_Above_Normal = 1
THREAD.Priority_Normal = 0 THREAD.Priority_Normal = 0
THREAD.Priority_Below_Normal = -1 THREAD.Priority_Below_Normal = -1
THREAD.Priority_Low = -2 THREAD.Priority_Low = -2
THREAD.Priority_Idle = -3 THREAD.Priority_Idle = -3
function THREAD.set(name, val) function THREAD.set(name, val)
GLOBAL[name] = val GLOBAL[name] = val
end end
function THREAD.get(name) function THREAD.get(name)
return GLOBAL[name] return GLOBAL[name]
end end
function THREAD.waitFor(name) function THREAD.waitFor(name)
return thread.hold(function() return GLOBAL[name] end) return thread.hold(function() return GLOBAL[name] end)
end end
if getOS() == "windows" then if getOS() == "windows" then
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
else else
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
end end
function THREAD.getCores() function THREAD.getCores()
return THREAD.__CORES return THREAD.__CORES
end end
function THREAD.getConsole() function THREAD.getConsole()
local c = {} local c = {}
function c.print(...) function c.print(...)
print(...) print(...)
end end
function c.error(err) function c.error(err)
error("ERROR in <"..GLOBAL["$__THREADNAME__"]..">: "..err) error("ERROR in <"..GLOBAL["$__THREADNAME__"]..">: "..err)
end end
return c return c
end end
function THREAD.getThreads() function THREAD.getThreads()
return {}--GLOBAL.__THREADS__ return {}--GLOBAL.__THREADS__
end end
THREAD.pushStatus = thread.pushStatus THREAD.pushStatus = thread.pushStatus
function THREAD.kill() function THREAD.kill()
error("Thread was killed!") error("Thread was killed!")
end end
THREAD.sleep = thread.sleep THREAD.sleep = thread.sleep
THREAD.hold = thread.hold THREAD.hold = thread.hold
THREAD.defer = thread.defer THREAD.defer = thread.defer
function THREAD.setENV(env, name) function THREAD.setENV(env, name)
name = name or "__env" name = name or "__env"
GLOBAL[name] = env GLOBAL[name] = env
end end
function THREAD.getENV(name) function THREAD.getENV(name)
name = name or "__env" name = name or "__env"
return GLOBAL[name] return GLOBAL[name]
end end
function THREAD.exposeENV(name) function THREAD.exposeENV(name)
name = name or "__env" name = name or "__env"
local env = THREAD.getENV(name) local env = THREAD.getENV(name)
for i,v in pairs(env) do for i,v in pairs(env) do
-- This may need to be reworked! -- This may need to be reworked!
local_global[i] = v local_global[i] = v
end end
end end
function THREAD.sync() function THREAD.sync()
thread.sleep(.5) thread.sleep(.5)
end end
return GLOBAL, THREAD return GLOBAL, THREAD
end end
return {init = function(thread, global) return {init = function(thread, global)
return INIT(thread, global) return INIT(thread, global)
end} end}
+336 -336
View File
@@ -1,336 +1,336 @@
--[[ todo finish the targeted job! --[[ todo finish the targeted job!
MIT License MIT License
Copyright (c) 2023 Ryan Ward Copyright (c) 2023 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
]] ]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
-- Returns a handler that allows a user to interact with an object on another thread! -- Returns a handler that allows a user to interact with an object on another thread!
-- Create on the thread that you want to interact with, send over the handle -- Create on the thread that you want to interact with, send over the handle
function multi:chop(obj) function multi:chop(obj)
if not _G["UIDS"] then if not _G["UIDS"] then
_G["UIDS"] = {} _G["UIDS"] = {}
end end
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local list = {[0] = multi.randomString(12)} local list = {[0] = multi.randomString(12)}
_G[list[0]] = obj _G[list[0]] = obj
for i,v in pairs(obj) do for i,v in pairs(obj) do
if type(v) == "function" or type(v) == "table" and v.Type == multi.registerType("s_function") then if type(v) == "function" or type(v) == "table" and v.Type == multi.registerType("s_function") then
table.insert(list, i) table.insert(list, i)
elseif type(v) == "table" and v.Type == multi.registerType("connector", "connections") then elseif type(v) == "table" and v.Type == multi.registerType("connector", "connections") then
table.insert(list, {i, multi:newProxy(multi:chop(v)):init()}) table.insert(list, {i, multi:newProxy(multi:chop(v)):init()})
end end
end end
return list return list
end end
function multi:newProxy(list) function multi:newProxy(list)
local c = {} local c = {}
c.name = multi.randomString(12) c.name = multi.randomString(12)
c.is_init = false c.is_init = false
local multi, thread = nil, nil local multi, thread = nil, nil
function c:init() function c:init()
local multi, thread = nil, nil local multi, thread = nil, nil
local function copy(obj) local function copy(obj)
if type(obj) ~= 'table' then return obj end if type(obj) ~= 'table' then return obj end
local res = {} local res = {}
for k, v in pairs(obj) do res[copy(k)] = copy(v) end for k, v in pairs(obj) do res[copy(k)] = copy(v) end
return res return res
end end
if not(self.is_init) then if not(self.is_init) then
THREAD.sync() THREAD.sync()
self.is_init = true self.is_init = true
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
self.proxy_link = "PL" .. multi.randomString(12) self.proxy_link = "PL" .. multi.randomString(12)
if multi.integration then if multi.integration then
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
end end
GLOBAL[self.proxy_link] = self GLOBAL[self.proxy_link] = self
local function check() local function check()
return self.send:pop() return self.send:pop()
end end
self.send = multi:newSystemThreadedQueue(self.name.."_S"):init() self.send = multi:newSystemThreadedQueue(self.name.."_S"):init()
self.recv = multi:newSystemThreadedQueue(self.name.."_R"):init() self.recv = multi:newSystemThreadedQueue(self.name.."_R"):init()
self.funcs = list self.funcs = list
self._funcs = copy(list) self._funcs = copy(list)
self.Type = multi.registerType("proxy", "proxies") self.Type = multi.registerType("proxy", "proxies")
self.TID = THREAD_ID self.TID = THREAD_ID
thread:newThread("Proxy_Handler_" .. multi.randomString(4), function() thread:newThread("Proxy_Handler_" .. multi.randomString(4), function()
while true do while true do
local data = thread.hold(check) local data = thread.hold(check)
if data then if data then
-- Let's not hold the main threadloop -- Let's not hold the main threadloop
thread:newThread("Temp_Thread", function() thread:newThread("Temp_Thread", function()
local func = table.remove(data, 1) local func = table.remove(data, 1)
local sref = table.remove(data, 1) local sref = table.remove(data, 1)
local ret local ret
if sref then if sref then
ret = {_G[list[0]][func](_G[list[0]], multi.unpack(data))} ret = {_G[list[0]][func](_G[list[0]], multi.unpack(data))}
else else
ret = {_G[list[0]][func](multi.unpack(data))} ret = {_G[list[0]][func](multi.unpack(data))}
end end
for i = 1,#ret do for i = 1,#ret do
if type(ret[i]) == "table" and ret[i].Type ~= nil and ret[i].Type ~= multi.registerType("proxy", "proxies") then if type(ret[i]) == "table" and ret[i].Type ~= nil and ret[i].Type ~= multi.registerType("proxy", "proxies") then
ret[i] = "\1PARENT_REF" ret[i] = "\1PARENT_REF"
end end
if type(ret[i]) == "table" and getmetatable(ret[i]) then if type(ret[i]) == "table" and getmetatable(ret[i]) then
setmetatable(ret[i],nil) -- remove that metatable, we do not need it on the other side! setmetatable(ret[i],nil) -- remove that metatable, we do not need it on the other side!
end end
if ret[i] == _G[list[0]] then if ret[i] == _G[list[0]] then
-- We cannot return itself, that return can contain bad values. -- We cannot return itself, that return can contain bad values.
ret[i] = "\1SELF_REF" ret[i] = "\1SELF_REF"
end end
end end
table.insert(ret, 1, func) table.insert(ret, 1, func)
self.recv:push(ret) self.recv:push(ret)
end) end)
end end
end end
end) end)
return self return self
else else
THREAD.sync() THREAD.sync()
if not self.funcs then return self end if not self.funcs then return self end
local function copy(obj) local function copy(obj)
if type(obj) ~= 'table' then return obj end if type(obj) ~= 'table' then return obj end
local res = {} local res = {}
for k, v in pairs(obj) do res[copy(k)] = copy(v) end for k, v in pairs(obj) do res[copy(k)] = copy(v) end
return res return res
end end
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local me = self local me = self
local funcs = copy(self.funcs) local funcs = copy(self.funcs)
if multi.integration then if multi.integration then
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
end end
self.send = THREAD.waitFor(self.name.."_S"):init() self.send = THREAD.waitFor(self.name.."_S"):init()
self.recv = THREAD.waitFor(self.name.."_R"):init() self.recv = THREAD.waitFor(self.name.."_R"):init()
self.Type = multi.registerType("proxy", "proxies") self.Type = multi.registerType("proxy", "proxies")
for _,v in pairs(funcs) do for _,v in pairs(funcs) do
if type(v) == "table" then if type(v) == "table" then
-- We have a connection -- We have a connection
v[2]:init(proc_name) v[2]:init(proc_name)
self[v[1]] = v[2] self[v[1]] = v[2]
v[2].Parent = self v[2].Parent = self
setmetatable(v[2],getmetatable(multi:newConnection())) setmetatable(v[2],getmetatable(multi:newConnection()))
else else
self[v] = thread:newFunction(function(self,...) self[v] = thread:newFunction(function(self,...)
if self == me then if self == me then
me.send:push({v, true, ...}) me.send:push({v, true, ...})
else else
me.send:push({v, false, ...}) me.send:push({v, false, ...})
end end
return thread.hold(function() return thread.hold(function()
local data = me.recv:peek() local data = me.recv:peek()
if data and data[1] == v then if data and data[1] == v then
me.recv:pop() me.recv:pop()
table.remove(data, 1) table.remove(data, 1)
for i=1,#data do for i=1,#data do
if data[i] == "\1SELF_REF" then if data[i] == "\1SELF_REF" then
data[i] = me data[i] = me
elseif data[i] == "\1PARENT_REF" then elseif data[i] == "\1PARENT_REF" then
data[i] = me.Parent data[i] = me.Parent
end end
end end
return multi.unpack(data) return multi.unpack(data)
end end
end) end)
end, true) end, true)
end end
end end
return self return self
end end
end end
function c:getTransferable() function c:getTransferable()
local cp = {} local cp = {}
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local function copy(obj) local function copy(obj)
if type(obj) ~= 'table' then return obj end if type(obj) ~= 'table' then return obj end
local res = {} local res = {}
for k, v in pairs(obj) do res[copy(k)] = copy(v) end for k, v in pairs(obj) do res[copy(k)] = copy(v) end
return res return res
end end
cp.is_init = true cp.is_init = true
cp.proxy_link = self.proxy_link cp.proxy_link = self.proxy_link
cp.name = self.name cp.name = self.name
cp.funcs = copy(self._funcs) cp.funcs = copy(self._funcs)
cp.init = function(self) cp.init = function(self)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
if multi.integration then if multi.integration then
GLOBAL = multi.integration.GLOBAL GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD THREAD = multi.integration.THREAD
end end
local proxy = THREAD.waitFor(self.proxy_link) local proxy = THREAD.waitFor(self.proxy_link)
proxy.funcs = self.funcs proxy.funcs = self.funcs
return proxy:init() return proxy:init()
end end
return cp return cp
end end
self:create(c) self:create(c)
return c return c
end end
local targets = {} local targets = {}
local references = {} local references = {}
local jid = -1 local jid = -1
function multi:newSystemThreadedProcessor(cores) function multi:newSystemThreadedProcessor(cores)
local name = "STP_"..multi.randomString(4) -- set a random name if none was given. local name = "STP_"..multi.randomString(4) -- set a random name if none was given.
local autoscale = autoscale or false -- Will scale up the number of cores that the process uses. local autoscale = autoscale or false -- Will scale up the number of cores that the process uses.
local c = {} local c = {}
setmetatable(c,{__index = multi}) setmetatable(c,{__index = multi})
c.Type = multi.registerType("s_process", "s_processes") c.Type = multi.registerType("s_process", "s_processes")
c.threads = {} c.threads = {}
c.cores = cores or 8 c.cores = cores or 8
c.Name = name c.Name = name
c.Mainloop = {} c.Mainloop = {}
c.__count = 0 c.__count = 0
c.processors = {} c.processors = {}
c.proc_list = {} c.proc_list = {}
c.OnObjectCreated = multi:newConnection() c.OnObjectCreated = multi:newConnection()
c.parent = self c.parent = self
c.jobqueue = multi:newSystemThreadedJobQueue(c.cores) c.jobqueue = multi:newSystemThreadedJobQueue(c.cores)
function c:pushJob(ID, name, ...) function c:pushJob(ID, name, ...)
local tq = THREAD.waitFor(self.Name .. "_target_tq_" .. ID):init() local tq = THREAD.waitFor(self.Name .. "_target_tq_" .. ID):init()
tq:push{name, jid, multi.pack(...)} tq:push{name, jid, multi.pack(...)}
jid = jid - 1 jid = jid - 1
return jid + 1 return jid + 1
end end
c.jobqueue:registerFunction("packObj",function(obj) c.jobqueue:registerFunction("packObj",function(obj)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local list = multi:chop(obj) local list = multi:chop(obj)
obj.__link_name = list[0] obj.__link_name = list[0]
local proxy = multi:newProxy(list):init() local proxy = multi:newProxy(list):init()
return proxy return proxy
end) end)
c.spawnThread = c.jobqueue:newFunction("__spawnThread__", function(name, func, ...) c.spawnThread = c.jobqueue:newFunction("__spawnThread__", function(name, func, ...)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local obj = thread:newThread(name, func, ...) local obj = thread:newThread(name, func, ...)
return packObj(obj) return packObj(obj)
end, true) end, true)
c.spawnTask = c.jobqueue:newFunction("__spawnTask__", function(obj, func, ...) c.spawnTask = c.jobqueue:newFunction("__spawnTask__", function(obj, func, ...)
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local obj = multi[obj](multi, func, ...) local obj = multi[obj](multi, func, ...)
return packObj(obj) return packObj(obj)
end, true) end, true)
local implement = { local implement = {
"newLoop", "newLoop",
"newTLoop", "newTLoop",
"newUpdater", "newUpdater",
"newEvent", "newEvent",
"newAlarm", "newAlarm",
"newStep", "newStep",
"newTStep", "newTStep",
"newService" "newService"
} }
for _, method in pairs(implement) do for _, method in pairs(implement) do
c[method] = thread:newFunction(function(self, ...) c[method] = thread:newFunction(function(self, ...)
proxy = self.spawnTask(method, ...) proxy = self.spawnTask(method, ...)
proxy:init() proxy:init()
references[proxy] = self references[proxy] = self
return proxy return proxy
end, true) end, true)
end end
function c:newThread(name, func, ...) function c:newThread(name, func, ...)
proxy = self.spawnThread(name, func, ...):init(self.Name) proxy = self.spawnThread(name, func, ...):init(self.Name)
references[proxy] = self references[proxy] = self
table.insert(self.threads, proxy) table.insert(self.threads, proxy)
return proxy return proxy
end end
function c:newFunction(func, holdme) function c:newFunction(func, holdme)
return self.jobqueue:newFunction(func, holdme) return self.jobqueue:newFunction(func, holdme)
end end
function c:newSharedTable(name) function c:newSharedTable(name)
if not name then multi.error("You must provide a name when creating a table!") end if not name then multi.error("You must provide a name when creating a table!") end
local tbl_name = "TABLE_"..multi.randomString(8) local tbl_name = "TABLE_"..multi.randomString(8)
self.jobqueue:doToAll(function(tbl_name, interaction) self.jobqueue:doToAll(function(tbl_name, interaction)
_G[interaction] = THREAD.waitFor(tbl_name):init() _G[interaction] = THREAD.waitFor(tbl_name):init()
end, tbl_name, name) end, tbl_name, name)
return multi:newSystemThreadedTable(tbl_name):init() return multi:newSystemThreadedTable(tbl_name):init()
end end
function c:getHandler() function c:getHandler()
return function() end -- return empty function return function() end -- return empty function
end end
function c:getThreads() function c:getThreads()
return self.threads return self.threads
end end
function c:getFullName() function c:getFullName()
return self.parent:getFullName() .. "." .. c.Name return self.parent:getFullName() .. "." .. c.Name
end end
function c:getName() function c:getName()
return self.Name return self.Name
end end
function c.run() function c.run()
return self return self
end end
function c.isActive() function c.isActive()
return true return true
end end
function c.Start() function c.Start()
return self return self
end end
function c.Stop() function c.Stop()
return self return self
end end
function c:Destroy() function c:Destroy()
return false return false
end end
return c return c
end end
+12 -12
View File
@@ -1,13 +1,13 @@
-- We need to detect what enviroment we are running our code in. -- We need to detect what enviroment we are running our code in.
return { return {
init = function() init = function()
if love then if love then
return require("multi.integration.loveManager"):init() return require("multi.integration.loveManager"):init()
else else
if pcall(require,"lanes") then if pcall(require,"lanes") then
return require("multi.integration.lanesManager"):init() return require("multi.integration.lanesManager"):init()
end end
return require("multi.integration.pesudoManager"):init() return require("multi.integration.pesudoManager"):init()
end end
end end
} }
+20 -20
View File
@@ -1,20 +1,20 @@
function love.conf(t) function love.conf(t)
t.identity = nil -- The name of the save directory (string) t.identity = nil -- The name of the save directory (string)
t.version = "12.0" -- The LOVE version this game was made for (string) t.version = "12.0" -- The LOVE version this game was made for (string)
t.console = true -- Attach a console (boolean, Windows only) t.console = true -- Attach a console (boolean, Windows only)
-- t.modules.audio = false -- Enable the audio module (boolean) -- t.modules.audio = false -- Enable the audio module (boolean)
-- t.modules.event = false -- Enable the event module (boolean) -- t.modules.event = false -- Enable the event module (boolean)
-- t.modules.graphics = false -- Enable the graphics module (boolean) -- t.modules.graphics = false -- Enable the graphics module (boolean)
-- t.modules.image = false -- Enable the image module (boolean) -- t.modules.image = false -- Enable the image module (boolean)
-- t.modules.joystick = false -- Enable the joystick module (boolean) -- t.modules.joystick = false -- Enable the joystick module (boolean)
-- t.modules.keyboard = false -- Enable the keyboard module (boolean) -- t.modules.keyboard = false -- Enable the keyboard module (boolean)
-- t.modules.math = false -- Enable the math module (boolean) -- t.modules.math = false -- Enable the math module (boolean)
-- t.modules.mouse = false -- Enable the mouse module (boolean) -- t.modules.mouse = false -- Enable the mouse module (boolean)
-- t.modules.physics = false -- Enable the physics module (boolean) -- t.modules.physics = false -- Enable the physics module (boolean)
-- t.modules.sound = false -- Enable the sound module (boolean) -- t.modules.sound = false -- Enable the sound module (boolean)
-- t.modules.system = true -- Enable the system module (boolean) -- t.modules.system = true -- Enable the system module (boolean)
-- t.modules.timer = true -- Enable the timer module (boolean) -- t.modules.timer = true -- Enable the timer module (boolean)
-- t.modules.window = false -- Enable the window module (boolean) -- t.modules.window = false -- Enable the window module (boolean)
-- t.modules.thread = true -- Enable the thread module (boolean) -- t.modules.thread = true -- Enable the thread module (boolean)
end end
+74 -74
View File
@@ -1,75 +1,75 @@
package.path = "../?/init.lua;../?.lua;"..package.path package.path = "../?/init.lua;../?.lua;"..package.path
local multi, thread = require("multi"):init{print=true, warning = true, error=true} local multi, thread = require("multi"):init{print=true, warning = true, error=true}
local utils = require("multi.integration.loveManager.utils") local utils = require("multi.integration.loveManager.utils")
local people = {1,2,3} local people = {1,2,3}
function dump(o) function dump(o)
if type(o) == 'table' then if type(o) == 'table' then
local s = '{ ' local s = '{ '
for k,v in pairs(o) do for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. '('..type(v):sub(1,1)..'),' s = s .. '['..k..'] = ' .. dump(v) .. '('..type(v):sub(1,1)..'),'
end end
return s .. '} ' return s .. '} '
else else
return tostring(o) return tostring(o)
end end
end end
local fpeople = utils.pack(people) local fpeople = utils.pack(people)
print("Pack:", dump(fpeople)) print("Pack:", dump(fpeople))
local people = utils.unpack(fpeople) local people = utils.unpack(fpeople)
print("Unpack:", dump(people)) print("Unpack:", dump(people))
print(type(people[3])) print(type(people[3]))
-- GLOBAL, THREAD = require("multi.integration.loveManager"):init() -- GLOBAL, THREAD = require("multi.integration.loveManager"):init()
-- local queue = multi:newSystemThreadedQueue("TestQueue") -- local queue = multi:newSystemThreadedQueue("TestQueue")
-- local tab = multi:newSystemThreadedTable("TestTable") -- local tab = multi:newSystemThreadedTable("TestTable")
-- local test = multi:newSystemThread("Test",function() -- local test = multi:newSystemThread("Test",function()
-- local queue = THREAD.waitFor("TestQueue") -- local queue = THREAD.waitFor("TestQueue")
-- local tab = THREAD.waitFor("TestTable") -- local tab = THREAD.waitFor("TestTable")
-- print("THREAD_ID:",THREAD_ID) -- print("THREAD_ID:",THREAD_ID)
-- queue:push("Did it work?") -- queue:push("Did it work?")
-- tab["Test"] = true -- tab["Test"] = true
-- return 1,2,3 -- return 1,2,3
-- end) -- end)
-- multi:newThread("QueueTest", function() -- multi:newThread("QueueTest", function()
-- print(thread.hold(queue)) -- print(thread.hold(queue))
-- print(thread.hold(tab, {key="Test"})) -- print(thread.hold(tab, {key="Test"}))
-- print("Done!") -- print("Done!")
-- end) -- end)
-- local jq = multi:newSystemThreadedJobQueue(n) -- local jq = multi:newSystemThreadedJobQueue(n)
-- jq:registerFunction("test2",function() -- jq:registerFunction("test2",function()
-- print("This works!") -- print("This works!")
-- end) -- end)
-- jq:registerFunction("test",function(a, b, c) -- jq:registerFunction("test",function(a, b, c)
-- print(a, b+c) -- print(a, b+c)
-- test2() -- test2()
-- return a+b+c -- return a+b+c
-- end) -- end)
-- print("Job:",jq:pushJob("test",1,2,3)) -- print("Job:",jq:pushJob("test",1,2,3))
-- print("Job:",jq:pushJob("test",2,3,4)) -- print("Job:",jq:pushJob("test",2,3,4))
-- print("Job:",jq:pushJob("test",5,6,7)) -- print("Job:",jq:pushJob("test",5,6,7))
-- jq.OnJobCompleted(function(...) -- jq.OnJobCompleted(function(...)
-- print("Job Completed!", ...) -- print("Job Completed!", ...)
-- end) -- end)
-- function love.draw() -- function love.draw()
-- -- -- --
-- end -- end
-- function love.update() -- function love.update()
-- multi:uManager() -- multi:uManager()
-- end -- end
File diff suppressed because it is too large Load Diff
+53 -53
View File
@@ -1,53 +1,53 @@
IsEvent=true IsEvent=true
event={ event={
Active=true, Active=true,
CT=false, CT=false,
tag={}, tag={},
Events={}, Events={},
EventTracker={}, EventTracker={},
Steps={}, Steps={},
setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) end, setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) end,
setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end event:new("Event_"..fname,condition,also) end, setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end event:new("Event_"..fname,condition,also) end,
removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end,
updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end,
addTracker=function(self,varname,var) event.EventTracker[varname]=var end, addTracker=function(self,varname,var) event.EventTracker[varname]=var end,
getTracker=function(self,var) return event.EventTracker[var] end, getTracker=function(self,var) return event.EventTracker[var] end,
removeTracker=function(self,var) event.EventTracker[var]=nil end, removeTracker=function(self,var) event.EventTracker[var]=nil end,
trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end,
updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end,
alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end,
new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end,
eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end,
destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end,
Stop=function() event.Active=false end, Stop=function() event.Active=false end,
OnCreate=function() end, OnCreate=function() end,
OnUpdate=function() end, OnUpdate=function() end,
OnClose=function() end, OnClose=function() end,
getActive=function() return event.tag end, getActive=function() return event.tag end,
Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end,
CManager=function() for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, CManager=function() for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then loadstring(event.Events[d])() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
createStep=function(self,tag,reset,endc) createStep=function(self,tag,reset,endc)
if not(endc) then endc=false end if not(endc) then endc=false end
if not(reset) then reset=0 end if not(reset) then reset=0 end
temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc, temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc,
Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then loadstring("Step_"..tag.."("..self.pos..",__CStep__)")() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then loadstring("Step_"..self.Name.."_End(__CStep__)")() end end end, Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then loadstring("Step_"..tag.."("..self.pos..",__CStep__)")() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then loadstring("Step_"..self.Name.."_End(__CStep__)")() end end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) self.pos=self.EndAt self.endc=true end, End=function(self) self.pos=self.EndAt self.endc=true end,
} }
table.insert(event.Steps,temp) return temp end, table.insert(event.Steps,temp) return temp end,
stepExist=function(self,tag) stepExist=function(self,tag)
for a_s=1,#event.Steps do for a_s=1,#event.Steps do
if event.Steps[a_s].Name==tag then if event.Steps[a_s].Name==tag then
return true return true
end end
end end
return false return false
end, end,
} }
+55 -55
View File
@@ -1,55 +1,55 @@
IsEvent=true IsEvent=true
event={ event={
Active=true, Active=true,
CT=false, CT=false,
tag={}, tag={},
Events={}, Events={},
EventTracker={}, EventTracker={},
Steps={}, Steps={},
--addAlarm=function(self,tag) end, --addAlarm=function(self,tag) end,
setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end, setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end,
setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end,
removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end,
updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end,
addTracker=function(self,varname,var) event.EventTracker[varname]=var end, addTracker=function(self,varname,var) event.EventTracker[varname]=var end,
getTracker=function(self,var) return event.EventTracker[var] end, getTracker=function(self,var) return event.EventTracker[var] end,
removeTracker=function(self,var) event.EventTracker[var]=nil end, removeTracker=function(self,var) event.EventTracker[var]=nil end,
trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end,
updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end,
alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end,
new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end,
eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end,
destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end,
Stop=function() event.Active=false end, Stop=function() event.Active=false end,
OnCreate=function() end, OnCreate=function() end,
OnUpdate=function() end, OnUpdate=function() end,
OnClose=function() end, OnClose=function() end,
getActive=function() return event.tag end, getActive=function() return event.tag end,
Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end,
CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
RManager=function() event.OnCreate() while event.Active==true do event.OnUpdate() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end event.OnClose() end, RManager=function() event.OnCreate() while event.Active==true do event.OnUpdate() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end event.OnClose() end,
createStep=function(self,tag,reset,endc) createStep=function(self,tag,reset,endc)
if not(endc) then endc=false end if not(endc) then endc=false end
if not(reset) then reset=0 end if not(reset) then reset=0 end
temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc, temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc,
Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end, Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) self.pos=self.EndAt self.endc=true end, End=function(self) self.pos=self.EndAt self.endc=true end,
} }
table.insert(event.Steps,temp) return temp end, table.insert(event.Steps,temp) return temp end,
stepExist=function(self,tag) stepExist=function(self,tag)
for a_s=1,#event.Steps do for a_s=1,#event.Steps do
if event.Steps[a_s].Name==tag then if event.Steps[a_s].Name==tag then
return true return true
end end
end end
return false return false
end, end,
} }
+55 -55
View File
@@ -1,55 +1,55 @@
IsEvent=true IsEvent=true
event={ event={
Active=true, Active=true,
CT=false, CT=false,
tag={}, tag={},
Events={}, Events={},
EventTracker={}, EventTracker={},
Steps={}, Steps={},
--addAlarm=function(self,tag) end, --addAlarm=function(self,tag) end,
setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end, setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end,
setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end,
removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end,
updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end,
addTracker=function(self,varname,var) event.EventTracker[varname]=var end, addTracker=function(self,varname,var) event.EventTracker[varname]=var end,
getTracker=function(self,var) return event.EventTracker[var] end, getTracker=function(self,var) return event.EventTracker[var] end,
removeTracker=function(self,var) event.EventTracker[var]=nil end, removeTracker=function(self,var) event.EventTracker[var]=nil end,
trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end,
updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end,
alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end,
new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end,
eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end,
destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end,
Stop=function() event.Active=false end, Stop=function() event.Active=false end,
OnCreate=function() end, OnCreate=function() end,
OnUpdate=function() end, OnUpdate=function() end,
OnClose=function() end, OnClose=function() end,
getActive=function() return event.tag end, getActive=function() return event.tag end,
Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end,
CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
RManager=function() event.OnCreate() while event.Active==true do event.OnUpdate() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end event.OnClose() end, RManager=function() event.OnCreate() while event.Active==true do event.OnUpdate() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end event.OnClose() end,
createStep=function(self,tag,reset,endc) createStep=function(self,tag,reset,endc)
if not(endc) then endc=false end if not(endc) then endc=false end
if not(reset) then reset=0 end if not(reset) then reset=0 end
temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc, temp={Name=tag,pos=1,endAt=reset,active=true,endc=endc,
Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end, Step=function(self) if self~=nil then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) self.pos=self.EndAt self.endc=true end, End=function(self) self.pos=self.EndAt self.endc=true end,
} }
table.insert(event.Steps,temp) return temp end, table.insert(event.Steps,temp) return temp end,
stepExist=function(self,tag) stepExist=function(self,tag)
for a_s=1,#event.Steps do for a_s=1,#event.Steps do
if event.Steps[a_s].Name==tag then if event.Steps[a_s].Name==tag then
return true return true
end end
end end
return false return false
end, end,
} }
+98 -98
View File
@@ -1,98 +1,98 @@
require("Data/BasicCommands") require("Data/BasicCommands")
IsEvent=true IsEvent=true
event={ event={
Active=true, Active=true,
CT=false, CT=false,
tag={}, tag={},
Events={}, Events={},
EventTracker={}, EventTracker={},
Steps={}, Steps={},
TSteps={}, TSteps={},
LoadOrder="/E/S/U",-- types = ESU,EUS,USE,UES,SEU,SUE LoadOrder="/E/S/U",-- types = ESU,EUS,USE,UES,SEU,SUE
setLoadOrder=function(self,str) event.LoadOrder=string.upper(str) end, setLoadOrder=function(self,str) event.LoadOrder=string.upper(str) end,
DO_Order=function() LoadOrder=event.LoadOrder LoadOrder=LoadOrder:gsub("/E", "event.RUN_EVENTS(); ") LoadOrder=LoadOrder:gsub("/S", "event.RUN_STEPS(); ") LoadOrder=LoadOrder:gsub("/U", "event.RUN_UPDATES(); ") assert(loadstring(LoadOrder))() end, DO_Order=function() LoadOrder=event.LoadOrder LoadOrder=LoadOrder:gsub("/E", "event.RUN_EVENTS(); ") LoadOrder=LoadOrder:gsub("/S", "event.RUN_STEPS(); ") LoadOrder=LoadOrder:gsub("/U", "event.RUN_UPDATES(); ") assert(loadstring(LoadOrder))() end,
RUN_EVENTS=function() for d=1,#event.Events do assert(loadstring(event.Events[d]))() end end, RUN_EVENTS=function() for d=1,#event.Events do assert(loadstring(event.Events[d]))() end end,
RUN_STEPS=function() for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end, RUN_STEPS=function() for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end,
RUN_UPDATES=function() event.OnUpdate() end, RUN_UPDATES=function() event.OnUpdate() end,
setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end, setAlarm=function(self,tag,set) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:addTracker("_Alarm_"..tag,SetCounter()) assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() end,
setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end,
removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, removeAlarm=function(self,tag) event:destroy("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end,
updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end,
addTracker=function(self,varname,var) event.EventTracker[varname]=var end, addTracker=function(self,varname,var) event.EventTracker[varname]=var end,
getTracker=function(self,varname) return event.EventTracker[varname] end, getTracker=function(self,varname) return event.EventTracker[varname] end,
removeTracker=function(self,var) event.EventTracker[var]=nil end, removeTracker=function(self,var) event.EventTracker[var]=nil end,
trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end,
updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end,
alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end,
new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end,
eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end,
destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, destroy=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end,
Stop=function() event.Active=false end, Stop=function() event.Active=false end,
OnCreate=function() end, OnCreate=function() end,
OnUpdate=function() end, OnUpdate=function() end,
OnClose=function() end, OnClose=function() end,
getActive=function() return event.tag end, getActive=function() return event.tag end,
Manager=function() event.OnCreate() while event.Active==true do event.DO_Order() end event.OnClose() end, Manager=function() event.OnCreate() while event.Active==true do event.DO_Order() end event.OnClose() end,
--Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end, --Manager=function() event.OnCreate() while event.Active==true do for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end event.OnClose() end,
CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, CManager=function() for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end, UManager=function() if event.CT==false then event.CT=true event.OnCreate() end for d=1,#event.Events do if event.Active==true then assert(loadstring(event.Events[d]))() end end for s_g=1,#event.Steps do event.Steps[s_g]:Step() end event.OnUpdate() end,
createStep=function(self,tag,reset,skip,endc) createStep=function(self,tag,reset,skip,endc)
if not(endc) then endc=false end if not(endc) then endc=false end
temp= temp=
{ {
Name=tag, Name=tag,
pos=1, pos=1,
endAt=reset or math.huge, endAt=reset or math.huge,
active=true, active=true,
endc=endc, endc=endc,
skip=skip or 0, skip=skip or 0,
spos=0, spos=0,
Step=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, Step=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
FStep=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, FStep=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self assert(loadstring("Step_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CStep__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) self.pos=self.EndAt self.endc=true end, End=function(self) self.pos=self.EndAt self.endc=true end,
} }
table.insert(event.Steps,temp) return temp end, table.insert(event.Steps,temp) return temp end,
createTStep=function(self,tag,reset,timer,endc) createTStep=function(self,tag,reset,timer,endc)
if not(endc) then endc=false end if not(endc) then endc=false end
timer=timer or 1 timer=timer or 1
temp= temp=
{ {
Name=tag, Name=tag,
pos=1, pos=1,
endAt=reset or math.huge, endAt=reset or math.huge,
active=true, active=true,
endc=endc, endc=endc,
skip= 0, skip= 0,
spos=0, spos=0,
Step=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self if self.active==true then assert(loadstring("TStep_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CStep__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, Step=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self if self.active==true then assert(loadstring("TStep_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CStep__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
FStep=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self assert(loadstring("TStep_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CStep__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, FStep=function(self) if self~=nil then if self.spos==0 then _G.__CStep__=self assert(loadstring("TStep_"..tag.."("..self.pos..",__CStep__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CStep__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) self.pos=self.EndAt self.endc=true end, End=function(self) self.pos=self.EndAt self.endc=true end,
} }
event:setAlarm("TStep_"..tag,timer) event:setAlarm("TStep_"..tag,timer)
event:addTracker("_TStep_"..tag,temp) event:addTracker("_TStep_"..tag,temp)
table.insert(event.TSteps,temp) table.insert(event.TSteps,temp)
assert(loadstring("function Alarm_TStep_"..tag.."(alarm) event:getTracker(\"_\"..alarm):Step() event:setAlarm(alarm,"..timer..") end"))() assert(loadstring("function Alarm_TStep_"..tag.."(alarm) event:getTracker(\"_\"..alarm):Step() event:setAlarm(alarm,"..timer..") end"))()
return temp end, return temp end,
stepExist=function(self,tag) stepExist=function(self,tag)
for a_s=1,#event.Steps do for a_s=1,#event.Steps do
if event.Steps[a_s].Name==tag then if event.Steps[a_s].Name==tag then
return true return true
end end
end end
return false return false
end, end,
} }
+203 -203
View File
@@ -1,203 +1,203 @@
function dump(t,indent) function dump(t,indent)
local names = {} local names = {}
if not indent then indent = "" end if not indent then indent = "" end
for n,g in pairs(t) do for n,g in pairs(t) do
table.insert(names,n) table.insert(names,n)
end end
table.sort(names) table.sort(names)
for i,n in pairs(names) do for i,n in pairs(names) do
local v = t[n] local v = t[n]
if type(v) == "table" then if type(v) == "table" then
if(v==t) then -- prevent endless loop if table contains reference to itself if(v==t) then -- prevent endless loop if table contains reference to itself
print(indent..tostring(n)..": <-") print(indent..tostring(n)..": <-")
else else
print(indent..tostring(n)..":") print(indent..tostring(n)..":")
dump(v,indent.." ") dump(v,indent.." ")
end end
else else
if type(v) == "function" then if type(v) == "function" then
print(indent..tostring(n).."()") print(indent..tostring(n).."()")
else else
print(indent..tostring(n)..": "..tostring(v)) print(indent..tostring(n)..": "..tostring(v))
end end
end end
end end
end end
function SetCounter() function SetCounter()
return os.clock() return os.clock()
end end
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
function GetCounter(count) function GetCounter(count)
if count~=nil then if count~=nil then
return os.clock()-count return os.clock()-count
else else
return 0 return 0
end end
end end
---------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------
clock=os.clock clock=os.clock
event={ event={
Active=true, Active=true,
CT=false, CT=false,
tag={}, tag={},
Events={}, Events={},
Alarms={}, Alarms={},
EventTracker={}, EventTracker={},
Steps={}, Steps={},
TSteps={}, TSteps={},
CTask="", CTask="",
LoadOrder="/E/S/A/U", LoadOrder="/E/S/A/U",
UpdateObj= UpdateObj=
{ {
LoadOrder="", LoadOrder="",
Resume=function(self) event.LoadOrder=self.LoadOrder end, Resume=function(self) event.LoadOrder=self.LoadOrder end,
Pause=function(self) self.LoadOrder=event.LoadOrder event.LoadOrder=event.LoadOrder:gsub("/U", "") end, Pause=function(self) self.LoadOrder=event.LoadOrder event.LoadOrder=event.LoadOrder:gsub("/U", "") end,
}, },
setLoadOrder=function(self,str) event.LoadOrder=string.upper(str) end, setLoadOrder=function(self,str) event.LoadOrder=string.upper(str) end,
DO_Order=function() LoadOrder=event.LoadOrder LoadOrder=LoadOrder:gsub("/A", "event.RUN_ALARMS(); ") LoadOrder=LoadOrder:gsub("/E", "event.RUN_EVENTS(); ") LoadOrder=LoadOrder:gsub("/S", "event.RUN_STEPS(); ") LoadOrder=LoadOrder:gsub("/U", "event.RUN_UPDATES(); ") assert(loadstring(LoadOrder))() end, DO_Order=function() LoadOrder=event.LoadOrder LoadOrder=LoadOrder:gsub("/A", "event.RUN_ALARMS(); ") LoadOrder=LoadOrder:gsub("/E", "event.RUN_EVENTS(); ") LoadOrder=LoadOrder:gsub("/S", "event.RUN_STEPS(); ") LoadOrder=LoadOrder:gsub("/U", "event.RUN_UPDATES(); ") assert(loadstring(LoadOrder))() end,
RUN_EVENTS=function() event.CTask="events" for d=1,#event.Events do assert(loadstring(event.Events[d]))() end end, RUN_EVENTS=function() event.CTask="events" for d=1,#event.Events do assert(loadstring(event.Events[d]))() end end,
RUN_STEPS=function() event.CTask="steps" for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end, RUN_STEPS=function() event.CTask="steps" for s_g=1,#event.Steps do event.Steps[s_g]:Step() end end,
RUN_UPDATES=function() _G.__CAction__=event.UpdateObj event.CTask="updates" event.OnUpdate() end, RUN_UPDATES=function() _G.__CAction__=event.UpdateObj event.CTask="updates" event.OnUpdate() end,
RUN_ALARMS=function() for i=1,#event.Alarms do event.Alarms[i]:Tick() end end, RUN_ALARMS=function() for i=1,#event.Alarms do event.Alarms[i]:Tick() end end,
--System Used Functions --System Used Functions
Hold=function(self,task) -- as many conditions and times that you want can be used Hold=function(self,task) -- as many conditions and times that you want can be used
local action=__CAction__ local action=__CAction__
action:Pause() action:Pause()
if type(task)=="number" then if type(task)=="number" then
local func=function() end local func=function() end
local alarm=event:newAlarm(task,func,true) local alarm=event:newAlarm(task,func,true)
while alarm.active==true do while alarm.active==true do
event.CManager() event.CManager()
end end
alarm:Destroy() alarm:Destroy()
action:Resume() action:Resume()
elseif type(task)=="string" then elseif type(task)=="string" then
assert(loadstring("while not("..task..") do event.CManager() end"))() assert(loadstring("while not("..task..") do event.CManager() end"))()
action:Resume() action:Resume()
end end
end, end,
newAlarm=function(self,set,func,start) newAlarm=function(self,set,func,start)
if not(start) then timer=0 active=false else timer=clock() active=true end if not(start) then timer=0 active=false else timer=clock() active=true end
if not(func) then func=(function() end) end if not(func) then func=(function() end) end
Alarm= Alarm=
{ {
active=active, active=active,
timer=timer, timer=timer,
set=set or 0, set=set or 0,
func=func, func=func,
Tick=function(self) _G.__CAction__=self if self.active==true then if clock()-self.timer>=self.set then self:Pause() self:Ring() end end end, Tick=function(self) _G.__CAction__=self if self.active==true then if clock()-self.timer>=self.set then self:Pause() self:Ring() end end end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Set=function(self,amt) self.set=amt self.timer=clock() self:Resume() end, Set=function(self,amt) self.set=amt self.timer=clock() self:Resume() end,
OnRing=function(self,func) self.func=func end, OnRing=function(self,func) self.func=func end,
Ring=function(self) self:func(self) end, Ring=function(self) self:func(self) end,
Reset=function(self) self.timer=clock() self:Resume() end, Reset=function(self) self.timer=clock() self:Resume() end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Destroy=function(self) for i=1,#event.Alarms do if tostring(event.Alarms[i])==tostring(self) then table.remove(event.Alarms,i) end end end, Destroy=function(self) for i=1,#event.Alarms do if tostring(event.Alarms[i])==tostring(self) then table.remove(event.Alarms,i) end end end,
} }
table.insert(event.Alarms,Alarm) table.insert(event.Alarms,Alarm)
return Alarm return Alarm
end, end,
setAlarm=function(self,tag,set) setAlarm=function(self,tag,set)
if event:eventExist("Alarm_"..tag.."(\""..tag.."\")")==false then if event:eventExist("Alarm_"..tag.."(\""..tag.."\")")==false then
event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]]) event:new("Alarm_"..tag.."(\""..tag.."\")",[[GetCounter(event:getTracker("_Alarm_]]..tag..[["))>=]]..set,[[event:removeAlarm("]]..tag..[[")]])
event:addTracker("_Alarm_"..tag,SetCounter()) event:addTracker("_Alarm_"..tag,SetCounter())
assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))() assert(loadstring("if Alarm_"..tag.."==nil then function Alarm_"..tag.."() print('No function \"Alarm_"..tag.."()\" exists make sure you created it') end end"))()
else else
event:addTracker("_Alarm_"..tag,SetCounter()) event:addTracker("_Alarm_"..tag,SetCounter())
end end
end, end,
setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end, setEvent=function(self,fname,condition,also) if not(string.find(fname,"(",1,true)) and not(string.find(fname,")",1,true)) then fname=fname.."()" end a=string.find(fname,"(",1,true) tempstr=string.sub(fname,1,a-1) event:new("Event_"..fname,condition,also) assert(loadstring("if Event_"..tempstr.."==nil then function Event_"..tempstr.."() print('No function \"Event_"..tempstr.."()\" exists make sure you created it') end end"))() end,
removeAlarm=function(self,tag) event:destroyEvent("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end, removeAlarm=function(self,tag) event:destroyEvent("Alarm_"..tag) event:removeTracker("_Alarm_"..tag) end,
updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end, updateAlarm=function(self,tag,set) event:removeAlarm(tag) event:setAlarm(tag,set) end,
addTracker=function(self,varname,var) event.EventTracker[varname]=var end, addTracker=function(self,varname,var) event.EventTracker[varname]=var end,
getTracker=function(self,varname) return event.EventTracker[varname] end, getTracker=function(self,varname) return event.EventTracker[varname] end,
listTrackers=function(self) return event.EventTracker end, listTrackers=function(self) return event.EventTracker end,
removeTracker=function(self,var) event.EventTracker[var]=nil end, removeTracker=function(self,var) event.EventTracker[var]=nil end,
trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end, trackerExist=function(self,tag) return event.EventTracker[tag]~=nil end,
updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end, updateTracker=function(self,tag,val) if event:trackerExist(tag) then event.EventTracker[tag]=val end end,
alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end, alarmExist=function(self,tag) return (event:getTracker("_Alarm_"..tag)~=nil) end,
new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end, new=function(self,fname,condition,also) if not(also) then also="" end table.insert(self.Events,"if "..condition.." then "..also.." "..fname.." end") table.insert(event.tag,fname) end,
eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end, eventExist=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then return true end end return false end,
destroyEvent=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end, destroyEvent=function(self,tag) for j=1,#event.tag do if event.tag[j]==tag then table.remove(event.tag,j) table.remove(event.Events,j) end end end,
Stop=function() event.Active=false end, Stop=function() event.Active=false end,
OnCreate=function() end, OnCreate=function() end,
OnUpdate=function() end, OnUpdate=function() end,
OnClose=function() end, OnClose=function() end,
getActive=function() return event.tag end, getActive=function() return event.tag end,
Manager=function() event.OnCreate() while event.Active==true do event.DO_Order() end event.OnClose() end, Manager=function() event.OnCreate() while event.Active==true do event.DO_Order() end event.OnClose() end,
CManager=function() if event.Active==true then event.DO_Order() end end, CManager=function() if event.Active==true then event.DO_Order() end end,
UManager=function() if event.CT==false then event.CT=true event.OnCreate() end if event.Active==true then event.DO_Order() end end, UManager=function() if event.CT==false then event.CT=true event.OnCreate() end if event.Active==true then event.DO_Order() end end,
createStep=function(self,tag,reset,skip,endc) createStep=function(self,tag,reset,skip,endc)
if not(endc) then if not(endc) then
endc=false endc=false
end end
temp= temp=
{ {
Name=tag, Name=tag,
pos=1, pos=1,
endAt=reset or math.huge, endAt=reset or math.huge,
active=true, active=true,
endc=endc, endc=endc,
skip=skip or 0, skip=skip or 0,
spos=0, spos=0,
Step=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, Step=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self if self.active==true then assert(loadstring("Step_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
FStep=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self assert(loadstring("Step_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, FStep=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self assert(loadstring("Step_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) _G.__CAction__=self assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() self:Reset() end, End=function(self) _G.__CAction__=self assert(loadstring("Step_"..self.Name.."_End(__CAction__)"))() self:Reset() end,
} }
table.insert(event.Steps,temp) return temp table.insert(event.Steps,temp) return temp
end, end,
createTStep=function(self,tag,reset,timer,endc) createTStep=function(self,tag,reset,timer,endc)
if not(endc) then if not(endc) then
endc=false endc=false
end end
timer=timer or 1 timer=timer or 1
temp= temp=
{ {
Name=tag, Name=tag,
pos=1, pos=1,
endAt=reset or math.huge, endAt=reset or math.huge,
active=true, active=true,
endc=endc, endc=endc,
skip= 0, skip= 0,
spos=0, spos=0,
Step=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self if self.active==true then assert(loadstring("TStep_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CAction__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, Step=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self if self.active==true then assert(loadstring("TStep_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CAction__)"))() end end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
FStep=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self assert(loadstring("TStep_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CAction__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end, FStep=function(self) if self~=nil then if self.spos==0 then _G.__CAction__=self assert(loadstring("TStep_"..tag.."("..self.pos..",__CAction__)"))() self.pos=self.pos+1 end end if self.endAt+1<=self.pos then self:Reset() if endc==true then assert(loadstring("TStep_"..self.Name.."_End(__CAction__)"))() end end self.spos=self.spos+1 if self.spos>=self.skip then self.spos=0 end end,
Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end, Remove=function(self) for as=1,#event.Steps do if event.Steps[as].Name==self.Name then table.remove(event.Steps,as) end end end,
Reset=function(self) self.pos=1 end, Reset=function(self) self.pos=1 end,
Set=function(self,amt) self.pos=amt end, Set=function(self,amt) self.pos=amt end,
Pause=function(self) self.active=false end, Pause=function(self) self.active=false end,
Resume=function(self) self.active=true end, Resume=function(self) self.active=true end,
Stop=function(self) self:Reset() self:Pause() end, Stop=function(self) self:Reset() self:Pause() end,
Start=function(self) self:Resume() end, Start=function(self) self:Resume() end,
End=function(self) self.pos=self.EndAt self.endc=true end, End=function(self) self.pos=self.EndAt self.endc=true end,
} }
event:setAlarm("TStep_"..tag,timer) event:setAlarm("TStep_"..tag,timer)
event:addTracker("_TStep_"..tag,temp) event:addTracker("_TStep_"..tag,temp)
table.insert(event.TSteps,temp) table.insert(event.TSteps,temp)
assert(loadstring("function Alarm_TStep_"..tag.."(alarm) event:getTracker(\"_\"..alarm):Step() event:updateAlarm(alarm,"..timer..") end"))() assert(loadstring("function Alarm_TStep_"..tag.."(alarm) event:getTracker(\"_\"..alarm):Step() event:updateAlarm(alarm,"..timer..") end"))()
return temp return temp
end, end,
stepExist=function(self,tag) stepExist=function(self,tag)
for a_s=1,#event.Steps do for a_s=1,#event.Steps do
if event.Steps[a_s].Name==tag then if event.Steps[a_s].Name==tag then
return true return true
end end
end end
return false return false
end, end,
tstepExist=function(self,tag) tstepExist=function(self,tag)
for a_s=1,#event.TSteps do for a_s=1,#event.TSteps do
if event.TSteps[a_s].Name==tag then if event.TSteps[a_s].Name==tag then
return true return true
end end
end end
return false return false
end, end,
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+365 -365
View File
@@ -1,365 +1,365 @@
multi = {} multi = {}
multi.__index = multi multi.__index = multi
multi.Mainloop={} multi.Mainloop={}
multi.Tasks={} multi.Tasks={}
multi.Tasks2={} multi.Tasks2={}
multi.Garbage={} multi.Garbage={}
multi.Children={} multi.Children={}
multi.Paused={} multi.Paused={}
multi.MasterId=0 multi.MasterId=0
multi.Active=true multi.Active=true
multi.Id=-1 multi.Id=-1
-- System -- System
function multi:newBase(ins) function multi:newBase(ins)
local c = {} local c = {}
setmetatable(c, multi) setmetatable(c, multi)
c.Parent=self c.Parent=self
c.Active=true c.Active=true
c.func={} c.func={}
c.Id=0 c.Id=0
c.Act=function() end c.Act=function() end
if ins then if ins then
table.insert(multi.Mainloop,ins,c) table.insert(multi.Mainloop,ins,c)
else else
table.insert(multi.Mainloop,c) table.insert(multi.Mainloop,c)
end end
multi.MasterId=multi.MasterId+1 multi.MasterId=multi.MasterId+1
return c return c
end end
function multi:reboot(r) function multi:reboot(r)
multi.Mainloop={} multi.Mainloop={}
multi.Tasks={} multi.Tasks={}
multi.Tasks2={} multi.Tasks2={}
multi.Garbage={} multi.Garbage={}
multi.Children={} multi.Children={}
multi.Paused={} multi.Paused={}
multi.MasterId=0 multi.MasterId=0
multi.Active=true multi.Active=true
multi.Id=-1 multi.Id=-1
if r then if r then
for i,v in pairs(_G) do for i,v in pairs(_G) do
if type(i)=="table" then if type(i)=="table" then
if i.Parent and i.Id and i.Act then if i.Parent and i.Id and i.Act then
i={} i={}
end end
end end
end end
end end
end end
--Processor --Processor
function multi.Do_Order() function multi.Do_Order()
for _D=#multi.Mainloop,1,-1 do for _D=#multi.Mainloop,1,-1 do
if multi.Mainloop[_D]~=nil then if multi.Mainloop[_D]~=nil then
multi.Mainloop[_D].Id=_D multi.Mainloop[_D].Id=_D
multi.Mainloop[_D]:Act() multi.Mainloop[_D]:Act()
end end
end end
end end
function multi:benchMark(sec) function multi:benchMark(sec)
local temp=multi:newStep(2) local temp=multi:newStep(2)
temp.CC=0 temp.CC=0
temp:OnStep(function(pos,step) step.CC=step.CC+1 end) temp:OnStep(function(pos,step) step.CC=step.CC+1 end)
local Loud=multi:newAlarm(sec) local Loud=multi:newAlarm(sec)
Loud.Link=temp Loud.Link=temp
Loud:OnRing(function(alarm) alarm.Link.CC=alarm.Link.CC print((alarm.Link.CC).." steps in "..alarm.set.." second(s)") alarm.bench=alarm.Link.CC alarm.Link:Destroy() alarm:Destroy() end) Loud:OnRing(function(alarm) alarm.Link.CC=alarm.Link.CC print((alarm.Link.CC).." steps in "..alarm.set.." second(s)") alarm.bench=alarm.Link.CC alarm.Link:Destroy() alarm:Destroy() end)
return Loud return Loud
end end
--Helpers --Helpers
function multi:FreeMainEvent() function multi:FreeMainEvent()
self.func={} self.func={}
end end
function multi:isPaused() function multi:isPaused()
return not(self.Active) return not(self.Active)
end end
function multi:Pause(n) function multi:Pause(n)
if not(n) then if not(n) then
self.Active=false self.Active=false
table.remove(multi.Mainloop,self.Id) table.remove(multi.Mainloop,self.Id)
table.insert(multi.Paused,self) table.insert(multi.Paused,self)
else else
self:hold(n) self:hold(n)
end end
end end
function multi:Resume() function multi:Resume()
if self:isPaused() then if self:isPaused() then
self.Active=true self.Active=true
table.remove(multi.Paused,self.Id) table.remove(multi.Paused,self.Id)
table.insert(multi.Mainloop,self) table.insert(multi.Mainloop,self)
end end
end end
function multi:Remove() function multi:Remove()
self:Pause() self:Pause()
self:Destroy() self:Destroy()
end end
function multi:Destroy() function multi:Destroy()
self:Pause() self:Pause()
if self:isPaused() then if self:isPaused() then
for i=1,#multi.Paused do for i=1,#multi.Paused do
if multi.Paused[i]==self then if multi.Paused[i]==self then
table.remove(multi.Paused,i) table.remove(multi.Paused,i)
return return
end end
end end
else else
table.remove(multi.Mainloop,self.Id) table.remove(multi.Mainloop,self.Id)
end end
self.Act=function() end self.Act=function() end
end end
function multi:hold(task) function multi:hold(task)
self:Pause() self:Pause()
if type(task)=="number" then if type(task)=="number" then
local alarm=multi:newAlarm(task) local alarm=multi:newAlarm(task)
while alarm.Active==true do while alarm.Active==true do
if love then if love then
multi.lManager() multi.lManager()
else else
multi.Do_Order() multi.Do_Order()
end end
end end
alarm:Destroy() alarm:Destroy()
self:Resume() self:Resume()
elseif type(task)=="function" then elseif type(task)=="function" then
local env=multi:newEvent(task) local env=multi:newEvent(task)
env:OnEvent(function(envt) envt:Pause() envt:Stop() end) env:OnEvent(function(envt) envt:Pause() envt:Stop() end)
while env.Active do while env.Active do
if love then if love then
multi.lManager() multi.lManager()
else else
multi.Do_Order() multi.Do_Order()
end end
end end
env:Destroy() env:Destroy()
self:Resume() self:Resume()
else else
print("Error Data Type!!!") print("Error Data Type!!!")
end end
end end
function multi:oneTime(func,...) function multi:oneTime(func,...)
for _k=1,#multi.Tasks2 do for _k=1,#multi.Tasks2 do
if multi.Tasks2[_k]==func then if multi.Tasks2[_k]==func then
return false return false
end end
end end
table.insert(multi.Tasks2,func) table.insert(multi.Tasks2,func)
func(...) func(...)
return true return true
end end
--Constructors --Constructors
function multi:newEvent(task) function multi:newEvent(task)
local c=multi:newBase() local c=multi:newBase()
c.Type="Event" c.Type="Event"
c.Task=task or function() end c.Task=task or function() end
function c:Act() function c:Act()
if self.Task(self) and self.Active==true then if self.Task(self) and self.Active==true then
self:Pause() self:Pause()
for _E=1,#self.func do for _E=1,#self.func do
self.func[_E](self) self.func[_E](self)
end end
end end
end end
function c:OnEvent(func) function c:OnEvent(func)
table.insert(self.func,func) table.insert(self.func,func)
end end
return c return c
end end
function multi:newAlarm(set) function multi:newAlarm(set)
local c=multi:newBase() local c=multi:newBase()
c.Type="Alarm" c.Type="Alarm"
c.timer=os.clock() c.timer=os.clock()
c.set=set or 0 c.set=set or 0
function c:Act() function c:Act()
if self.Active==true then if self.Active==true then
if os.clock()-self.timer>=self.set then if os.clock()-self.timer>=self.set then
self:Pause() self:Pause()
for i=1,#self.func do for i=1,#self.func do
self.func[i](self) self.func[i](self)
end end
end end
end end
end end
function c:Reset(n) function c:Reset(n)
if n then self.set=n end if n then self.set=n end
self.timer=os.clock() self.timer=os.clock()
self:Resume() self:Resume()
end end
function c:OnRing(func) function c:OnRing(func)
table.insert(self.func,func) table.insert(self.func,func)
end end
return c return c
end end
function multi:newTask(func) function multi:newTask(func)
table.insert(multi.Tasks,func) table.insert(multi.Tasks,func)
end end
function multi:newLoop() function multi:newLoop()
local c=multi:newBase() local c=multi:newBase()
c.Type="Loop" c.Type="Loop"
function c:Act() function c:Act()
if self.Active==true then if self.Active==true then
for i=1,#self.func do for i=1,#self.func do
self.func[i](os.clock()-multi.Start,self) self.func[i](os.clock()-multi.Start,self)
end end
end end
end end
function c:OnLoop(func) function c:OnLoop(func)
table.insert(self.func,func) table.insert(self.func,func)
end end
return c return c
end end
function multi:newStep(start,reset,count,skip) function multi:newStep(start,reset,count,skip)
local c=multi:newBase() local c=multi:newBase()
think=1 think=1
c.Type="Step" c.Type="Step"
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
c.spos=0 c.spos=0
c.count=count or 1*think c.count=count or 1*think
c.funcE={} c.funcE={}
c.start=start or 1 c.start=start or 1
if start~=nil and reset~=nil then if start~=nil and reset~=nil then
if start>reset then if start>reset then
think=-1 think=-1
end end
end end
function c:Act() function c:Act()
if self~=nil then if self~=nil then
if self.spos==0 then if self.spos==0 then
if self.Active==true then if self.Active==true then
for i=1,#self.func do for i=1,#self.func do
self.func[i](self.pos,self) self.func[i](self.pos,self)
end end
self.pos=self.pos+self.count self.pos=self.pos+self.count
end end
end end
end end
self.spos=self.spos+1 self.spos=self.spos+1
if self.spos>=self.skip then if self.spos>=self.skip then
self.spos=0 self.spos=0
end end
end end
function c:OnStep(func) function c:OnStep(func)
table.insert(self.func,1,func) table.insert(self.func,1,func)
end end
function c:OnEnd(func) function c:OnEnd(func)
table.insert(self.funcE,func) table.insert(self.funcE,func)
end end
function c:Update(start,reset,count,skip) function c:Update(start,reset,count,skip)
self.start=start or self.start self.start=start or self.start
self.endAt=reset or self.endAt self.endAt=reset or self.endAt
self.skip=skip or self.skip self.skip=skip or self.skip
self.count=count or self.count self.count=count or self.count
self:Resume() self:Resume()
end end
c:OnStep(function(p,s) c:OnStep(function(p,s)
if s.count>0 and s.endAt==p then if s.count>0 and s.endAt==p then
for fe=1,#s.funcE do for fe=1,#s.funcE do
s.funcE[fe](s) s.funcE[fe](s)
end end
s.pos=s.start-1 s.pos=s.start-1
elseif s.count<0 and s.endAt==p then elseif s.count<0 and s.endAt==p then
for fe=1,#s.funcE do for fe=1,#s.funcE do
s.funcE[fe](s) s.funcE[fe](s)
end end
s.pos=s.start-1 s.pos=s.start-1
end end
end) end)
return c return c
end end
function multi:newTStep(start,reset,count,set) function multi:newTStep(start,reset,count,set)
local c=multi:newBase() local c=multi:newBase()
think=1 think=1
c.Type="TStep" c.Type="TStep"
c.start=start or 1 c.start=start or 1
local reset = reset or math.huge local reset = reset or math.huge
c.endAt=reset c.endAt=reset
c.pos=start or 1 c.pos=start or 1
c.skip=skip or 0 c.skip=skip or 0
c.count=count or 1*think c.count=count or 1*think
c.funcE={} c.funcE={}
c.timer=os.clock() c.timer=os.clock()
c.set=set or 1 c.set=set or 1
function c:Update(start,reset,count,set) function c:Update(start,reset,count,set)
self.start=start or self.start self.start=start or self.start
self.pos=start self.pos=start
self.endAt=reset or self.endAt self.endAt=reset or self.endAt
self.set=set or self.set self.set=set or self.set
self.count=count or self.count or 1 self.count=count or self.count or 1
self.timer=os.clock() self.timer=os.clock()
self:Resume() self:Resume()
end end
function c:Act() function c:Act()
if self.Active then if self.Active then
if os.clock()-self.timer>=self.set then if os.clock()-self.timer>=self.set then
self:Reset() self:Reset()
for i=1,#self.func do for i=1,#self.func do
self.func[i](self.pos,self) self.func[i](self.pos,self)
end end
if self.endAt==self.pos then if self.endAt==self.pos then
for fe=1,#self.funcE do for fe=1,#self.funcE do
self.funcE[fe](self) self.funcE[fe](self)
end end
self.pos=self.start-1 self.pos=self.start-1
end end
self.pos=self.pos+self.count self.pos=self.pos+self.count
end end
end end
end end
function c:OnEnd(func) function c:OnEnd(func)
table.insert(self.funcE,func) table.insert(self.funcE,func)
end end
function c:Reset(n) function c:Reset(n)
if n then self.set=n end if n then self.set=n end
self.timer=os.clock() self.timer=os.clock()
self:Resume() self:Resume()
end end
function c:OnStep(func) function c:OnStep(func)
table.insert(self.func,func) table.insert(self.func,func)
end end
return c return c
end end
function multi:inQueue(func) function multi:inQueue(func)
if self.Id==-1 then if self.Id==-1 then
print("Error: Can't queue the multi object") print("Error: Can't queue the multi object")
return return
end end
local c=multi:newBase(self.Id) local c=multi:newBase(self.Id)
self.Id=self.Id-1 self.Id=self.Id-1
c.Type="Queue" c.Type="Queue"
c.Task=func c.Task=func
c.Link=self c.Link=self
function c:Act() function c:Act()
self.Task(self.Link) self.Task(self.Link)
self:Destroy() self:Destroy()
end end
end end
function multi:newTrigger(func) function multi:newTrigger(func)
local c=multi:newBase() local c=multi:newBase()
c.Type="Trigger" c.Type="Trigger"
c.trigfunc=func or function() end c.trigfunc=func or function() end
function c:Fire(...) function c:Fire(...)
self:trigfunc(self,...) self:trigfunc(self,...)
end end
return c return c
end end
--Managers --Managers
function multi:mainloop() function multi:mainloop()
for i=1,#multi.Tasks do for i=1,#multi.Tasks do
multi.Tasks[i]() multi.Tasks[i]()
end end
multi.Start=os.clock() multi.Start=os.clock()
while self.Active do while self.Active do
multi.Do_Order() multi.Do_Order()
end end
end end
function multi._tFunc(dt) function multi._tFunc(dt)
if dt then if dt then
multi.pump=true multi.pump=true
end end
multi.pumpvar=dt multi.pumpvar=dt
multi.Start=os.clock() multi.Start=os.clock()
end end
function multi:uManager(dt) function multi:uManager(dt)
multi:oneTime(multi._tFunc,dt) multi:oneTime(multi._tFunc,dt)
multi.Do_Order() multi.Do_Order()
end end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+32 -32
View File
@@ -1,33 +1,33 @@
package = "multi" package = "multi"
version = "1.10.0" version = "1.10.0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.10.0", tag = "v1.10.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only! This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only!
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes" "lanes"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+31 -31
View File
@@ -1,32 +1,32 @@
package = "multi" package = "multi"
version = "1.11.0" version = "1.11.0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.11.0", tag = "v1.11.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes" "lanes"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+29 -29
View File
@@ -1,30 +1,30 @@
package = "multi" package = "multi"
version = "1.8-2" version = "1.8-2"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.8.2", tag = "v1.8.2",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 This library contains many methods for multi tasking. From simple side by side code using multi objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1, < 5.2" "lua >= 5.1, < 5.2"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua"
} }
} }
+29 -29
View File
@@ -1,30 +1,30 @@
package = "multi" package = "multi"
version = "1.8-3" version = "1.8-3"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.8.3", tag = "v1.8.3",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1, < 5.2" "lua >= 5.1, < 5.2"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua"
} }
} }
+29 -29
View File
@@ -1,30 +1,30 @@
package = "multi" package = "multi"
version = "1.8-4" version = "1.8-4"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.8.4", tag = "v1.8.4",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1, < 5.2" "lua >= 5.1, < 5.2"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua"
} }
} }
+29 -29
View File
@@ -1,30 +1,30 @@
package = "multi" package = "multi"
version = "1.8-5" version = "1.8-5"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.8.5", tag = "v1.8.5",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1, < 5.2" "lua >= 5.1, < 5.2"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua"
} }
} }
+29 -29
View File
@@ -1,30 +1,30 @@
package = "multi" package = "multi"
version = "1.8-6" version = "1.8-6"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.8.6", tag = "v1.8.6",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes being lua 5.1 only! This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes being lua 5.1 only!
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1, < 5.2" "lua >= 5.1, < 5.2"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
package = "multi" package = "multi"
version = "1.9-1" version = "1.9-1"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.9.1", tag = "v1.9.1",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only! This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only!
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1, < 5.2" "lua >= 5.1, < 5.2"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+32 -32
View File
@@ -1,33 +1,33 @@
package = "multi" package = "multi"
version = "1.9-2" version = "1.9-2"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.9.2", tag = "v1.9.2",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only! This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only!
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes" "lanes"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+32 -32
View File
@@ -1,33 +1,33 @@
package = "multi" package = "multi"
version = "1.9-3" version = "1.9-3"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v1.9.3", tag = "v1.9.3",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only! This library contains many methods for multi tasking. From simple side by side code using multiobjs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d. Optional) The core of the library works on lua 5.1+ however the systemthreading features are limited to 5.1 due to love2d and lua lanes and now luvit (See ReadMe on gotchas) being lua 5.1 only!
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes" "lanes"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
-- Note the required Lua syntax when listing submodules as keys -- Note the required Lua syntax when listing submodules as keys
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+31 -31
View File
@@ -1,32 +1,32 @@
package = "multi" package = "multi"
version = "12.0-0" version = "12.0-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v12.0.0", tag = "v12.0.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
"lua-net" "lua-net"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.networkManager"] = "multi/integration/networkManager.lua", ["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+31 -31
View File
@@ -1,32 +1,32 @@
package = "multi" package = "multi"
version = "12.2-0" version = "12.2-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v12.2.0", tag = "v12.2.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
"lua-net" "lua-net"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.networkManager"] = "multi/integration/networkManager.lua", ["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
package = "multi" package = "multi"
version = "12.2-1" version = "12.2-1"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v12.2.1", tag = "v12.2.1",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.networkManager"] = "multi/integration/networkManager.lua", ["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
package = "multi" package = "multi"
version = "13.0-0" version = "13.0-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v13.0.0", tag = "v13.0.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.networkManager"] = "multi/integration/networkManager.lua", ["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
package = "multi" package = "multi"
version = "13.1-0" version = "13.1-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v13.1.0", tag = "v13.1.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.networkManager"] = "multi/integration/networkManager.lua", ["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+34 -34
View File
@@ -1,35 +1,35 @@
package = "multi" package = "multi"
version = "14.0-0" version = "14.0-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v14.0.0", tag = "v14.0.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d) This library contains many methods for multi tasking. From simple side by side code using multi-objs, to using coroutine based Threads and System threads(When you have lua lanes installed or are using love2d)
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
["multi.integration.shared"] = "multi/integration/shared.lua" ["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+34 -34
View File
@@ -1,35 +1,35 @@
package = "multi" package = "multi"
version = "14.1-0" version = "14.1-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v14.1.0", tag = "v14.1.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ detailed = [[
This library contains many methods for multi tasking. Features non coroutine based multitasking, coroutine based multi tasking, and system threading (Requires use of an integration). Check github for how to use. This library contains many methods for multi tasking. Features non coroutine based multitasking, coroutine based multi tasking, and system threading (Requires use of an integration). Check github for how to use.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"bin", "bin",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
--["multi.integration.shared"] = "multi/integration/shared.lua" --["multi.integration.shared"] = "multi/integration/shared.lua"
} }
} }
+33 -33
View File
@@ -1,34 +1,34 @@
package = "multi" package = "multi"
version = "14.2-0" version = "14.2-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v14.2.0", tag = "v14.2.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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 how to use. Check github for how to use.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
} }
} }
+37 -37
View File
@@ -1,38 +1,38 @@
package = "multi" package = "multi"
version = "15.0-0" version = "15.0-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v15.0.0", tag = "v15.0.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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 how to use. Check github for how to use.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.threading"] = "multi/integration/threading.lua", ["multi.integration.threading"] = "multi/integration/threading.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua", ["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua", ["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua", ["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
} }
} }
+41 -41
View File
@@ -1,42 +1,42 @@
package = "multi" package = "multi"
version = "15.1-0" version = "15.1-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "V15.1.0", tag = "V15.1.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1", "lua >= 5.1",
"lanes", "lanes",
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.compat.love2d"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.compat.lovr"] = "multi/compat/lovr.lua", ["multi.compat.lovr"] = "multi/compat/lovr.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua",
["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua", ["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua", ["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua", ["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.threading"] = "multi/integration/threading.lua", ["multi.integration.threading"] = "multi/integration/threading.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
} }
} }
+38 -38
View File
@@ -1,39 +1,39 @@
package = "multi" package = "multi"
version = "15.2-0" version = "15.2-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v15.2.0", tag = "v15.2.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua",
["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua", ["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua", ["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua", ["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.threading"] = "multi/integration/threading.lua", ["multi.integration.threading"] = "multi/integration/threading.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
} }
} }
+38 -38
View File
@@ -1,39 +1,39 @@
package = "multi" package = "multi"
version = "15.2-1" version = "15.2-1"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v15.2.1", tag = "v15.2.1",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "multi/init.lua", ["multi"] = "multi/init.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua",
["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua", ["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua", ["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua", ["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua", ["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
["multi.integration.threading"] = "multi/integration/threading.lua", ["multi.integration.threading"] = "multi/integration/threading.lua",
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua", --["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
} }
} }
+38 -38
View File
@@ -1,39 +1,39 @@
package = "multi" package = "multi"
version = "15.3-0" version = "15.3-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v15.3.0", tag = "v15.3.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "init.lua", ["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua", ["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pesudoManager"] = "integration/pesudoManager/init.lua", ["multi.integration.pesudoManager"] = "integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "integration/pesudoManager/extensions.lua", ["multi.integration.pesudoManager.extensions"] = "integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "integration/pesudoManager/threads.lua", ["multi.integration.pesudoManager.threads"] = "integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua", ["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua", ["multi.integration.threading"] = "integration/threading.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua", --["multi.integration.networkManager"] = "integration/networkManager.lua",
} }
} }
+38 -38
View File
@@ -1,39 +1,39 @@
package = "multi" package = "multi"
version = "15.3-1" version = "15.3-1"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "15.3.1", tag = "15.3.1",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "init.lua", ["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua", ["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pesudoManager"] = "integration/pesudoManager/init.lua", ["multi.integration.pesudoManager"] = "integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "integration/pesudoManager/extensions.lua", ["multi.integration.pesudoManager.extensions"] = "integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "integration/pesudoManager/threads.lua", ["multi.integration.pesudoManager.threads"] = "integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua", ["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua", ["multi.integration.threading"] = "integration/threading.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua", --["multi.integration.networkManager"] = "integration/networkManager.lua",
} }
} }
+41 -41
View File
@@ -1,42 +1,42 @@
package = "multi" package = "multi"
version = "16.0-0" version = "16.0-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v16.0.0", tag = "v16.0.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "init.lua", ["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua", ["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua", ["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua", ["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua", ["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua", ["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua", ["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua", ["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua", ["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua", --["multi.integration.networkManager"] = "integration/networkManager.lua",
} }
} }
+41 -41
View File
@@ -1,42 +1,42 @@
package = "multi" package = "multi"
version = "16.0-1" version = "16.0-1"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v16.0.1", tag = "v16.0.1",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "init.lua", ["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua", ["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua", ["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua", ["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua", ["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua", ["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua", ["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua", ["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua", ["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua", --["multi.integration.networkManager"] = "integration/networkManager.lua",
} }
} }
+41 -41
View File
@@ -1,42 +1,42 @@
package = "multi" package = "multi"
version = "16.1-0" version = "16.1-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v16.1.0", tag = "v16.1.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "init.lua", ["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua", ["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua", ["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua", ["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua", ["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua", ["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua", ["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua", ["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua", ["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua", --["multi.integration.networkManager"] = "integration/networkManager.lua",
} }
} }
+41 -41
View File
@@ -1,42 +1,42 @@
package = "multi" package = "multi"
version = "16.2-0" version = "16.2-0"
source = { source = {
url = "git://github.com/rayaman/multi.git", url = "git://github.com/rayaman/multi.git",
tag = "v16.2.0", tag = "v16.2.0",
} }
description = { description = {
summary = "Lua Multi tasking library", summary = "Lua Multi tasking library",
detailed = [[ 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). 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. Check github for documentation.
]], ]],
homepage = "https://github.com/rayaman/multi", homepage = "https://github.com/rayaman/multi",
license = "MIT" license = "MIT"
} }
dependencies = { dependencies = {
"lua >= 5.1" "lua >= 5.1"
} }
build = { build = {
type = "builtin", type = "builtin",
modules = { modules = {
["multi"] = "init.lua", ["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua", ["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua", ["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua", ["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua", ["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua", ["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua", ["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua", --["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua", --["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua", --["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua", ["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua", ["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua", ["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua", ["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua", ["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua", ["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua", ["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua", --["multi.integration.networkManager"] = "integration/networkManager.lua",
} }
} }
-39
View File
@@ -1,39 +0,0 @@
function love.conf(t)
t.identity = nil -- The name of the save directory (string)
t.version = "12.0" -- The LOVE version this game was made for (string)
t.console = true -- Attach a console (boolean, Windows only)
t.window.title = "MultiThreadTest" -- The window title (string)
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
t.window.width = 1280 -- The window width (number)
t.window.height = 720 -- The window height (number)
t.window.borderless = false -- Remove all border visuals from the window (boolean)
t.window.resizable = true -- Let the window be user-resizable (boolean)
t.window.minwidth = 1 -- Minimum window width if the window is resizable (number)
t.window.minheight = 1 -- Minimum window height if the window is resizable (number)
t.window.fullscreen = false -- Enable fullscreen (boolean)
t.window.fullscreentype = "desktop" -- Standard fullscreen or desktop fullscreen mode (string)
t.window.vsync = false -- Enable vertical sync (boolean)
t.window.fsaa = 2 -- The number of samples to use with multi-sampled antialiasing (number)
t.window.display = 1 -- Index of the monitor to show the window in (number)
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean)
t.window.srgb = false -- Enable sRGB gamma correction when drawing to the screen (boolean)
t.window.x = nil -- The x-coordinate of the window's position in the specified display (number)
t.window.y = nil -- The y-coordinate of the window's position in the specified display (number)
t.modules.audio = false -- Enable the audio module (boolean)
t.modules.event = false -- Enable the event module (boolean)
t.modules.graphics = false -- Enable the graphics module (boolean)
t.modules.image = false -- Enable the image module (boolean)
t.modules.joystick = false -- Enable the joystick module (boolean)
t.modules.keyboard = false -- Enable the keyboard module (boolean)
t.modules.math = false -- Enable the math module (boolean)
t.modules.mouse = false -- Enable the mouse module (boolean)
t.modules.physics = false -- Enable the physics module (boolean)
t.modules.sound = false -- Enable the sound module (boolean)
t.modules.system = false -- Enable the system module (boolean)
t.modules.timer = false -- Enable the timer module (boolean)
t.modules.window = false -- Enable the window module (boolean)
t.modules.thread = true -- Enable the thread module (boolean)
end
+244
View File
@@ -0,0 +1,244 @@
--[[
Test suite for multi.lua
Run with: lua multi_test.lua
Requires multi.lua to be in the same directory or on the Lua path.
Compatible with Lua 5.1, 5.2, 5.3, 5.4, and LuaJIT.
]]
package.path = "../?/init.lua;../?.lua;../init.lua;../?.lua;" .. package.path
-- ─────────────────────────────────────────────
-- Minimal test runner
-- ─────────────────────────────────────────────
local passed, failed, skipped = 0, 0, 0
local failures = {}
local function test(name, fn)
local ok, err = pcall(fn)
if ok then
passed = passed + 1
io.write("\x1b[92m ✓\x1b[0m " .. name .. "\n")
else
failed = failed + 1
table.insert(failures, {name = name, err = tostring(err)})
io.write("\x1b[91m ✗\x1b[0m " .. name .. "\n")
io.write(" " .. tostring(err) .. "\n")
end
end
local function skip(name, reason)
skipped = skipped + 1
io.write("\x1b[93m -\x1b[0m " .. name .. " [SKIPPED: " .. (reason or "") .. "]\n")
end
local function section(name)
io.write("\n\x1b[97m── " .. name .. " ──\x1b[0m\n")
end
local function assert_eq(a, b, msg)
if a ~= b then
error((msg or "assert_eq failed") .. ": expected " .. tostring(b) .. ", got " .. tostring(a), 2)
end
end
local function assert_truthy(v, msg)
if not v then
error((msg or "expected truthy value, got falsy") .. ": " .. tostring(v), 2)
end
end
local function assert_falsy(v, msg)
if v then
error((msg or "expected falsy value, got truthy") .. ": " .. tostring(v), 2)
end
end
local function assert_type(v, t, msg)
if type(v) ~= t then
error((msg or "type mismatch") .. ": expected " .. t .. ", got " .. type(v), 2)
end
end
-- ─────────────────────────────────────────────
-- Load the library
-- ─────────────────────────────────────────────
local multi, thread
local ok, err = pcall(function()
multi, thread = require("multi"):init()
end)
if not ok then
io.write("\x1b[91mFATAL: Could not load multi.lua: " .. tostring(err) .. "\x1b[0m\n")
io.write("Make sure multi.lua is in the same directory or on package.path.\n")
os.exit(1)
end
-- Helper: run the scheduler for up to `max_ticks` ticks or until `done()` returns true.
local function run_until(done, max_ticks)
max_ticks = max_ticks or 10000
for _ = 1, max_ticks do
multi:uManager()
if done and done() then return true end
end
return done == nil
end
section("Initialization")
test("lanesManager init returns GLOBAL and THREAD", function()
local GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
assert_type(GLOBAL, "table")
assert_type(THREAD, "table")
end)
test("lanesManager sets integration table", function()
assert_type(multi.integration.GLOBAL, "table")
assert_type(multi.integration.THREAD, "table")
end)
-- initialize once for rest of tests
local GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
-- ─────────────────────────────────────────────
section("SystemThreadedQueue")
test("queue push/pop", function()
local q = multi:newSystemThreadedQueue("testQ1")
q:push(42)
local val = q:pop()
assert_eq(val, 42)
end)
test("queue peek does not remove", function()
local q = multi:newSystemThreadedQueue("testQ2")
q:push("hello")
assert_eq(q:peek(), "hello")
assert_eq(q:pop(), "hello")
end)
test("queue empty returns nil", function()
local q = multi:newSystemThreadedQueue("testQ3")
assert_eq(q:pop(), nil)
end)
-- ─────────────────────────────────────────────
section("SystemThreadedTable")
test("table set/get", function()
local t = multi:newSystemThreadedTable("testT1")
t.foo = "bar"
assert_eq(t.foo, "bar")
end)
test("table overwrite", function()
local t = multi:newSystemThreadedTable("testT2")
t.x = 1
t.x = 2
assert_eq(t.x, 2)
end)
-- ─────────────────────────────────────────────
section("THREAD API")
test("THREAD set/get", function()
THREAD.set("abc", 123)
assert_eq(THREAD.get("abc"), 123)
end)
test("THREAD getCores > 0", function()
assert_truthy(THREAD.getCores() > 0)
end)
-- ─────────────────────────────────────────────
section("SystemThreadedConnection")
test("connection fires event", function()
local conn = multi:newSystemThreadedConnection("conn1"):init()
local received = nil
conn(function(v)
received = v
end)
conn:Fire("ping")
run_until(function()
return received ~= nil
end, 5000)
assert_eq(received, "ping")
end)
-- ─────────────────────────────────────────────
section("SystemThreadedJobQueue")
test("job queue executes function", function()
local jq = multi:newSystemThreadedJobQueue(1)
jq:registerFunction("add", function(a, b)
return a + b
end)
local result = nil
jq.OnJobCompleted(function(_, val)
result = val
end)
jq:pushJob("add", 2, 3)
run_until(function()
return result ~= nil
end, 10000)
assert_eq(result, 5)
end)
-- ─────────────────────────────────────────────
section("JobQueue newFunction")
test("newFunction returns correct result", function()
local jq = multi:newSystemThreadedJobQueue(1)
local fn = jq:newFunction(function(a, b)
return a * b
end,true)
local result = nil
result = fn(3, 4)
run_until(function()
return result ~= nil
end, 10000)
assert_eq(result, 12)
end)
-- ─────────────────────────────────────────────
-- Summary
-- ─────────────────────────────────────────────
section("Results")
io.write("\n")
io.write("Passed: " .. passed .. "\n")
io.write("Failed: " .. failed .. "\n")
io.write("Skipped: " .. skipped .. "\n")
if failed > 0 then
io.write("\nFailures:\n")
for _, f in ipairs(failures) do
io.write(" - " .. f.name .. "\n")
io.write(" " .. f.err .. "\n")
end
os.exit(1)
end
-10
View File
@@ -1,10 +0,0 @@
package.path = "../?/init.lua;../?.lua;"..package.path
if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
require("lldebugger").start()
end
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
require("runtests")
require("threadtests")
-1
View File
@@ -1 +0,0 @@
../
+1095
View File
File diff suppressed because it is too large Load Diff
-195
View File
@@ -1,195 +0,0 @@
package.path = "../?/init.lua;../?.lua;./init.lua;./?.lua;"..package.path
local multi, thread = require("multi"):init{print=true,warn=true,error=true}--{priority=true}
local good = false
local proc = multi:newProcessor("Test")
print("Version: "..multi.Version)
proc.Start()
proc:newAlarm(3):OnRing(function()
good = true
end)
runTest = thread:newFunction(function()
local alarms,tsteps,steps,loops,tloops,updaters,events=false,0,0,0,0,0,false
multi.print("Testing Basic Features. If this fails most other features will probably not work!")
proc:newAlarm(2):OnRing(function(a)
alarms = true
a:Destroy()
end)
proc:newTStep(1,10,1,.1):OnStep(function(t)
tsteps = tsteps + 1
end):OnEnd(function(step)
step:Destroy()
end)
proc:newStep(1,10):OnStep(function(s)
steps = steps + 1
end):OnEnd(function(step)
step:Destroy()
end)
local loop = proc:newLoop(function(l)
loops = loops + 1
end)
proc:newTLoop(function(t)
tloops = tloops + 1
end,.1)
local updater = proc:newUpdater(1):OnUpdate(function()
updaters = updaters + 1
end)
local event = proc:newEvent(function()
return alarms
end)
event.OnEvent(function(evnt)
evnt:Destroy()
events = true
multi.success("Alarms: Ok")
multi.success("Events: Ok")
if tsteps == 10 then multi.success("TSteps: Ok") else multi.error("TSteps: Bad!") end
if steps == 10 then multi.success("Steps: Ok") else multi.error("Steps: Bad!") end
if loops > 100 then multi.success("Loops: Ok") else multi.error("Loops: Bad!") end
if tloops > 10 then multi.success("TLoops: Ok") else multi.error("TLoops: Bad!") end
if updaters > 100 then multi.success("Updaters: Ok") else multi.error("Updaters: Bad!") end
end)
thread.hold(event.OnEvent)
multi.print("Starting Connection and Thread tests!")
func = thread:newFunction(function(count)
multi.print("Starting Status test: ",count)
local a = 0
while true do
a = a + 1
thread.sleep(.1)
thread.pushStatus(a,count)
if a == count then break end
end
return "Done", true, math.random(1,10000)
end)
local ret = func(10)
local ret2 = func(15)
local ret3 = func(20)
local s1,s2,s3 = 0,0,0
ret.OnError(function(...)
multi.error("Func 1:",...)
end)
ret2.OnError(function(...)
multi.error("Func 2:",...)
end)
ret3.OnError(function(...)
multi.error("Func 3:",...)
end)
ret.OnStatus(function(part,whole)
s1 = math.ceil((part/whole)*1000)/10
end)
ret2.OnStatus(function(part,whole)
s2 = math.ceil((part/whole)*1000)/10
end)
ret3.OnStatus(function(part,whole)
s3 = math.ceil((part/whole)*1000)/10
end)
ret.OnReturn(function(...)
multi.success("Done 1",...)
end)
ret2.OnReturn(function(...)
multi.success("Done 2",...)
end)
ret3.OnReturn(function(...)
multi.success("Done 3",...)
end)
local err, timeout = thread.hold(ret.OnReturn * ret2.OnReturn * ret3.OnReturn)
if s1 == 100 and s2 == 100 and s3 == 100 then
multi.success("Threads: All tests Ok")
else
if s1>0 and s2>0 and s3 > 0 then
multi.success("Thread OnStatus: Ok")
else
multi.error("Threads OnStatus or thread.hold(conn) Error!")
end
if timeout then
multi.error("Connection Error!")
else
multi.success("Connection Test 1: Ok")
end
multi.error("Connection holding Error!")
end
conn1 = proc:newConnection()
conn2 = proc:newConnection()
conn3 = proc:newConnection()
local c1,c2,c3,c4 = false,false,false,false
local a = conn1(function()
c1 = true
end)
local b = conn2(function()
c2 = true
end)
local c = conn3(function()
c3 = true
end)
local d = conn3(function()
c4 = true
end)
conn1:Fire()
conn2:Fire()
conn3:Fire()
if c1 and c2 and c3 and c4 then
multi.success("Connection Test 2: Ok")
else
multi.error("Connection Test 2: Error")
end
c3 = false
c4 = false
conn3:Unconnect(d)
conn3:Fire()
if c3 and not(c4) then
multi.success("Connection Test 3: Ok")
else
multi.error("Connection Test 3: Error removing connection")
end
if not love then
local ec = 0
multi.print("Testing pseudo threading")
capture = io.popen("lua tests/threadtests.lua p"):read("*a")
if capture:lower():match("error") then
ec = ec + 1
os.exit(1)
else
io.write(capture)
end
multi.print("Testing lanes threading")
capture = io.popen("lua tests/threadtests.lua l"):read("*a")
if capture:lower():match("error") then
ec = ec + 1
os.exit(1)
else
io.write(capture)
end
os.exit(0)
end
end)
local handle = runTest()
handle.OnError(function(...)
multi.error("Something went wrong with the test!")
print(...)
end)
if not love then
multi:mainloop()
else
local hold = thread:newFunction(function()
thread.hold(handle.OnError + handle.OnReturn)
end, true)
hold()
multi.print("Starting Threading tests!")
end
+1 -1
View File
@@ -1,4 +1,4 @@
package.path = "D:/VSCWorkspace/?/init.lua;D:/VSCWorkspace/?.lua;"..package.path package.path = "../?/init.lua;../?.lua;../init.lua;../?.lua;" .. package.path
package.cpath = "C:/luaInstalls/lua5.4/lib/lua/5.4/?/core.dll;" .. package.cpath package.cpath = "C:/luaInstalls/lua5.4/lib/lua/5.4/?/core.dll;" .. package.cpath
multi, thread = require("multi"):init{error=true,warning=true,print=true, priority=true} multi, thread = require("multi"):init{error=true,warning=true,print=true, priority=true}
proc = multi:newProcessor("Thread Test",true) proc = multi:newProcessor("Thread Test",true)
File diff suppressed because it is too large Load Diff