36 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 7f35265a8e new actions (#78) 2026-03-23 21:59:47 -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
server f8265fbb3b Update changes.md (#75)
Fixed bad console output
2026-01-11 15:25:53 -08:00
server b995b1c0a7 Update changes.md
fixed hyperlink
2026-01-11 14:24:01 -08:00
server 66e922a971 fixing issue with timestamp using lua 5.1/luajit (#72)
* fixing issue with timestamp using lua 5.1/luajit

* fixed issues, testing

* bumped up version number

* updated docs
2026-01-11 14:18:43 -08:00
server 92659c7eaf Update README.md (#71) 2026-01-03 22:36:17 -08:00
server 011ed53337 Added rockspec 2025-12-30 15:18:08 -05:00
server 474ad6438f V16.1.0 (#69)
* Fixed issue with pushstatus

* added newTimeout

* updated changes and added multi.isTimeout function

* new mod feature, helper functions for types and connections

* cleaning up

* Updated changes.md, enhanced processors

* updated docs, added multi.UUID

* updated testfile
2025-12-30 15:14:34 -05:00
server 45095191f4 V16.0.1 (#68)
* Fixed issue with pushstatus

* Fixed bug with pushstatus
2024-03-24 23:29:43 -04:00
server e44a3cd98b update working branch 2024-02-26 09:50:40 -05:00
server fff3601041 Working on 16.0.0 (#53)
* Fixed spelling, started ideaing for 16.0.0

* Updated files

* Updated readme

* Updated version

* Concat conns now properly transfer events

* Testing types

* Connections can be % with functions

* Updated connections

* Fixed issue with double thread activations (Looking for another solution)

* Working on issue with love threaded functions not waiting when in a thread

* Working on issue where threads created in threads don't work

* Fixed broken threads for love

* Fixed some issues with threads

* removed test

* Updated changes.md

* Plan on testing parity between the threading modules

* Writing tests for system threading

* Added test cases for threading, fixed issues. Todo test love2d

* Fixed love2d to succeed with tests

* All tests working

* Updated files for testing

* Modified tests to make it more seamless

* removed extra __cores in lanes/pseudo

* Working on new priority scheme

* Working on priority management

* Working on custom prioritySchemes

* Fixed issues with missing code

* Threaded processors

* THREAD.exposeENV(), thread:newProcessor()

* Typo in changes.md

* Fixed typo in pseudoManager

* fixing

* Trying to fix exposeENV with pseudoThreading

* Changes to threads

* updated changes.md

* Working on systemthreadedprocess, and experimental newProxy for threading

* newProxy and STP work

* newProxy implemented

* Proxies work with connections now :D

* Added tstep to STP, updated changes.md

* thread.hold(proxy.conn)

* Clean up connection events when holding, working on scheduling tasks/threads to system threaded processors

* Getting loads of processors implemented

* Finished getLoad(type)

* Fixed some bugs

* Added an easy way to share a table, found some limitations with lanes threading.

* THREAD_NAME set for main thread, connections break the rules for proxies

* Testing

* Really close to portable proxies, currently extreamly unstable!

* Debugging what is going on...

* Fixed critical issue with coroutine based threads

* Removed extra bloat, proxies are portable now!

* Started work on the debugManager

* Testing actions, fixing bugs with lanes

* Testing...

* fixing actions

* typo fixed

* Throw an error when things break

* fixing stuff

* Fixed issue with errors not going through

* Removed system threaded connections, soon to be replaced by proxies

* Testing love2d tests

* Test love2d

* Use later love-build

* Use ubuntu for build

* Fixed path

* Use appimage

* use sudo

* No window for love2d

* Fixed love2d tests

* Testing love2d

* Use workspace

* Moved other tests while testing

* actually pull the repo

* packagepath set

* Fixed pull

* Update multi

* Removed link

* Edited symlink

* Added timeout to build

* Rewriting loveManager, too much outdated code

* Still implementing new love2d threading code

* Rewriting love2d threading binding

* Working on adding a Hold method to all objects. Will document how they all work when done.

* jobqueues having isues with stp

* new pack/unpack for tables, current issue is things being turned into strings

* Fixed packing of values into threads, need to fix system proxies and system threaded processors

* testing...

* Not hard crashing when error is encountered

* Should now push non 0 exit codes

* Push error when an error happens

* Closer to getting things working...

* Working on new type system, planning out debugmanager

* Fixed error code issue

* Test for 5.1

* Planning out debugManager

* Some work on the debug manager, proxies working on lanes, todo get pseudo manager and love2d working

* Working on getting pseudoThreading tests to work

* Added function / connection

* Added boost method

* Document new features to conns, todo fix newTask

* Fixed newTask()

* Updated changes.md and fixed some bugs

* Added thread.defer(func)

* Fixed tests on lanes and pseudo threading, todo fix love2d threading

* Fixed paths

* Working on paths

* Testing paths

* Add test for rockspec

* Fixed issues

* Fixed typo

* Added test for defer

* Threading working in love2d

* Fixed, conf

* lanes uses a threaded function like waitfor function

* Cleaned up changes.md

* added priorityManager to rockspec
2024-02-25 00:00:51 -05:00
server 1639de5d0f Update README.md 2023-01-04 19:50:13 -05:00
server 59462df9a6 Merge pull request #52 from rayaman/15.3.1
15.3.1
2023-01-04 10:36:39 -05:00
server 72733394ac Fixed connections * 2023-01-04 10:33:36 -05:00
server dc9cee5a3e Fixing connection * issue 2023-01-04 10:28:02 -05:00
server 71ab702a75 Updated progress 2022-12-31 02:23:12 -05:00
server 1bb7410210 Merge pull request #51 from rayaman/v15.3.0
V15.3.0
2022-12-31 02:22:22 -05:00
server ec5bf74009 Fixed love2d STCs! Actually before new years :P 2022-12-31 02:21:01 -05:00
server 7ea6873c1f Fixed issue where fastmode connections wouldn't properly be removed 2022-12-30 15:22:37 -05:00
99 changed files with 30768 additions and 25262 deletions
+32
View File
@@ -0,0 +1,32 @@
name: Lua Unit Tests (Matrix)
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
luaVersion: ["5.1", "5.2", "5.3", "5.4"]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Lua
uses: leafo/gh-actions-lua@v10
with:
luaVersion: ${{ matrix.luaVersion }}
- name: Verify Lua version
run: lua -v
- name: Run unit tests
run: |
# Replace with your actual test file
lua tests/multi_test.lua
+3 -2
View File
@@ -1,2 +1,3 @@
*.code-workspace *.code-workspace
lua5.4/* lua5.4/*
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.
+26
View File
@@ -0,0 +1,26 @@
# NTHREAD Namespace
- [ ] NTHREAD.set(name, val)
- [ ] NTHREAD.get(name, val)
- [ ] NTHREAD.waitFor(name)
- [ ] NTHREAD.getCores()*
- [ ] NTHREAD.getConsole()
- [ ] NTHREAD.getThreads()
- [ ] NTHREAD.kill()
- [ ] NTHREAD.getName()
- [ ] NTHREAD.getID()
- [ ] NTHREAD.pushStatus(...)
- [ ] NTHREAD.sleep(n)
- [ ] NTHREAD.hold(n)
- [ ] NTHREAD.setENV(env)
- [ ] NTHREAD.getENV()
# Extensions
- [ ] multi:newNetworkThreadedQueue(name)
- [ ] multi:newNetworkThreadedTable(name)
- [ ] multi:newNetworkThreadedJobQueue(n)
- [ ] multi:newNetworkThreadedConnection(name)
# Core
- [ ] NTHREAD:newFunction(func, holdme)
- [ ] NTHREAD:newNetworkThread(name, func, ...)
- [ ] mulit:newNetworkThread(name, func, ...)
+100 -82
View File
@@ -1,82 +1,100 @@
# Multi Version: 15.3.0 A world of Connections # Multi Version: 16.3.0 -
**Key Changes** **Key Changes**
- SystemThreadedConnections - Fixed connection multiplying
- Restructured the directory structure of the repo (Allows for keeping multi as a submodule and being able to require it as is) - Optimizing the library
- Bug fixes - Updated task management support
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it! Refer to the [Change Log](https://github.com/rayaman/multi/blob/master/docs/changes.md) for more infromation
My multitasking library for lua. It is a pure lua binding, with exceptions of the integrations. Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
</br> My multitasking library for lua. It is a pure lua binding, with exceptions of the integrations.
Progress is being made in [v15.4.0](https://github.com/rayaman/multi/tree/v15.4.0) </br>
---
Progress is being made in [v16.3.0](https://github.com/rayaman/multi/tree/v16.3.0)
</br> ---
INSTALLING </br>
----------
Link to optional dependencies: INSTALLING
- [lanes](https://github.com/LuaLanes/lanes) ----------
Link to optional dependencies:
- [love2d](https://love2d.org/) - [lanes](https://github.com/LuaLanes/lanes) `luarocks install lanes`
To install copy the multi folder into your environment and you are good to go</br> - [chronos](https://github.com/ldrumm/chronos) `luarocks install chronos`
If you want to use the system threads, then you'll need to install lanes or love2d game engine!
- [love2d](https://love2d.org/)
```
luarocks install multi When using love2d add multi:uManager() or any processor to love.update()
```
```lua
Discord function love.update(dt)
------- multi:uManager()
Have a question or need realtime assistance? Feel free to join the discord!</br> end
https://discord.gg/U8UspuA ```
Planned features/TODO 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!
- [ ] Create test suite (In progress, mostly done)
- [ ] Network Parallelism rework ```
luarocks install multi
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/Documentation.md) ```
-----
Discord
```lua -------
local multi, thread = require("multi"):init() Have a question or need realtime assistance? Feel free to join the discord!</br>
GLOBAL, THREAD = require("multi.integration.threading"):init() https://discord.gg/U8UspuA
multi:newSystemThread("System Thread",function() Planned features/TODO
while true do ---------------------
THREAD.sleep(.1) - [x] ~~Create test suite (In progress, mostly done)~~
io.write(" World") - [ ] Network Parallelism rework
THREAD.kill()
end Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/docs/Documentation.md)
end) -----
multi:newThread("Coroutine Based Thread",function() You can run tests in 2 ways:
while true do ```
io.write("Hello") lua tests/runtests.lua (Runs all tests, attempts to use lanes)
thread.sleep(.1) love tests (Runs all tests in love2d env)
thread.kill() ```
end
end) ```lua
local multi, thread = require("multi"):init()
multi:newTLoop(function(loop) GLOBAL, THREAD = require("multi.integration.threading"):init()
print("!")
loop:Destroy() multi:newSystemThread("System Thread",function()
os.exit() while true do
end,.3) THREAD.sleep(.1)
io.write(" World")
multi:mainloop() THREAD.kill()
end
--[[ end)
while true do
multi:uManager() multi:newThread("Coroutine Based Thread",function()
end while true do
]] io.write("Hello")
``` thread.sleep(.1)
thread.kill()
Known Bugs/Issues end
----------------- end)
Check the [Issues tab](https://github.com/rayaman/multi/issues) for issues
multi:newTLoop(function(loop)
print("!")
loop:Destroy()
os.exit()
end,.3)
multi:mainloop()
--[[
while true do
multi:uManager()
end
]]
```
Known Bugs/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
+3697 -2906
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2993 -2256
View File
File diff suppressed because it is too large Load Diff
+106
View File
@@ -0,0 +1,106 @@
local multi, thread = require("multi"):init()
multi.defaultSettings.debugging = true
local dbg = {}
dbg.__index = dbg
dbg.processors = {}
-- Hooks to all on object created events!
local c_cache = {}
local d_cache = {}
local proc = multi:newProcessor("Debug_Processor").Start()
dbg.OnObjectCreated = function(obj, process)
if c_cache[obj] then
return false
else
c_cache[obj] = true
proc:newTask(function()
c_cache[obj] = false
end)
return true
end
end .. multi:newConnection()
dbg.OnObjectDestroyed = function(obj, process)
if d_cache[obj] then
return false
else
d_cache[obj] = true
proc:newTask(function()
d_cache[obj] = false
end)
return true
end
end .. multi:newConnection()
local creation_hook, destruction_hook
local types
local objects = {}
creation_hook = function(obj, process)
types = multi:getTypes()
if obj.Type == multi.PROCESS and not dbg.processors[obj] then
obj.OnObjectCreated(creation_hook)
obj.OnObjectDestroyed(destruction_hook)
end
table.insert(objects, obj)
dbg.OnObjectCreated:Fire(obj, process)
end
destruction_hook = function(obj, process)
for i = 1, #objects do
if objects[i] == obj then
table.remove(objects, i)
break
end
end
dbg.OnObjectDestroyed:Fire(obj, process)
end
function dbg:getObjects(typ)
if type(typ) == "string" then
local objs = {}
for i = 1, #objects do
if objects[i].Type == typ then
objs[#objs+1] = objects[i]
end
end
return objs
elseif type(typ) == "table" then -- Process
local objs = {}
for i = 1, #objects do
if objects[i].Parent == typ then
objs[#objs+1] = objects[i]
end
end
return objs
elseif type(typ) == "function" then
local objs = {}
-- Keep objects local/private, return true to add to list, false to reject, "break" to break loop
for i = 1, #objects do
local ret = typ(objects[i])
if ret then
objs[#objs+1] = objects[i]
elseif ret == "break" then
break
end
end
return objs
end
end
local debug_stats = {}
local tmulti = multi:getThreadManagerProcess()
multi.OnObjectCreated(creation_hook)
tmulti.OnObjectCreated(creation_hook)
multi.OnObjectDestroyed(destroction_hook)
tmulti.OnObjectDestroyed(destroction_hook)
-- We write to a debug interface in the multi namespace
multi.debugging = dbg
+46
View File
@@ -0,0 +1,46 @@
local multi, thread = require("multi"):init{error=true}
multi.error("Currntly not supported!")
os.exit(1)
local effil = require("effil")
-- I like some of the things that this library offers.
-- Current limitations prevent me from being able to use effil,
-- but I might fork and work on it myself.
-- Configs
effil.allow_table_upvalues(false)
local GLOBAL,THREAD = require("multi.integration.effilManager.threads").init()
local count = 1
local started = false
local livingThreads = {}
function multi:newSystemThread(name, func, ...)
local name = name or multi.randomString(16)
local rand = math.random(1, 10000000)
c = {}
c.name = name
c.Name = name
c.Id = count
end
function THREAD:newFunction(func, holdme)
return thread:newFunctionBase(function(...)
return multi:newSystemThread("TempSystemThread",func,...)
end, holdme, multi.SFUNCTION)()
end
THREAD.newSystemThread = function(...)
multi:newSystemThread(...)
end
multi.print("Integrated Effil Threading!")
multi.integration = {} -- for module creators
multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD
require("multi.integration.effilManager.extensions")
return {
init = function()
return GLOBAL, THREAD
end
}
+397 -312
View File
@@ -1,312 +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
local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD if not (GLOBAL and THREAD) then
else GLOBAL, THREAD = multi.integration.GLOBAL, multi.integration.THREAD
lanes = require("lanes") else
end lanes = require("lanes")
function multi:newSystemThreadedQueue(name) end
local name = name or multi.randomString(16)
local c = {} function multi:newSystemThreadedQueue(name)
c.Name = name local name = name or multi.randomString(16)
c.linda = lanes.linda() local c = {}
function c:push(v) c.Name = name
self.linda:send("Q", v) c.linda = lanes.linda()
end c.Type = multi.registerType("s_queue")
function c:pop()
return ({self.linda:receive(0, "Q")})[2] function c:push(v)
end self.linda:send("Q", v)
function c:peek() end
return self.linda:get("Q")
end function c:pop()
function c:init() return ({self.linda:receive(0, "Q")})[2]
return self end
end
GLOBAL[name or "_"] = c function c:peek()
return c return self.linda:get("Q")
end end
function multi:newSystemThreadedTable(name) function c:init()
local name = name or multi.randomString(16) return self
local c = {} end
c.link = lanes.linda()
c.Name = name if multi.isMainThread then
setmetatable(c,{ multi.integration.GLOBAL[name] = c
__index = function(t,k) else
return c.link:get(k) GLOBAL[name] = c
end, end
__newindex = function(t,k,v)
c.link:set(k,v) local peek = function()
end return c:peek()
}) end
function c:init()
return self local pop = function()
end return c:pop()
GLOBAL[name or "_"] = c end
return c
end function c:Hold(opt)
local multi, thread = require("multi"):init()
function multi:newSystemThreadedJobQueue(n) if opt.peek then
local c = {} return thread.hold(peek)
c.cores = n or THREAD.getCores()*2 else
c.OnJobCompleted = multi:newConnection() return thread.hold(pop)
local funcs = multi:newSystemThreadedTable():init() end
local queueJob = multi:newSystemThreadedQueue():init() end
local queueReturn = multi:newSystemThreadedQueue():init()
local doAll = multi:newSystemThreadedQueue():init() self:create(c)
local ID=1
local jid = 1 return c
function c:isEmpty() end
return queueJob:peek()==nil
end function multi:newSystemThreadedTable(name)
function c:doToAll(func) local name = name or multi.randomString(16)
for i=1,c.cores do local c = {}
doAll:push{ID,func} c.link = lanes.linda()
end c.Name = name
ID = ID + 1 c.Type = multi.registerType("s_table")
return self
end function c:init()
function c:registerFunction(name,func) return self
funcs[name]=func end
return self
end setmetatable(c,{
function c:pushJob(name,...) __index = function(t,k)
queueJob:push{name,jid,{...}} return c.link:get(k)
jid = jid + 1 end,
return jid-1 __newindex = function(t,k,v)
end c.link:set(k, v)
local nFunc = 0 end
function c:newFunction(name,func,holup) -- This registers with the queue })
if type(name)=="function" then
holup = func if multi.isMainThread then
func = name multi.integration.GLOBAL[name] = c
name = "JQ_Function_"..nFunc else
end GLOBAL[name] = c
nFunc = nFunc + 1 end
c:registerFunction(name,func)
return thread:newFunction(function(...) function c:Hold(opt)
local id = c:pushJob(name,...) local multi, thread = require("multi"):init()
local link if opt.key then
local rets return thread.hold(function()
link = c.OnJobCompleted(function(jid,...) return self.tab[opt.key]
if id==jid then end)
rets = {...} else
link:Destroy() multi.error("Must provide a key to check opt.key = 'key'")
end end
end) end
return thread.hold(function()
if rets then self:create(c)
return unpack(rets) or multi.NIL
end return c
end) end
end,holup),name
end function multi:newSystemThreadedJobQueue(n)
thread:newThread("JobQueueManager",function() local c = {}
while true do c.cores = n or THREAD.getCores()*2
local job = thread.hold(function() c.Type = multi.registerType("s_jobqueue")
return queueReturn:pop() c.OnJobCompleted = multi:newConnection()
end) local funcs = multi:newSystemThreadedTable()
local id = table.remove(job,1) local queueJob = multi:newSystemThreadedQueue()
c.OnJobCompleted:Fire(id,unpack(job)) local queueReturn = multi:newSystemThreadedQueue()
end local doAll = multi:newSystemThreadedQueue()
end) local ID=1
for i=1,c.cores do local jid = 1
multi:newSystemThread("SystemThreadedJobQueue",function(queue) function c:isEmpty()
local multi,thread = require("multi"):init() return queueJob:peek()==nil
local idle = os.clock() end
local clock = os.clock function c:doToAll(func,...)
local ref = 0 for i=1,c.cores do
setmetatable(_G,{__index = funcs}) doAll:push{ID,func,...}
thread:newThread("JobHandler",function() end
while true do ID = ID + 1
local dat = thread.hold(function() return self
return queueJob:pop() end
end) function c:registerFunction(name,func)
idle = clock() funcs[name]=func
local name = table.remove(dat,1) return self
local jid = table.remove(dat,1) end
local args = table.remove(dat,1) function c:pushJob(name,...)
queueReturn:push{jid, funcs[name](unpack(args)),queue} queueJob:push{name,jid,multi.pack(...)}
end jid = jid + 1
end) return jid-1
thread:newThread("DoAllHandler",function() end
while true do local nFunc = 0
local dat = thread.hold(function() function c:newFunction(name, func, holup) -- This registers with the queue
return doAll:peek() if type(name)=="function" then
end) holup = func
if dat then func = name
if dat[1]>ref then name = "JQ_Function_"..nFunc
idle = clock() end
ref = dat[1] nFunc = nFunc + 1
dat[2]() c:registerFunction(name,func)
doAll:pop() return thread:newFunction(function(...)
end local id = c:pushJob(name,...)
end local link
end local rets
end) link = c.OnJobCompleted(function(jid,...)
thread:newThread("IdleHandler",function() if id==jid then
while true do rets = multi.pack(...)
thread.hold(function() end
return clock()-idle>3 end)
end) return thread.hold(function()
THREAD.sleep(.01) if rets then
end if #rets == 0 then
end) return multi.NIL
multi:mainloop() else
end,i).priority = thread.Priority_Core return multi.unpack(rets)
end end
return c end
end end)
end, holup), name
function multi:newSystemThreadedConnection(name) end
local name = name or multi.randomString(16) thread:newThread("JobQueueManager",function()
local c = {} while true do
c.CONN = 0x00 local job = thread.hold(function()
c.TRIG = 0x01 return queueReturn:pop()
c.PING = 0x02 end)
c.PONG = 0x03 if job then
local function remove(a, b) local id = table.remove(job,1)
local ai = {} c.OnJobCompleted:Fire(id,multi.unpack(job))
local r = {} end
for k,v in pairs(a) do ai[v]=true end end
for k,v in pairs(b) do end)
if ai[v]==nil then table.insert(r,a[k]) end for i=1,c.cores do
end multi:newSystemThread("STJQ_"..multi.randomString(8),function(queue)
return r local multi, thread = require("multi"):init()
end local idle = os.clock()
c.CID = THREAD.getID() local clock = os.clock
c.subscribe = multi:newSystemThreadedQueue("SUB_STC_"..self.Name):init() local ref = 0
c.Name = name _G["__QR"] = queueReturn
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. setmetatable(_G,{__index = funcs})
-- Locals will only live in the thread that creates the original object thread:newThread("JobHandler",function()
local ping while true do
local pong = function(link, links) local dat = thread.hold(function()
local res = thread.hold(function() return queueJob:pop()
return link:peek()[1] == c.PONG end)
end,{sleep=3}) idle = clock()
thread:newThread("JobQueue-Spawn",function()
if not res then local name = table.remove(dat, 1)
for i=1,#links do local jid = table.remove(dat, 1)
if links[i] == link then local args = table.remove(dat, 1)
table.remove(links,i,link) queueReturn:push{jid, funcs[name](args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]), queue}
break end)
end end
end end)
else thread:newThread("DoAllHandler",function()
link:pop() while true do
end local dat = thread.hold(function()
end return doAll:peek()
end)
ping = thread:newFunction(function(self) if dat then
ping:Pause() if dat[1]>ref then
multi.ForEach(self.links, function(link) -- Sync new connections ref = table.remove(dat, 1)
link:push{self.PING} func = table.remove(dat, 1)
multi:newThread("pong Thread", pong, link, self.links) idle = clock()
end) func(unpack(dat))
doAll:pop()
thread.sleep(3) end
end
ping:Resume() end
end,false) end)
thread:newThread("IdleHandler",function()
local function fire(...) while true do
for _, link in pairs(c.links) do thread.hold(function()
link:push {c.TRIG, {...}} return clock()-idle>3
end end)
end THREAD.sleep(.01)
end
thread:newThread("STC_SUB_MAN"..name,function() end)
local item multi:mainloop()
local sub_func = function() -- This will keep things held up until there is something to process end,i)
return c.subscribe:pop() end
end
while true do function c:Hold(opt)
thread.yield() return thread.hold(self.OnJobCompleted)
-- We need to check on broken connections end
ping(c) -- Should return instantlly and process this in another thread
item = thread.hold(sub_func) self:create(c)
if item[1] == c.CONN then
multi.ForEach(c.links, function(link) -- Sync new connections return c
item[2]:push{c.CONN, link} end
end)
c.links[#c.links+1] = item[2] function multi:newSystemThreadedConnection(name)
elseif item[1] == c.TRIG then local name = name or multi.randomString(16)
fire(unpack(item[2])) local c = {}
c.proxy_conn:Fire(unpack(item[2])) c.Type = multi.registerType("s_connection")
end c.CONN = 0x00
end c.TRIG = 0x01
end) c.PING = 0x02
--- ^^^ This will only exist in the init thread c.PONG = 0x03
local function remove(a, b)
function c:Fire(...) local ai = {}
local args = {...} local r = {}
if self.CID == THREAD.getID() then -- Host Call for k,v in pairs(a) do ai[v]=true end
for _, link in pairs(self.links) do for k,v in pairs(b) do
link:push {self.TRIG, args} if ai[v]==nil then table.insert(r,a[k]) end
end end
self.proxy_conn:Fire(...) return r
else end
self.subscribe:push {self.TRIG, args} c.CID = THREAD_ID
end c.subscribe = multi:newSystemThreadedQueue("SUB_STC_"..self.Name):init()
end c.Name = name
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.
function c:init() -- Locals will only live in the thread that creates the original object
local multi, thread = require("multi"):init() local ping
self.links = {} local pong = function(link, links)
self.proxy_conn = multi:newConnection() local res = thread.hold(function()
local mt = getmetatable(self.proxy_conn) return link:peek()[1] == c.PONG
setmetatable(self, {__index = self.proxy_conn, __call = function(t,func) self.proxy_conn(func) end, __add = mt.__add}) end,{sleep=3})
if self.CID == THREAD.getID() then return self end
thread:newThread("STC_CONN_MAN"..name,function() if not res then
local item for i=1,#links do
local link_self_ref = multi:newSystemThreadedQueue() if links[i] == link then
self.subscribe:push{self.CONN, link_self_ref} table.remove(links,i,link)
while true do break
item = thread.hold(function() end
return link_self_ref:peek() end
end) else
if item[1] == self.PING then link:pop()
link_self_ref:push{self.PONG} end
link_self_ref:pop() end
elseif item[1] == self.CONN then
if item[2].Name ~= link_self_ref.Name then ping = thread:newFunction(function(self)
table.insert(self.links, item[2]) ping:Pause()
end multi.ForEach(self.links, function(link) -- Sync new connections
link_self_ref:pop() link:push{self.PING}
elseif item[1] == self.TRIG then multi:newThread("pong Thread", pong, link, self.links)
self.proxy_conn:Fire(unpack(item[2])) end)
link_self_ref:pop()
else thread.sleep(3)
-- This shouldn't be the case
end ping:Resume()
end end,false)
end)
return self local function fire(...)
end for _, link in pairs(c.links) do
link:push {c.TRIG, multi.pack(...)}
GLOBAL[name] = c end
end
return c
end thread:newThread("STC_SUB_MAN"..name,function()
local item
local sub_func = function() -- This will keep things held up until there is something to process
return c.subscribe:pop()
end
while true do
thread.yield()
-- We need to check on broken connections
ping(c) -- Should return instantlly and process this in another thread
item = thread.hold(sub_func)
if item[1] == c.CONN then
multi.ForEach(c.links, function(link) -- Sync new connections
item[2]:push{c.CONN, link}
end)
c.links[#c.links+1] = item[2]
elseif item[1] == c.TRIG then
fire(multi.unpack(item[2]))
c.proxy_conn:Fire(multi.unpack(item[2]))
end
end
end)
--- ^^^ This will only exist in the init thread
function c:Fire(...)
local args = multi.pack(...)
if self.CID == THREAD_ID then -- Host Call
for _, link in pairs(self.links) do
link:push {self.TRIG, args}
end
self.proxy_conn:Fire(...)
else
self.subscribe:push {self.TRIG, args}
end
end
function c:init()
local multi, thread = require("multi"):init()
self.links = {}
self.proxy_conn = multi:newConnection()
local mt = getmetatable(self.proxy_conn)
local tempMT = {}
for i,v in pairs(mt) do
tempMT[i] = v
end
tempMT.__index = self.proxy_conn
tempMT.__call = function(t,func) self.proxy_conn(func) end
setmetatable(self, tempMT)
if self.CID == THREAD_ID then return self end
thread:newThread("STC_CONN_MAN"..name,function()
local item
local link_self_ref = multi:newSystemThreadedQueue()
self.subscribe:push{self.CONN, link_self_ref}
while true do
item = thread.hold(function()
return link_self_ref:peek()
end)
if item[1] == self.PING then
link_self_ref:push{self.PONG}
link_self_ref:pop()
elseif item[1] == self.CONN then
if item[2].Name ~= link_self_ref.Name then
table.insert(self.links, item[2])
end
link_self_ref:pop()
elseif item[1] == self.TRIG then
self.proxy_conn:Fire(multi.unpack(item[2]))
link_self_ref:pop()
else
-- This shouldn't be the case
end
end
end)
return self
end
if multi.isMainThread then
multi.integration.GLOBAL[name] = c
else
GLOBAL[name] = c
end
self:create(c)
return c
end
require("multi.integration.sharedExtensions")
+205 -180
View File
@@ -1,180 +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
function multi:canSystemThread() _G.THREAD_NAME = "MAIN_THREAD"
return true _G.THREAD_ID = 0
end
function multi:canSystemThread()
function multi:getPlatform() return true
return "lanes" end
end
function multi:getPlatform()
-- Step 2 set up the Linda objects return "lanes"
local __GlobalLinda = lanes.linda() -- handles global stuff end
local __SleepingLinda = lanes.linda() -- handles sleeping stuff
local __ConsoleLinda = lanes.linda() -- handles console stuff -- Step 2 set up the Linda objects
local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions local __GlobalLinda = lanes.linda() -- handles global stuff
local __SleepingLinda = lanes.linda() -- handles sleeping stuff
local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda, __ConsoleLinda) local __ConsoleLinda = lanes.linda() -- handles console stuff
local count = 1 local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions
local started = false
local livingThreads = {} local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda, __ConsoleLinda)
local count = 1
function THREAD:newFunction(func,holdme) local started = false
return thread:newFunctionBase(function(...) local livingThreads = {}
return multi:newSystemThread("TempSystemThread",func,...)
end,holdme)() function THREAD:newFunction(func, holdme)
end return thread:newFunctionBase(function(...)
return multi:newSystemThread("TempSystemThread",func,...)
function multi:newSystemThread(name, func, ...) end, holdme, multi.registerType("s_function"))()
local name = name or multi.randomString(16) end
multi.InitSystemThreadErrorHandler()
local rand = math.random(1, 10000000) function multi:newSystemThread(name, func, ...)
local return_linda = lanes.linda() local name = name or multi.randomString(16)
c = {} multi.InitSystemThreadErrorHandler()
c.name = name local rand = math.random(1, 10000000)
c.Name = name local return_linda = lanes.linda()
c.Id = count c = {}
c.loadString = {"base","package","os","io","math","table","string","coroutine"} c.Name = name
livingThreads[count] = {true, name} c.ID = count
c.returns = return_linda c.loadString = {"base","package","os","io","math","table","string","coroutine"}
c.Type = "sthread" livingThreads[count] = {true, name}
c.creationTime = os.clock() c.returns = return_linda
c.alive = true c.Type = multi.registerType("s_thread")
c.priority = THREAD.Priority_Normal c.creationTime = os.clock()
local multi_settings = multi.defaultSettings c.alive = true
for i,v in pairs(multi_settings) do c.priority = THREAD.Priority_Normal
print(i,v) local multi_settings = multi.defaultSettings
end local globe = {
c.thread = lanes.gen("*", THREAD_NAME = name,
{ THREAD_ID = count,
globals={ -- Set up some globals THREAD = THREAD,
THREAD_NAME = name, GLOBAL = GLOBAL,
THREAD_ID = count, _Console = __ConsoleLinda,
THREAD = THREAD, _DEFER = {}
GLOBAL = GLOBAL, }
_Console = __ConsoleLinda if GLOBAL["__env"] then
}, for i,v in pairs(GLOBAL["__env"]) do
priority=c.priority globe[i] = v
},function(...) end
require("multi"):init(multi_settings) end
require("multi.integration.lanesManager.extensions") c.thread = lanes.gen("*",
local has_error = true {
return_linda:set("returns",{func(...)}) globals = globe,
has_error = false priority = c.priority
end)(...) },function(...)
count = count + 1 multi, thread = require("multi"):init(multi_settings)
function c:getName() require("multi.integration.lanesManager.extensions")
return c.Name require("multi.integration.sharedExtensions")
end local has_error = true
function c:kill() returns = {pcall(func, ...)}
self.thread:cancel() return_linda:set("returns", returns)
self.alive = false for i,v in pairs(_DEFER) do
end pcall(v)
table.insert(multi.SystemThreads, c) end
c.OnDeath = multi:newConnection() has_error = false
c.OnError = multi:newConnection() end)(...)
GLOBAL["__THREADS__"] = livingThreads count = count + 1
return c function c:getName()
end return c.Name
end
THREAD.newSystemThread = multi.newSystemThread function c:kill()
self.thread:cancel()
function multi.InitSystemThreadErrorHandler() self.alive = false
if started == true then end
return table.insert(multi.SystemThreads, c)
end c.OnDeath = multi:newConnection()
started = true c.OnError = multi:newConnection()
thread:newThread("SystemThreadScheduler",function() GLOBAL["__THREADS__"] = livingThreads
local threads = multi.SystemThreads c.OnError(multi.error)
local _,data,status,push,temp
while true do if self.isActor then
thread.yield() self:create(c)
_,data = __ConsoleLinda:receive(0, "Q") else
if data then print(unpack(data)) end multi.create(multi, c)
for i = #threads, 1, -1 do end
temp = threads[i]
status = temp.thread.status return c
push = __StatusLinda:get(temp.Id) end
if push then
temp.statusconnector:Fire(unpack(({__StatusLinda:receive(nil, temp.Id)})[2])) THREAD.newSystemThread = function(...)
end multi:newSystemThread(...)
if status == "done" or temp.returns:get("returns") then end
livingThreads[temp.Id] = {false, temp.Name}
temp.alive = false function multi.InitSystemThreadErrorHandler()
temp.OnDeath:Fire(unpack(({temp.returns:receive(0, "returns")})[2])) if started == true then
GLOBAL["__THREADS__"] = livingThreads return
table.remove(threads, i) end
elseif status == "running" then started = true
-- thread:newThread("SystemThreadScheduler",function()
elseif status == "waiting" then local threads = multi.SystemThreads
-- local _,data,status,push,temp
elseif status == "error" then while true do
livingThreads[temp.Id] = {false, temp.Name} thread.yield()
temp.alive = false _,data = __ConsoleLinda:receive(0, "Q")
temp.OnError:Fire(temp,unpack(temp.returns:receive(0,"returns") or {"Thread Killed!"})) if data then
GLOBAL["__THREADS__"] = livingThreads --print(data[1])
table.remove(threads, i) end
elseif status == "cancelled" then for i = #threads, 1, -1 do
livingThreads[temp.Id] = {false, temp.Name} temp = threads[i]
temp.alive = false status = temp.thread.status
temp.OnError:Fire(temp,"thread_cancelled") push = __StatusLinda:get(temp.ID)
GLOBAL["__THREADS__"] = livingThreads if push then
table.remove(threads, i) temp.statusconnector:Fire(multi.unpack(({__StatusLinda:receive(nil, temp.ID)})[2]))
elseif status == "killed" then end
livingThreads[temp.Id] = {false, temp.Name} if status == "done" or temp.returns:get("returns") then
temp.alive = false returns = ({temp.returns:receive(0, "returns")})[2]
temp.OnError:Fire(temp,"thread_killed") livingThreads[temp.ID] = {false, temp.Name}
GLOBAL["__THREADS__"] = livingThreads temp.alive = false
table.remove(threads, i) if returns[1] == false then
end temp.OnError:Fire(temp, returns[2])
end else
end table.remove(returns,1)
end) temp.OnDeath:Fire(multi.unpack(returns))
end end
GLOBAL["__THREADS__"] = livingThreads
multi.print("Integrated Lanes!") table.remove(threads, i)
multi.integration = {} -- for module creators elseif status == "running" then
multi.integration.GLOBAL = GLOBAL --
multi.integration.THREAD = THREAD elseif status == "waiting" then
require("multi.integration.lanesManager.extensions") --
return { elseif status == "error" then
init = function() -- The thread never really errors, we handle this through our linda object
return GLOBAL, THREAD elseif status == "cancelled" then
end livingThreads[temp.ID] = {false, temp.Name}
} temp.alive = false
temp.OnError:Fire(temp,"thread_cancelled")
GLOBAL["__THREADS__"] = livingThreads
table.remove(threads, i)
elseif status == "killed" then
livingThreads[temp.ID] = {false, temp.Name}
temp.alive = false
temp.OnError:Fire(temp,"thread_killed")
GLOBAL["__THREADS__"] = livingThreads
table.remove(threads, i)
end
end
end
end).OnError(multi.error)
end
multi.print("Integrated Lanes Threading!")
multi.integration = {} -- for module creators
multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD
require("multi.integration.lanesManager.extensions")
return {
init = function()
return GLOBAL, THREAD
end
}
+150 -141
View File
@@ -1,142 +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 function wait() local multi, thread = require("multi"):init()
math.randomseed(os.time()) return multi.hold(function()
__SleepingLinda:receive(.001, "__non_existing_variable") math.randomseed(os.time())
end __SleepingLinda:receive(.001, "__non_existing_variable")
repeat return __GlobalLinda:get(name)
wait() end)
until __GlobalLinda:get(name) end
return __GlobalLinda:get(name)
end function THREAD.getCores()
return THREAD.__CORES
if getOS() == "windows" then end
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
else function THREAD.getConsole()
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) local c = {}
end c.queue = __Console
function c.print(...)
function THREAD.getCores() c.queue:push("Q", table.concat(multi.pack(...), "\t"))
return THREAD.__CORES end
end function c.error(err)
c.queue:push("Q", "Error in <"..THREAD_NAME..":" .. THREAD_ID .. ">: ".. err)
function THREAD.getConsole() multi.error(err)
local c = {} end
c.queue = __Console return c
function c.print(...) end
c.queue:send("Q", {...})
end function THREAD.getThreads()
function c.error(err) return GLOBAL.__THREADS__
c.queue:push("Q",{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__}) end
error(err)
end if os.getOS() == "windows" then
return c THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
end else
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
function THREAD.getThreads() end
return GLOBAL.__THREADS__
end function THREAD.kill() -- trigger the lane destruction
error("Thread was killed!\1")
if os.getOS() == "windows" then end
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
else function THREAD.sync()
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) -- Maybe do something...
end end
function THREAD.kill() -- trigger the lane destruction function THREAD.pushStatus(...)
error("Thread was killed!\1") local args = multi.pack(...)
end __StatusLinda:send(nil,THREAD_ID, args)
end
function THREAD.getName()
return THREAD_NAME _G.THREAD_ID = 0
end
function THREAD.sleep(n)
function THREAD.getID() math.randomseed(os.time())
return THREAD_ID __SleepingLinda:receive(n, "__non_existing_variable")
end end
function THREAD.pushStatus(...) function THREAD.hold(n)
local args = {...} local function wait()
__StatusLinda:send(nil,THREAD_ID, args) math.randomseed(os.time())
end __SleepingLinda:receive(.001, "__non_existing_variable")
end
_G.THREAD_ID = 0 repeat
wait()
function THREAD.sleep(n) until n()
math.randomseed(os.time()) end
__SleepingLinda:receive(n, "__non_existing_variable")
end local GLOBAL = {}
setmetatable(GLOBAL, {
function THREAD.hold(n) __index = function(t, k)
local function wait() return __GlobalLinda:get(k)
math.randomseed(os.time()) end,
__SleepingLinda:receive(.001, "__non_existing_variable") __newindex = function(t, k, v)
end __GlobalLinda:set(k, v)
repeat end
wait() })
until n()
end function THREAD.setENV(env, name)
GLOBAL[name or "__env"] = env
local GLOBAL = {} end
setmetatable(GLOBAL, {
__index = function(t, k) function THREAD.getENV(name)
return __GlobalLinda:get(k) return GLOBAL[name or "__env"]
end, end
__newindex = function(t, k, v)
__GlobalLinda:set(k, v) function THREAD.exposeENV(name)
end name = name or "__env"
}) local env = THREAD.getENV(name)
return GLOBAL, THREAD for i,v in pairs(env) do
end _G[i] = v
end
return {init = function(g,s,st,c) end
return INIT(g,s,st,c)
function THREAD.defer(func)
table.insert(_DEFER, func)
end
return GLOBAL, THREAD
end
return {init = function(g,s,st,c,onexit)
return INIT(g,s,st,c,onexit)
end} end}
+243 -348
View File
@@ -1,349 +1,244 @@
--[[ if not ISTHREAD then
MIT License multi, thread = require("multi").init()
GLOBAL = multi.integration.GLOBAL
Copyright (c) 2022 Ryan Ward THREAD = multi.integration.THREAD
end
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal function multi:newSystemThreadedQueue(name)
in the Software without restriction, including without limitation the rights local name = name or multi.randomString(16)
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 local c = {}
furnished to do so, subject to the following conditions:
c.Name = name
The above copyright notice and this permission notice shall be included in all c.Type = multi.registerType("s_queue")
copies or substantial portions of the Software. c.chan = love.thread.getChannel(name)
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR function c:push(dat)
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, self.chan:push(THREAD.packValue(dat))
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE end
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, function c:pop()
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE return THREAD.unpackValue(self.chan:pop())
SOFTWARE. end
]]
function c:peek()
if not ISTHREAD then return THREAD.unpackValue(self.chan:peek())
multi, thread = require("multi").init() end
GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD function c:init()
else self.chan = love.thread.getChannel(self.Name)
return self
end end
function multi:newSystemThreadedQueue(name) function c:Hold(opt)
local name = name or multi.randomString(16) local multi, thread = require("multi"):init()
local c = {} if opt.peek then
c.Name = name return thread.hold(function()
local fRef = {"func",nil} return self:peek()
function c:init() end)
local q = {} else
q.chan = love.thread.getChannel(self.Name) return thread.hold(function()
function q:push(dat) return self:pop()
if type(dat) == "function" then end)
fRef[2] = THREAD.dump(dat) end
self.chan:push(fRef) end
return
else GLOBAL[name] = c
self.chan:push(dat)
end self:create(c)
end
function q:pop() return c
local dat = self.chan:pop() end
if type(dat)=="table" and dat[1]=="func" then
return THREAD.loadDump(dat[2]) function multi:newSystemThreadedTable(name)
else local name = name or multi.randomString(16)
return dat
end local c = {}
end
function q:peek() c.Name = name
local dat = self.chan:peek() c.Type = multi.registerType("s_table")
if type(dat)=="table" and dat[1]=="func" then c.tab = THREAD.createTable(name)
return THREAD.loadDump(dat[2])
else function c:init()
return dat self.tab = THREAD.createTable(self.Name)
end setmetatable(self,{
end __index = function(t, k)
return q return self.tab[k]
end end,
THREAD.package(name,c) __newindex = function(t,k,v)
return c self.tab[k] = v
end end
function multi:newSystemThreadedTable(name) })
local name = name or multi.randomString(16) return self
local c = {} end
c.Name = name
function c:init() c.__init = c.init
return THREAD.createTable(self.Name)
end function c:Hold(opt)
THREAD.package(name,c) local multi, thread = require("multi"):init()
return c if opt.key then
end return thread.hold(function()
local jqc = 1 return self.tab[opt.key]
function multi:newSystemThreadedJobQueue(n) end)
local c = {} else
c.cores = n or THREAD.getCores() multi.error("Must provide a key to check opt.key = 'key'")
c.registerQueue = {} end
c.funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table") end
c.queue = love.thread.getChannel("__JobQueue_"..jqc.."_queue")
c.queueReturn = love.thread.getChannel("__JobQueue_"..jqc.."_queueReturn") setmetatable(c,{
c.queueAll = love.thread.getChannel("__JobQueue_"..jqc.."_queueAll") __index = function(t, k)
c.id = 0 return c.tab[k]
c.OnJobCompleted = multi:newConnection() end,
local allfunc = 0 __newindex = function(t,k,v)
function c:doToAll(func) c.tab[k] = v
local f = THREAD.dump(func) end
for i = 1, self.cores do })
self.queueAll:push({allfunc,f})
end GLOBAL[name] = c
allfunc = allfunc + 1
end self:create(c)
function c:registerFunction(name,func)
if self.funcs[name] then return c
error("A function by the name "..name.." has already been registered!") end
end
self.funcs[name] = func local jqc = 1
end function multi:newSystemThreadedJobQueue(n)
function c:pushJob(name,...) local c = {}
self.id = self.id + 1
self.queue:push{name,self.id,...} c.cores = n or THREAD.getCores()
return self.id c.registerQueue = {}
end c.Type = multi.registerType("s_jobqueue")
function c:isEmpty() c.funcs = THREAD.createTable("__JobQueue_"..jqc.."_table")
return queueJob:peek()==nil c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue")
end c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn")
local nFunc = 0 c.queueAll = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueAll")
function c:newFunction(name,func,holup) -- This registers with the queue c.id = 0
if type(name)=="function" then c.OnJobCompleted = multi:newConnection()
holup = func
func = name local allfunc = 0
name = "JQ_Function_"..nFunc
end function c:doToAll(func)
nFunc = nFunc + 1 for i = 1, self.cores do
c:registerFunction(name,func) self.queueAll:push({allfunc, func})
return thread:newFunction(function(...) end
local id = c:pushJob(name,...) allfunc = allfunc + 1
local link end
local rets function c:registerFunction(name, func)
link = c.OnJobCompleted(function(jid,...) if self.funcs[name] then
if id==jid then multi.error("A function by the name "..name.." has already been registered!")
rets = {...} end
link:Destroy() self.funcs[name] = func
end end
end) function c:pushJob(name,...)
return thread.hold(function() self.id = self.id + 1
if rets then self.queue:push{name,self.id,...}
return unpack(rets) or multi.NIL return self.id
end end
end) function c:isEmpty()
end,holup),name return queueJob:peek()==nil
end end
thread:newThread("jobManager",function() local nFunc = 0
while true do function c:newFunction(name,func,holup) -- This registers with the queue
thread.yield() if type(name)=="function" then
local dat = c.queueReturn:pop() holup = func
if dat then func = name
c.OnJobCompleted:Fire(unpack(dat)) name = "JQ_Function_"..nFunc
end end
end nFunc = nFunc + 1
end) c:registerFunction(name,func)
for i=1,c.cores do return thread:newFunction(function(...)
multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc) local id = c:pushJob(name,...)
local multi, thread = require("multi"):init() local link
require("love.timer") local rets
local function atomic(channel) link = c.OnJobCompleted(function(jid,...)
return channel:pop() if id==jid then
end rets = multi.pack(...)
local clock = os.clock end
local funcs = THREAD.createStaticTable("__JobQueue_"..jqc.."_table") end)
local queue = love.thread.getChannel("__JobQueue_"..jqc.."_queue") return thread.hold(function()
local queueReturn = love.thread.getChannel("__JobQueue_"..jqc.."_queueReturn") if rets then
local lastProc = clock() return multi.unpack(rets) or multi.NIL
local queueAll = love.thread.getChannel("__JobQueue_"..jqc.."_queueAll") end
local registry = {} end)
setmetatable(_G,{__index = funcs}) end,holup),name
thread:newThread("startUp",function() end
while true do thread:newThread("jobManager",function()
thread.yield() while true do
local all = queueAll:peek() thread.yield()
if all and not registry[all[1]] then local dat = c.queueReturn:pop()
lastProc = os.clock() if dat then
THREAD.loadDump(queueAll:pop()[2])() c.OnJobCompleted:Fire(multi.unpack(dat))
end end
end end
end) end)
thread:newThread("runner",function() for i=1,c.cores do
thread.sleep(.1) multi:newSystemThread("JobQueue_"..jqc.."_worker_"..i,function(jqc)
while true do local multi, thread = require("multi"):init()
thread.yield() require("love.timer")
local all = queueAll:peek() love.timer.sleep(1)
if all and not registry[all[1]] then local clock = os.clock
lastProc = os.clock() local funcs = THREAD.createTable("__JobQueue_"..jqc.."_table")
THREAD.loadDump(queueAll:pop()[2])() local queue = THREAD.waitFor("__JobQueue_"..jqc.."_queue")
end local queueReturn = THREAD.waitFor("__JobQueue_"..jqc.."_queueReturn")
local dat = queue:performAtomic(atomic) local lastProc = clock()
if dat then local queueAll = THREAD.waitFor("__JobQueue_"..jqc.."_queueAll")
lastProc = os.clock() local registry = {}
local name = table.remove(dat,1) _G["__QR"] = queueReturn
local id = table.remove(dat,1) setmetatable(_G,{__index = funcs})
local tab = {funcs[name](unpack(dat))} thread:newThread("startUp",function()
table.insert(tab,1,id) while true do
queueReturn:push(tab) thread.yield()
end local all = queueAll:peek()
end if all and not registry[all[1]] then
end):OnError(function(...) lastProc = os.clock()
error(...) queueAll:pop()[2]()
end) end
thread:newThread("Idler",function() end
while true do end)
thread.yield() thread:newThread("runner",function()
if clock()-lastProc> 2 then thread.sleep(.1)
THREAD.sleep(.05) while true do
else thread.yield()
THREAD.sleep(.001) local all = queueAll:peek()
end if all and not registry[all[1]] then
end lastProc = os.clock()
end) queueAll:pop()[2]()
multi:mainloop() end
end,jqc) local dat = thread.hold(queue)
end if dat then
jqc = jqc + 1 multi:newThread("Test",function()
return c lastProc = os.clock()
end local name = table.remove(dat,1)
local id = table.remove(dat,1)
function multi:newSystemThreadedConnection(name) local tab = {funcs[name](multi.unpack(dat))}
local name = name or multi.randomString(16) table.insert(tab,1,id)
local c = {} --local test = queueReturn.push
c.CONN = 0x00 queueReturn:push(tab)
c.TRIG = 0x01 end)
c.PING = 0x02 end
c.PONG = 0x03 end
end)
local subscribe = multi:newSystemThreadedQueue("SUB_STC_" .. name):init() thread:newThread("Idler",function()
while true do
function c:init() thread.yield()
if clock()-lastProc> 2 then
self.subscribe = THREAD.waitFor("SUB_STC_" .. self.Name):init() THREAD.sleep(.05)
else
function self:Fire(...) THREAD.sleep(.001)
local args = {...} end
if self.CID == THREAD.getID() then -- Host Call end
for _, link in pairs(self.links) do end)
link:push{self.TRIG, args} multi:mainloop()
end end,jqc)
self.proxy_conn:Fire(...) end
else
self.subscribe:push{self.TRIG, args} function c:Hold(opt)
end return thread.hold(self.OnJobCompleted)
end end
local multi, thread = require("multi"):init() jqc = jqc + 1
self.links = {}
self.proxy_conn = multi:newConnection() self:create(c)
local mt = getmetatable(self.proxy_conn)
setmetatable(self, {__index = self.proxy_conn, __call = function(t,func) self.proxy_conn(func) end, __add = mt.__add}) return c
if self.CID == THREAD.getID() then return self end
thread:newThread("STC_CONN_MAN" .. self.Name,function()
local item
local string_self_ref = "LSF_" .. multi.randomString(16)
local link_self_ref = multi:newSystemThreadedQueue():init()
self.subscribe:push{self.CONN, string_self_ref}
while true do
item = thread.hold(function()
return link_self_ref:peek()
end)
if item[1] == self.PING then
link_self_ref:push{self.PONG}
link_self_ref:pop()
elseif item[1] == self.CONN then
if string_self_ref ~= item[2] then
table.insert(self.links, THREAD.waitFor(item[2]):init())
end
link_self_ref:pop()
elseif item[1] == self.TRIG then
self.proxy_conn:Fire(unpack(item[2]))
link_self_ref:pop()
else
-- This shouldn't be the case
end
end
end).OnError(print)
return self
end
local function remove(a, b)
local ai = {}
local r = {}
for k,v in pairs(a) do ai[v]=true end
for k,v in pairs(b) do
if ai[v]==nil then table.insert(r,a[k]) end
end
return r
end
c.CID = THREAD.getID()
c.Name = name
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.
-- Locals will only live in the thread that creates the original object
local ping
local pong = function(link, links)
local res = thread.hold(function()
return link:peek()[1] == c.PONG
end,{sleep=3})
if not res then
for i=1,#links do
if links[i] == link then
table.remove(links,i,link)
break
end
end
else
link:pop()
end
end
ping = thread:newFunction(function(self)
ping:Pause()
multi.ForEach(self.links, function(link) -- Sync new connections
link:push{self.PING}
multi:newThread("pong Thread", pong, link, links)
end)
thread.sleep(3)
ping:Resume()
end,false)
local function fire(...)
for _, link in pairs(c.links) do
link:push {c.TRIG, {...}}
end
end
thread:newThread("STC_SUB_MAN"..name,function()
local item
while true do
thread.yield()
-- We need to check on broken connections
ping(c) -- Should return instantlly and process this in another thread
item = thread.hold(function() -- This will keep things held up until there is something to process
return c.subscribe:pop()
end)
if item[1] == c.CONN then
multi.ForEach(c.links, function(link) -- Sync new connections
THREAD.waitFor(item[2]):init():push{c.CONN, link.Name}
end)
print("Adding link")
c.links[#c.links+1] = THREAD.waitFor(item[2]):init()
elseif item[1] == c.TRIG then
fire(unpack(item[2]))
c.proxy_conn:Fire(unpack(item[2]))
end
end
end).OnError(print)
--- ^^^ This will only exist in the init thread
THREAD.package(name,c)
return c
end end
+137 -116
View File
@@ -1,116 +1,137 @@
--[[ if ISTHREAD then
MIT License error("You cannot require the loveManager from within a thread!")
end
Copyright (c) 2022 Ryan Ward
local ThreadFileData = [[
Permission is hereby granted, free of charge, to any person obtaining a copy ISTHREAD = true
of this software and associated documentation files (the "Software"), to deal args = {...}
in the Software without restriction, including without limitation the rights THREAD_ID = args[1]
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell THREAD_NAME = args[2]
copies of the Software, and to permit persons to whom the Software is GLOBAL, THREAD, DEFER = require("multi.integration.loveManager.threads"):init()
furnished to do so, subject to the following conditions: __FUNC = THREAD.unpackValue(args[3])
ARGS = THREAD.unpackValue(args[4])
The above copyright notice and this permission notice shall be included in all settings = args[5]
copies or substantial portions of the Software. if ARGS == nil then ARGS = {} end
math.randomseed(THREAD_ID)
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR math.random()
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, math.random()
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE math.random()
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER stab = THREAD.createTable(THREAD_NAME .. THREAD_ID)
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, if GLOBAL["__env"] then
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE local env = THREAD.getENV()
SOFTWARE. for i,v in pairs(env) do
]] _G[i] = v
if ISTHREAD then end
error("You cannot require the loveManager from within a thread!") end
end multi, thread = require("multi"):init{error=true, warning=true, print=true, priority=true}
local ThreadFileData = [[ multi.defaultSettings.print = true
ISTHREAD = true require("multi.integration.loveManager.extensions")
THREAD = require("multi.integration.loveManager.threads") -- order is important! require("multi.integration.sharedExtensions")
sThread = THREAD local returns = {pcall(__FUNC, multi.unpack(ARGS))}
__IMPORTS = {...} table.remove(returns,1)
__FUNC__=table.remove(__IMPORTS,1) stab["returns"] = returns
__THREADID__=table.remove(__IMPORTS,1) for i,v in pairs(DEFER) do
__THREADNAME__=table.remove(__IMPORTS,1) pcall(v)
stab = THREAD.createStaticTable(__THREADNAME__) end
GLOBAL = THREAD.getGlobal() ]]
multi, thread = require("multi").init()
print(pcall(require,"multi.integration.loveManager.extensions")) _G.THREAD_NAME = "MAIN_THREAD"
stab["returns"] = {THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))} _G.THREAD_ID = 0
]]
local multi, thread = require("multi"):init() local multi, thread = require("multi"):init()
local THREAD = {} local GLOBAL, THREAD = require("multi.integration.loveManager.threads"):init()
__THREADID__ = 0
__THREADNAME__ = "MainThread" multi.registerType("s_function")
multi.integration={} multi.registerType("s_thread")
multi.integration.love2d={}
local THREAD = require("multi.integration.loveManager.threads") multi.integration = {}
local GLOBAL = THREAD.getGlobal() multi.isMainThread = true
local THREAD_ID = 1 local threads = {}
local OBJECT_ID = 0 local tid = 0
local stf = 0 function multi:newSystemThread(name, func, ...)
multi.InitSystemThreadErrorHandler()
function multi:newSystemThread(name,func,...) local name = name or multi.randomString(16)
local c = {} tid = tid + 1
c.name = name local c = {}
c.ID=THREAD_ID c.Type = multi.STHREAD
c.thread=love.thread.newThread(ThreadFileData) c.Name = name
c.thread:start(THREAD.dump(func),c.ID,c.name,...) c.ID = tid
c.stab = THREAD.createStaticTable(name) c.thread = love.thread.newThread(ThreadFileData)
c.OnDeath = multi:newConnection() c.thread:start(c.ID, c.Name, THREAD.packValue(func), THREAD.packValue({...}), multi.defaultSettings)
c.OnError = multi:newConnection() c.stab = THREAD.createTable(name .. c.ID)
GLOBAL["__THREAD_"..c.ID] = {ID=c.ID, Name=c.name, Thread=c.thread} c.creationTime = os.clock()
GLOBAL["__THREAD_COUNT"] = THREAD_ID c.OnDeath = multi:newConnection()
THREAD_ID=THREAD_ID + 1 c.OnError = multi:newConnection()
function c:getName() c.status_channel = love.thread.getChannel("__status_channel__" .. c.ID)
return c.name
end function c:getName() return c.name end
thread:newThread(function()
if name:find("TempSystemThread") then table.insert(threads, c)
local status_channel = love.thread.getChannel("__"..c.ID.."__MULTI__STATUS_CHANNEL__")
thread.hold(function() c.OnError(multi.error)
-- While the thread is running we might as well do something in the loop
local status = status_channel if self.isActor then
if status:peek()~=nil then self:create(c)
c.statusconnector:Fire(unpack(status:pop())) else
end multi.create(multi, c)
return not c.thread:isRunning() end
end)
else return c
thread.hold(function() end
return not c.thread:isRunning()
end) local started = false
end local console_channel = love.thread.getChannel("__console_channel__")
-- If the thread is not running let's handle that.
local thread_err = c.thread:getError() function THREAD:newFunction(func, holdme)
if thread_err == "Thread Killed!\1" then return thread:newFunctionBase(function(...)
c.OnDeath:Fire("Thread Killed!") return multi:newSystemThread("SystemThreaded Function Handler", func, ...)
elseif thread_err then end, holdme, multi.SFUNCTION)()
c.OnError:Fire(c,thread_err) end
elseif c.stab.returns then
c.OnDeath:Fire(unpack(c.stab.returns)) function love.threaderror(thread, errorstr)
c.stab.returns = nil multi.error("Thread error! " .. errorstr)
end end
end)
return c function multi.InitSystemThreadErrorHandler()
end if started == true then return end
started = true
function THREAD:newFunction(func) thread:newThread("Love System Thread Handler", function()
return thread:newFunctionBase(function(...) while true do
return multi:newSystemThread("TempSystemThread"..THREAD_ID,func,...) thread.yield()
end)() for i = #threads, 1, -1 do
end local th = threads[i]
if th.status_channel:peek() ~= nil then
THREAD.newSystemThread = multi.newSystemThread th.statusconnector:Fire(multi.unpack(th.status_channel:pop()))
end
function love.threaderror(thread, errorstr) local th_err = th.thread:getError()
multi.print("Thread error!\n"..errorstr) if th_err == "Thread Killed!\1" then
end th.OnDeath:Fire("Thread Killed!")
table.remove(threads, i)
multi.integration.GLOBAL = GLOBAL elseif th_err then
multi.integration.THREAD = THREAD th.OnError:Fire(th, th_err)
require("multi.integration.loveManager.extensions") table.remove(threads, i)
multi.print("Integrated Love Threading!") elseif th.stab.returns then
return {init=function() th.OnDeath:Fire(multi.unpack(th.stab.returns))
return GLOBAL,THREAD th.stab.returns = nil
end} table.remove(threads, i)
end
end
end
end)
end
THREAD.newSystemThread = function(...)
multi:newSystemThread(...)
end
multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD
require("multi.integration.loveManager.extensions")
require("multi.integration.sharedExtensions")
multi.print("Integrated Love Threading!")
return {
init = function()
return GLOBAL, THREAD
end
}
+228 -250
View File
@@ -1,250 +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 socket = require("socket") local multi, thread = require("multi"):init()
local multi, thread = require("multi").init()
local threads = {} -- 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 threads.loadDump(d) -- Check if the value has metatable
return loadstring(d:getString()) if type(value) == "userdata" and getmetatable(value) then
end -- Check if the metatable has the __index field
local index = getmetatable(value).__index
function threads.dump(func) if type(index) == "table" then
return love.data.newByteData(string.dump(func)) -- Check if the metatable's __index table contains functions typical of LOVE2D objects
end if index.draw or index.update or index.getWidth or index.getHeight or index.getString or index.getPointer then
return true
local fRef = {"func",nil} end
local function manage(channel, value) end
channel:clear() end
if type(value) == "function" then return false
fRef[2] = THREAD.dump(value) end
channel:push(fRef)
return -- 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
else function tableToFunctionString(t)
channel:push(value) if type(t) == "nil" then return "\1\2:nil:" end
end if type(t) == "function" then return "\1\2:func:"..string.dump(t) end
end if type(t) ~= "table" then return t end
local newtable = {}
local function RandomVariable(length) for k, v in pairs(t) do
local res = {} if type(v) == "function" then
math.randomseed(socket.gettime()*10000) newtable[k] = "\1\2:func:"..string.dump(v)
for i = 1, length do elseif type(v) == "table" then
res[#res+1] = string.char(math.random(97, 122)) newtable[k] = tableToFunctionString(v)
end elseif isLoveObject(v) then
return table.concat(res) newtable[k] = v
end elseif type(v) == "userdata" then
newtable[k] = tostring(v)
local GNAME = "__GLOBAL_" else
local proxy = {} newtable[k] = v
function threads.set(name,val) end
if not proxy[name] then proxy[name] = love.thread.getChannel(GNAME..name) end end
proxy[name]:performAtomic(manage, val) return newtable
end end
function threads.get(name) -- Converts strings with the value "\1\2:func:<function_string>" back to functions
if not proxy[name] then proxy[name] = love.thread.getChannel(GNAME..name) end function functionStringToTable(t)
local dat = proxy[name]:peek() if type(t) == "string" and t:sub(1, 8) == "\1\2:func:" then return loadstring(t:sub(9, -1)) end
if type(dat)=="table" and dat[1]=="func" then if type(t) == "string" and t:sub(1, 7) == "\1\2:nil:" then return nil end
return THREAD.loadDump(dat[2]) if type(t) ~= "table" then return t end
else for k, v in pairs(t) do
return dat if type(v) == "string" then
end if v:sub(1, 8) == "\1\2:func:" then
end t[k] = loadstring(v:sub(9, -1))
else
function threads.waitFor(name) t[k] = v
if thread.isThread() then end
return thread.hold(function() elseif type(v) == "table" then
return threads.get(name) t[k] = functionStringToTable(v)
end) else
end t[k] = v
while threads.get(name)==nil do end
love.timer.sleep(.001) end
end if t.init then
local dat = threads.get(name) t:init()
if type(dat) == "table" and dat.init then end
dat.init = threads.loadDump(dat.init) return t
end end
return dat
end local function packValue(t)
return tableToFunctionString(t)
function threads.package(name,val) end
local init = val.init
val.init=threads.dump(val.init) local function unpackValue(t)
GLOBAL[name]=val return functionStringToTable(t)
val.init=init end
end
local function createTable(n)
function threads.getCores() if not n then
return love.system.getProcessorCount() n = "STAB"..multi.randomString(8)
end end
local __proxy = {}
function threads.kill() local function set(name, val)
error("Thread Killed!\1") local chan = love.thread.getChannel(n .. name)
end if chan:getCount() == 1 then chan:pop() end
__proxy[name] = true
function threads.pushStatus(...) chan:push(packValue(val))
local status_channel = love.thread.getChannel("__"..__THREADID__.."__MULTI__STATUS_CHANNEL__") end
local args = {...} local function get(name)
status_channel:push(__THREADID__, args) return unpackValue(love.thread.getChannel(n .. name):peek())
end -- if type(data) == "table" and data.init then
-- return data:init()
function threads.getThreads() -- else
local t = {} -- return data
for i=1,GLOBAL["__THREAD_COUNT"] do -- end
t[#t+1]=GLOBAL["__THREAD_"..i] end
end return setmetatable({},
return t {
end __index = function(t, k)
return get(k)
function threads.getThread(n) end,
return GLOBAL["__THREAD_"..n] __newindex = function(t, k, v)
end set(k,v)
end
function threads.getName() }
return __THREADNAME__ )
end end
function threads.getID() function INIT()
return __THREADID__ local GLOBAL, THREAD, DEFER = createTable("__GLOBAL__"), {}, {}
end local status_channel, console_channel = love.thread.getChannel("__status_channel__" .. THREAD_ID),
love.thread.getChannel("__console_channel__")
function threads.sleep(n)
love.timer.sleep(n) -- Non portable methods, shouldn't be used unless you know what you are doing
end THREAD.packValue = packValue
THREAD.unpackValue = unpackValue
function threads.getGlobal() THREAD.createTable = createTable
return setmetatable({},
{ function THREAD.set(name, val)
__index = function(t, k) GLOBAL[name] = val
return THREAD.get(k) end
end,
__newindex = function(t, k, v) function THREAD.get(name, val)
THREAD.set(k,v) return GLOBAL[name]
end end
}
) THREAD.waitFor = thread:newFunction(function(name)
end local function wait()
math.randomseed(os.time())
function threads.createTable(n) thread.yield()
local _proxy = {} end
local function set(name,val) repeat
if not _proxy[name] then _proxy[name] = love.thread.getChannel(n..name) end wait()
_proxy[name]:performAtomic(manage, val) until GLOBAL[name] ~= nil
end return GLOBAL[name]
local function get(name) end, true)
if not _proxy[name] then _proxy[name] = love.thread.getChannel(n..name) end
local dat = _proxy[name]:peek() function THREAD.getCores()
if type(dat)=="table" and dat[1]=="func" then return love.system.getProcessorCount()
return THREAD.loadDump(dat[2]) end
else
return dat function THREAD.getConsole()
end local c = {}
end c.queue = console_channel
return setmetatable({}, function c.print(...)
{ c.queue:push(table.concat(multi.pack(...), "\t"))
__index = function(t, k) end
return get(k) function c.error(err)
end, c.queue:push("Error in <"..THREAD_NAME..":" .. THREAD_ID .. ">: ".. err)
__newindex = function(t, k, v) multi.error(err)
set(k,v) end
end return c
} end
)
end function THREAD.getThreads()
--
function threads.getConsole() end
local c = {}
c.queue = love.thread.getChannel("__CONSOLE__") function THREAD.kill() -- trigger the lane destruction
function c.print(...) error("Thread was killed!\1")
c.queue:push{...} end
end
function c.error(err) function THREAD.pushStatus(...)
c.queue:push{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__} status_channel:push(multi.pack(...))
error(err) end
end
return c function THREAD.sleep(n)
end love.timer.sleep(n)
end
if not ISTHREAD then
local clock = os.clock THREAD.hold = thread:newFunction(function(n)
local lastproc = clock() thread.hold(n)
local queue = love.thread.getChannel("__CONSOLE__") end, true)
thread:newThread("consoleManager",function()
while true do function THREAD.setENV(env, name)
thread.yield() GLOBAL[name or "__env"] = env
dat = queue:pop() end
if dat then
lastproc = clock() function THREAD.getENV(name)
print(unpack(dat)) return GLOBAL[name or "__env"]
end end
if clock()-lastproc>2 then
thread.sleep(.1) function THREAD.exposeENV(name)
end name = name or "__env"
end local env = THREAD.getENV(name)
end) for i,v in pairs(env) do
end _G[i] = v
end
function threads.createStaticTable(n) end
local __proxy = {}
local function set(name,val) function THREAD.defer(func)
if __proxy[name] then return end table.insert(DEFER, func)
local chan = love.thread.getChannel(n..name) end
if chan:getCount()>0 then return end
chan:performAtomic(manage, val) function THREAD.sync()
__proxy[name] = val -- Maybe do something...
end end
local function get(name)
if __proxy[name] then return __proxy[name] end return GLOBAL, THREAD, DEFER
local dat = love.thread.getChannel(n..name):peek() end
if type(dat)=="table" and dat[1]=="func" then
__proxy[name] = THREAD.loadDump(dat[2]) return {
return __proxy[name] init = function()
else return INIT()
__proxy[name] = dat end
return __proxy[name] }
end
end
return setmetatable({},
{
__index = function(t, k)
return get(k)
end,
__newindex = function(t, k, v)
set(k,v)
end
}
)
end
function threads.hold(n)
local dat
while not(dat) do
dat = n()
end
end
return threads
+203 -202
View File
@@ -1,203 +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 = {...} 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 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(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 = {}
setmetatable(_G,{__index = funcs}) _G["__QR"] = queueReturn
thread:newThread("startUp",function() setmetatable(_G,{__index = funcs})
while true do thread:newThread("startUp",function()
thread.yield() while true do
local all = queueAll:peek() thread.yield()
if all and not registry[all[1]] then local all = queueAll:peek()
lastProc = os.clock() if all and not registry[all[1]] then
THREAD.loadDump(queueAll:pop()[2])() lastProc = os.clock()
end THREAD.loadDump(queueAll:pop()[2])()
end end
end) end
thread:newThread("runner",function() end)
thread.sleep(.1) thread:newThread("runner",function()
while true do thread.sleep(.1)
thread.yield() while true do
local all = queueAll:peek() thread.yield()
if all and not registry[all[1]] then local all = queueAll:peek()
lastProc = os.clock() if all and not registry[all[1]] then
THREAD.loadDump(queueAll:pop()[2])() lastProc = os.clock()
end THREAD.loadDump(queueAll:pop()[2])()
local dat = queue:performAtomic(atomic) end
if dat then local dat = queue:performAtomic(atomic)
lastProc = os.clock() if dat then
local name = table.remove(dat,1) lastProc = os.clock()
local id = table.remove(dat,1) local name = table.remove(dat,1)
local tab = {funcs[name](unpack(dat))} local id = table.remove(dat,1)
table.insert(tab,1,id) local tab = {funcs[name](multi.unpack(dat))}
queueReturn:push(tab) table.insert(tab,1,id)
end queueReturn:push(tab)
end end
end):OnError(function(...) end
error(...) end):OnError(function(...)
end) error(...)
thread:newThread("Idler",function() end)
while true do thread:newThread("Idler",function()
thread.yield() while true do
if clock()-lastProc> 2 then thread.yield()
THREAD.sleep(.05) if clock()-lastProc> 2 then
else THREAD.sleep(.05)
THREAD.sleep(.001) else
end THREAD.sleep(.001)
end end
end) end
multi:mainloop() end)
end,jqc) multi:mainloop()
end end,jqc)
jqc = jqc + 1 end
return c jqc = jqc + 1
return c
end end
+97 -88
View File
@@ -1,89 +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__)(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"
multi.integration={} _G.THREAD_NAME = "MAIN_THREAD"
multi.integration.lovr2d={} _G.THREAD_ID = 0
local THREAD = require("multi.integration.lovrManager.threads") multi.integration={}
local GLOBAL = THREAD.getGlobal() multi.integration.lovr2d={}
local THREAD_ID = 1 local THREAD = require("multi.integration.lovrManager.threads")
local OBJECT_ID = 0 local GLOBAL = THREAD.getGlobal()
local stf = 0 local THREAD_ID = 1
function THREAD:newFunction(func,holup) local OBJECT_ID = 0
stf = stf + 1 local stf = 0
return function(...) function THREAD:newFunction(func,holup)
local t = multi:newSystemThread("STF"..stf,func,...) stf = stf + 1
return thread:newFunction(function() return function(...)
return thread.hold(function() local t = multi:newSystemThread("STF"..stf,func,...)
if t.stab["returns"] then return thread:newFunction(function()
local dat = t.stab.returns return thread.hold(function()
t.stab.returns = nil if t.stab["returns"] then
return unpack(dat) local dat = t.stab.returns
end t.stab.returns = nil
end) return multi.unpack(dat)
end,holup)() end
end end)
end end,holup)()
function multi:newSystemThread(name,func,...) end
local c = {} end
c.name = name function multi:newSystemThread(name,func,...)
c.ID=THREAD_ID local c = {}
c.thread=lovr.thread.newThread(ThreadFileData) c.name = name
c.thread:start(THREAD.dump(func),c.ID,c.name,...) c.ID=THREAD_ID
c.stab = THREAD.createStaticTable(name) c.thread=lovr.thread.newThread(ThreadFileData)
GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread} c.thread:start(THREAD.dump(func),c.ID,c.name,...)
GLOBAL["__THREAD_COUNT"] = THREAD_ID c.stab = THREAD.createStaticTable(name)
THREAD_ID=THREAD_ID+1 GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread}
return c GLOBAL["__THREAD_COUNT"] = THREAD_ID
end THREAD_ID=THREAD_ID+1
THREAD.newSystemThread = multi.newSystemThread
function lovr.threaderror(thread, errorstr) if self.isActor then
print("Thread error!\n"..errorstr) self:create(c)
end else
multi.integration.GLOBAL = GLOBAL multi.create(multi, c)
multi.integration.THREAD = THREAD end
require("multi.integration.lovrManager.extensions")
print("Integrated lovr Threading!") return c
return {init=function() end
return GLOBAL,THREAD THREAD.newSystemThread = multi.newSystemThread
function lovr.threaderror(thread, errorstr)
multi.print("Thread error!\n"..errorstr)
end
multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD
require("multi.integration.lovrManager.extensions")
multi.print("Integrated lovr Threading!")
return {init=function()
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{...} 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(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()
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 = "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
-141
View File
@@ -1,141 +0,0 @@
--[[
MIT License
Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
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
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
]]
local multi, thread = require("multi"):init()
local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD
local function stripUpValues(func)
local dmp = string.dump(func)
if setfenv then
return loadstring(dmp,"IsolatedThread_PesudoThreading")
else
return load(dmp,"IsolatedThread_PesudoThreading","bt")
end
end
function multi:newSystemThreadedQueue(name)
local c = {}
function c:push(v)
table.insert(self,v)
end
function c:pop()
return table.remove(self,1)
end
function c:peek()
return self[1]
end
function c:init()
return self
end
GLOBAL[name or "_"] = c
return c
end
function multi:newSystemThreadedTable(name)
local c = {}
function c:init()
return self
end
GLOBAL[name or "_"] = c
return c
end
local setfenv = setfenv
if not setfenv then
if not debug then
multi.print("Unable to implement setfenv in lua 5.2+ the debug module is not available!")
else
setfenv = function(f, env)
return load(string.dump(f), nil, nil, env)
end
end
end
function multi:newSystemThreadedJobQueue(n)
local c = {}
c.cores = n or THREAD.getCores()*2
c.OnJobCompleted = multi:newConnection()
local jobs = {}
local ID=1
local jid = 1
local env = {}
setmetatable(env,{
__index = _G
})
local funcs = {}
function c:doToAll(func)
setfenv(func,env)()
return self
end
function c:registerFunction(name,func)
funcs[name] = setfenv(func,env)
return self
end
function c:pushJob(name,...)
table.insert(jobs,{name,jid,{...}})
jid = jid + 1
return jid-1
end
function c:isEmpty()
print(#jobs)
return #jobs == 0
end
local nFunc = 0
function c:newFunction(name,func,holup) -- This registers with the queue
local func = stripUpValues(func)
if type(name)=="function" then
holup = func
func = name
name = "JQ_Function_"..nFunc
end
nFunc = nFunc + 1
c:registerFunction(name,func)
return thread:newFunction(function(...)
local id = c:pushJob(name,...)
local link
local rets
link = c.OnJobCompleted(function(jid,...)
if id==jid then
rets = {...}
link:Destroy()
end
end)
return thread.hold(function()
if rets then
return unpack(rets) or multi.NIL
end
end)
end,holup),name
end
for i=1,c.cores do
thread:newthread("PesudoThreadedJobQueue_"..i,function()
while true do
thread.yield()
if #jobs>0 then
local j = table.remove(jobs,1)
c.OnJobCompleted:Fire(j[2],funcs[j[1]](unpack(j[3])))
else
thread.sleep(.05)
end
end
end)
end
return c
end
+213
View File
@@ -0,0 +1,213 @@
-- Advanced process management. Mutates the multi namespace
local multi, thread = require("multi"):init()
local ok, chronos = pcall(require, "chronos") -- hpc
if not ok then chronos = nil end
-- This is an integration, we cannot directly access locals that are in the main file.
local PList = {
multi.Priority_Core,
multi.Priority_Very_High,
multi.Priority_High,
multi.Priority_Above_Normal,
multi.Priority_Normal,
multi.Priority_Below_Normal,
multi.Priority_Low,
multi.Priority_Very_Low,
multi.Priority_Idle
}
-- Restructered these functions since they rely on local variables from the core library
local mainloop = multi.mainloopRef
local mainloop_p = multi.mainloop_p
local uManagerRef = multi.uManagerRef
local uManagerRefP = multi.uManagerRefP1
local PROFILE_COUNT = 5
-- self:setCurrentProcess() a bit slower than using the local var, but there isn't another option
local priorityManager = multi:newProcessor("Priority Manager", true)
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
local function average(t)
local sum = 0
for _,v in pairs(t) do
sum = sum + v
end
return sum / #t
end
local function getPriority(obj)
local avg = average(obj.__profiling)
if avg < 0.0002 then
return PList[1]
elseif avg < 0.0004 then
return PList[2]
elseif avg < 0.0008 then
return PList[3]
elseif avg < 0.001 then
return PList[4]
elseif avg < 0.0025 then
return PList[5]
elseif avg < 0.005 then
return PList[6]
elseif avg < 0.008 then
return PList[7]
elseif avg < 0.01 then
return PList[8]
else
return PList[9]
end
end
local start, stop
priorityManager.uManager = function(self)
-- proc.run already checks if the processor is active
self:setCurrentProcess()
local Loop=self.Mainloop
local ctask
for _D=#Loop,1,-1 do
ctask = Loop[_D]
ctask:setCurrentTask()
start = chronos.nanotime()
if ctask:Act() then
stop = chronos.nanotime()
if ctask.__profiling then
table.insert(ctask.__profiling, stop - start)
end
if ctask.__profiling and #ctask.__profiling == PROFILE_COUNT then
ctask:setPriority(getPriority(ctask))
ctask:reallocate(ctask.__restoreProc)
ctask.__restoreProc = nil
ctask.__profiling = nil
end
end
self:setCurrentProcess()
end
end
local function processHook(obj, proc)
if obj.Type == multi.registerType("process", "processes") or not(obj.IsAnActor) then return end
obj.__restoreProc = proc
obj.__profiling = {}
obj:reallocate(priorityManager)
end
local function init()
local registry = {}
multi.priorityScheme = {
RoundRobin = "RoundRobin",
PriorityBased = "PriorityBased",
TimeBased = "TimeBased"
}
function multi:setProfilerCount(count)
PROFILE_COUNT = count
end
function multi:recalibrate()
if self.__processConn then
local items = self.Mainloop
for i,v in pairs(items) do
processHook(v, self)
end
else
multi.error("Cannot recalibrate the priority if not using Time based mangement!")
end
end
function multi:isRegistredScheme(scheme)
return registry[name] ~= nil
end
function multi:getRegisteredScheme(scheme)
return registry[name].mainloop, registry[name].umanager, registry[name].condition
end
local empty_func = function() return true end
function multi:registerScheme(name,options)
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!")
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!")
end
local condition = options.condition or empty_func
if registry[name] and not registry[name].static then
multi.warn("A scheme named: \"" .. name .. "\" has already been registred, overriting!")
else
multi.error("A scheme named: \"" .. name .. "\" has already been registred!")
end
registry[name] = {
mainloop = mainloop,
umanager = umanger,
condition = condition,
static = options.static or false
}
multi.priorityScheme[name] = name
return true
end
function multi:setPriorityScheme(scheme)
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!")
end
if scheme == multi.priorityScheme.RoundRobin then
if self.__processConn then self.OnObjectCreated:Unconnect(self.__processConn) self.__processConn = nil end
self.mainloop = mainloop
self.uManager = uManagerRef
elseif scheme == multi.priorityScheme.PriorityBased then
if self.__processConn then self.OnObjectCreated:Unconnect(self.__processConn) self.__processConn = nil end
self.mainloop = mainloop_p
self.uManager = uManagerRefP
elseif scheme == multi.priorityScheme.TimeBased then
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
self.__processConn = self.OnObjectCreated(processHook)
self.mainloop = mainloop_p
self.uManager = uManagerRefP
elseif self:isRegistredScheme(scheme) then
local mainloop, umanager, condition = self:getRegisteredScheme(scheme)
if condition() then
self.mainloop = mainloop
self.uManager = umanager
end
else
self.error("Invalid priority scheme selected!")
end
end
end
local function init_chronos()
-- Let's implement a higher precision clock
multi.setClock(chronos.nanotime) -- This is also in .000 format. So a plug and play works.
thread:newThread("System Priority Manager", function()
while true do
thread.yield()
priorityManager.run()
end
end)
end
if chronos then
init_chronos()
else
multi.warn("In order to have time based priority management, you need to install the chronos library!")
end
init()
+221
View File
@@ -0,0 +1,221 @@
--[[
MIT License
Copyright (c) 2022 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
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
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
]]
local multi, thread = require("multi"):init()
local GLOBAL, THREAD = multi.integration.GLOBAL, multi.integration.THREAD
local function stripUpValues(func)
local dmp = string.dump(func)
if setfenv then
return loadstring(dmp,"IsolatedThread_PesudoThreading")
else
return load(dmp,"IsolatedThread_PesudoThreading","bt")
end
end
function multi:newSystemThreadedQueue(name)
local c = {}
c.data = {}
c.Type = multi.registerType("s_queue")
function c:push(v)
table.insert(self.data,v)
end
function c:pop()
return table.remove(self.data,1)
end
function c:peek()
return self.data[1]
end
function c:init()
return self
end
function c:Hold(opt)
if opt.peek then
return thread.hold(function()
return self:peek()
end)
else
return thread.hold(function()
return self:pop()
end)
end
end
GLOBAL[name or "_"] = c
return c
end
function multi:newSystemThreadedTable(name)
local c = {}
c.Type = multi.registerType("s_table")
function c:init()
return self
end
function c:Hold(opt)
if opt.key then
return thread.hold(function()
return self.tab[opt.key]
end)
else
multi.error("Must provide a key to check opt.key = 'key'")
end
end
GLOBAL[name or "_"] = c
return c
end
local setfenv = multi.isolateFunction
local jqc = 1
function multi:newSystemThreadedJobQueue(n)
local c = {}
c.cores = n or THREAD.getCores()
c.registerQueue = {}
c.Type = multi.registerType("s_jobqueue")
c.funcs = multi:newSystemThreadedTable("__JobQueue_"..jqc.."_table")
c.queue = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queue")
c.queueReturn = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueReturn")
c.queueAll = multi:newSystemThreadedQueue("__JobQueue_"..jqc.."_queueAll")
c.id = 0
c.OnJobCompleted = multi:newConnection()
local allfunc = 0
function c:doToAll(func)
for i = 1, self.cores do
self.queueAll:push({allfunc, func})
end
allfunc = allfunc + 1
end
function c:registerFunction(name, func)
if self.funcs[name] then
multi.error("A function by the name "..name.." has already been registered!")
end
self.funcs[name] = func
end
function c:pushJob(name,...)
self.id = self.id + 1
self.queue:push{name,self.id,...}
return self.id
end
function c:isEmpty()
return queueJob:peek()==nil
end
local nFunc = 0
function c:newFunction(name,func,holup) -- This registers with the queue
if type(name)=="function" then
holup = func
func = name
name = "JQ_Function_"..nFunc
end
nFunc = nFunc + 1
c:registerFunction(name,func)
return thread:newFunction(function(...)
local id = c:pushJob(name,...)
local link
local rets
link = c.OnJobCompleted(function(jid,...)
if id==jid then
rets = multi.pack(...)
end
end)
return thread.hold(function()
if rets then
return multi.unpack(rets) or multi.NIL
end
end)
end,holup),name
end
thread:newThread("jobManager",function()
while true do
thread.yield()
local dat = c.queueReturn:pop()
if dat then
c.OnJobCompleted:Fire(multi.unpack(dat))
end
end
end)
for i=1,c.cores do
multi:newSystemThread("STJQ_"..multi.randomString(8),function(jqc)
local GLOBAL, THREAD = require("multi.integration.pseudoManager"):init()
local multi, thread = require("multi"):init()
local clock = os.clock
local funcs = THREAD.waitFor("__JobQueue_"..jqc.."_table")
local queue = THREAD.waitFor("__JobQueue_"..jqc.."_queue")
local queueReturn = THREAD.waitFor("__JobQueue_"..jqc.."_queueReturn")
local queueAll = THREAD.waitFor("__JobQueue_"..jqc.."_queueAll")
local registry = {}
_G["__QR"] = queueReturn
setmetatable(_G,{__index = funcs})
thread:newThread("startUp",function()
while true do
thread.yield()
local all = queueAll:peek()
if all and not registry[all[1]] then
queueAll:pop()[2]()
end
end
end)
thread:newThread("runner",function()
thread.sleep(.1)
while true do
thread.yield()
local all = queueAll:peek()
if all and not registry[all[1]] then
queueAll:pop()[2]()
end
local dat = thread.hold(queue)
if dat then
multi:newThread("JobSubRunner",function()
local name = table.remove(dat,1)
local id = table.remove(dat,1)
local tab = {multi.isolateFunction(funcs[name],_G)(multi.unpack(dat))}
table.insert(tab,1,id)
queueReturn:push(tab)
end)
end
end
end)
multi:mainloop()
end, jqc)
end
function c:Hold(opt)
return thread.hold(self.OnJobCompleted)
end
jqc = jqc + 1
self:create(c)
return c
end
function multi:newSystemThreadedConnection(name)
local conn = multi:newConnection()
conn.init = function(self) return self end
GLOBAL[name or "_"] = conn
return conn
end
require("multi.integration.sharedExtensions")
@@ -1,101 +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()
if multi.integration then if multi.integration then
return { return {
init = function() init = function()
return multi.integration.GLOBAL, multi.integration.THREAD return multi.integration.GLOBAL, multi.integration.THREAD
end end
} }
end end
multi.isMainThread = true
local GLOBAL, THREAD = require("multi.integration.pesudoManager.threads").init(thread) local activator = require("multi.integration.pseudoManager.threads")
local GLOBAL, THREAD = activator.init(thread)
function multi:canSystemThread() -- We are emulating system threading
return true _G.THREAD_NAME = "MAIN_THREAD"
end _G.THREAD_ID = 0
function multi:getPlatform() function multi:canSystemThread() -- We are emulating system threading
return "pesudo" return true
end end
local function split(str) function multi:getPlatform()
local tab = {} return "pesudo"
for word in string.gmatch(str, '([^,]+)') do end
table.insert(tab,word)
end local function split(str)
return tab local tab = {}
end for word in string.gmatch(str, '([^,]+)') do
table.insert(tab,word)
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,unpack,xpcall,math,coroutine,string,table]] end
tab = split(tab) return tab
end
local id = 0
function multi:newSystemThread(name,func,...) 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]]
GLOBAL["$THREAD_NAME"] = name tab = split(tab)
GLOBAL["$__THREADNAME__"] = name
GLOBAL["$THREAD_ID"] = id local id = 0
GLOBAL["$thread"] = thread
local env = { function multi:newSystemThread(name, func, ...)
GLOBAL = GLOBAL, local env
THREAD = THREAD, env = {
THREAD_NAME = name, GLOBAL = GLOBAL,
__THREADNAME__ = name, THREAD = THREAD,
THREAD_ID = id, THREAD_NAME = tostring(name),
thread = thread __THREADNAME__ = tostring(name),
} THREAD_ID = id,
thread = thread,
for i = 1,#tab do multi = multi,
env[tab[i]] = _G[tab[i]] }
end
for i, v in pairs(_G) do
local th = thread:newISOThread(name,func,env,...) if not(env[i]) and not(i == "_G") and not(i == "local_global") then
env[i] = v
id = id + 1 else
multi.warn("skipping:",i)
return th end
end end
THREAD.newSystemThread = multi.newSystemThread if GLOBAL["__env"] then
-- System threads as implemented here cannot share memory, but use a message passing system. for i,v in pairs(GLOBAL["__env"]) do
-- 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 env[i] = v
end
function THREAD:newFunction(func,holdme) end
return thread:newFunctionBase(function(...)
return multi:newSystemThread("TempSystemThread",func,...) env._G = env
end,holdme)()
end local GLOBAL, THREAD = activator.init(thread, env)
multi.print("Integrated Pesudo Threading!") local th = pseudoProcessor:newISOThread(name, func, env, ...)
multi.integration = {} -- for module creators th.Type = multi.registerType("s_thread", "pseudoThreads")
multi.integration.GLOBAL = GLOBAL th.OnError(multi.error)
multi.integration.THREAD = THREAD
require("multi.integration.pesudoManager.extensions") id = id + 1
return {
init = function() return th
return GLOBAL, THREAD end
end
} THREAD.newSystemThread = multi.newSystemThread
-- 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(...)
return multi:newSystemThread("TempSystemThread",func,...)
end, holdme, multi.registerType("s_function", "pseudoFunctions"))()
end
multi.print("Integrated Pesudo Threading!")
multi.integration = {} -- for module creators
multi.integration.GLOBAL = GLOBAL
multi.integration.THREAD = THREAD
require("multi.integration.pseudoManager.extensions")
require("multi.integration.sharedExtensions")
return {
init = function()
return GLOBAL, THREAD
end
}
@@ -1,110 +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_High = 2 THREAD.Priority_Core = 3
THREAD.Priority_Above_Normal = 1 THREAD.Priority_High = 2
THREAD.Priority_Normal = 0 THREAD.Priority_Above_Normal = 1
THREAD.Priority_Below_Normal = -1 THREAD.Priority_Normal = 0
THREAD.Priority_Low = -2 THREAD.Priority_Below_Normal = -1
THREAD.Priority_Idle = -3 THREAD.Priority_Low = -2
THREAD.Priority_Idle = -3
function THREAD.set(name, val)
GLOBAL[name] = val function THREAD.set(name, val)
end GLOBAL[name] = val
end
function THREAD.get(name)
return GLOBAL[name] function THREAD.get(name)
end return GLOBAL[name]
end
function THREAD.waitFor(name)
return thread.hold(function() return GLOBAL[name] end) function THREAD.waitFor(name)
end return thread.hold(function() return GLOBAL[name] end)
end
if getOS() == "windows" then
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) if getOS() == "windows" then
else THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) else
end THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
end
function THREAD.getCores()
return THREAD.__CORES function THREAD.getCores()
end return THREAD.__CORES
end
function THREAD.getConsole()
local c = {} function THREAD.getConsole()
function c.print(...) local c = {}
print(...) function c.print(...)
end print(...)
function c.error(err) end
error("ERROR in <"..GLOBAL["$__THREADNAME__"]..">: "..err) function c.error(err)
end error("ERROR in <"..GLOBAL["$__THREADNAME__"]..">: "..err)
return c end
end return c
end
function THREAD.getThreads()
return {}--GLOBAL.__THREADS__ function THREAD.getThreads()
end return {}--GLOBAL.__THREADS__
end
THREAD.pushStatus = thread.pushStatus
THREAD.pushStatus = thread.pushStatus
if os.getOS() == "windows" then
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS")) function THREAD.kill()
else error("Thread was killed!")
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n")) end
end
THREAD.sleep = thread.sleep
function THREAD.kill()
error("Thread was killed!") THREAD.hold = thread.hold
end
THREAD.defer = thread.defer
function THREAD.getName()
return GLOBAL["$THREAD_NAME"] function THREAD.setENV(env, name)
end name = name or "__env"
GLOBAL[name] = env
function THREAD.getID() end
return GLOBAL["$THREAD_ID"]
end function THREAD.getENV(name)
name = name or "__env"
THREAD.sleep = thread.sleep return GLOBAL[name]
end
THREAD.hold = thread.hold
function THREAD.exposeENV(name)
return GLOBAL, THREAD name = name or "__env"
end local env = THREAD.getENV(name)
for i,v in pairs(env) do
return {init = function(thread) -- This may need to be reworked!
return INIT(thread) local_global[i] = v
end
end
function THREAD.sync()
thread.sleep(.5)
end
return GLOBAL, THREAD
end
return {init = function(thread, global)
return INIT(thread, global)
end} end}
+336
View File
@@ -0,0 +1,336 @@
--[[ todo finish the targeted job!
MIT License
Copyright (c) 2023 Ryan Ward
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
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
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
SOFTWARE.
]]
local multi, thread = require("multi"):init()
-- 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
function multi:chop(obj)
if not _G["UIDS"] then
_G["UIDS"] = {}
end
local multi, thread = require("multi"):init()
local list = {[0] = multi.randomString(12)}
_G[list[0]] = obj
for i,v in pairs(obj) do
if type(v) == "function" or type(v) == "table" and v.Type == multi.registerType("s_function") then
table.insert(list, i)
elseif type(v) == "table" and v.Type == multi.registerType("connector", "connections") then
table.insert(list, {i, multi:newProxy(multi:chop(v)):init()})
end
end
return list
end
function multi:newProxy(list)
local c = {}
c.name = multi.randomString(12)
c.is_init = false
local multi, thread = nil, nil
function c:init()
local multi, thread = nil, nil
local function copy(obj)
if type(obj) ~= 'table' then return obj end
local res = {}
for k, v in pairs(obj) do res[copy(k)] = copy(v) end
return res
end
if not(self.is_init) then
THREAD.sync()
self.is_init = true
local multi, thread = require("multi"):init()
self.proxy_link = "PL" .. multi.randomString(12)
if multi.integration then
GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD
end
GLOBAL[self.proxy_link] = self
local function check()
return self.send:pop()
end
self.send = multi:newSystemThreadedQueue(self.name.."_S"):init()
self.recv = multi:newSystemThreadedQueue(self.name.."_R"):init()
self.funcs = list
self._funcs = copy(list)
self.Type = multi.registerType("proxy", "proxies")
self.TID = THREAD_ID
thread:newThread("Proxy_Handler_" .. multi.randomString(4), function()
while true do
local data = thread.hold(check)
if data then
-- Let's not hold the main threadloop
thread:newThread("Temp_Thread", function()
local func = table.remove(data, 1)
local sref = table.remove(data, 1)
local ret
if sref then
ret = {_G[list[0]][func](_G[list[0]], multi.unpack(data))}
else
ret = {_G[list[0]][func](multi.unpack(data))}
end
for i = 1,#ret do
if type(ret[i]) == "table" and ret[i].Type ~= nil and ret[i].Type ~= multi.registerType("proxy", "proxies") then
ret[i] = "\1PARENT_REF"
end
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!
end
if ret[i] == _G[list[0]] then
-- We cannot return itself, that return can contain bad values.
ret[i] = "\1SELF_REF"
end
end
table.insert(ret, 1, func)
self.recv:push(ret)
end)
end
end
end)
return self
else
THREAD.sync()
if not self.funcs then return self end
local function copy(obj)
if type(obj) ~= 'table' then return obj end
local res = {}
for k, v in pairs(obj) do res[copy(k)] = copy(v) end
return res
end
local multi, thread = require("multi"):init()
local me = self
local funcs = copy(self.funcs)
if multi.integration then
GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD
end
self.send = THREAD.waitFor(self.name.."_S"):init()
self.recv = THREAD.waitFor(self.name.."_R"):init()
self.Type = multi.registerType("proxy", "proxies")
for _,v in pairs(funcs) do
if type(v) == "table" then
-- We have a connection
v[2]:init(proc_name)
self[v[1]] = v[2]
v[2].Parent = self
setmetatable(v[2],getmetatable(multi:newConnection()))
else
self[v] = thread:newFunction(function(self,...)
if self == me then
me.send:push({v, true, ...})
else
me.send:push({v, false, ...})
end
return thread.hold(function()
local data = me.recv:peek()
if data and data[1] == v then
me.recv:pop()
table.remove(data, 1)
for i=1,#data do
if data[i] == "\1SELF_REF" then
data[i] = me
elseif data[i] == "\1PARENT_REF" then
data[i] = me.Parent
end
end
return multi.unpack(data)
end
end)
end, true)
end
end
return self
end
end
function c:getTransferable()
local cp = {}
local multi, thread = require("multi"):init()
local function copy(obj)
if type(obj) ~= 'table' then return obj end
local res = {}
for k, v in pairs(obj) do res[copy(k)] = copy(v) end
return res
end
cp.is_init = true
cp.proxy_link = self.proxy_link
cp.name = self.name
cp.funcs = copy(self._funcs)
cp.init = function(self)
local multi, thread = require("multi"):init()
if multi.integration then
GLOBAL = multi.integration.GLOBAL
THREAD = multi.integration.THREAD
end
local proxy = THREAD.waitFor(self.proxy_link)
proxy.funcs = self.funcs
return proxy:init()
end
return cp
end
self:create(c)
return c
end
local targets = {}
local references = {}
local jid = -1
function multi:newSystemThreadedProcessor(cores)
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 c = {}
setmetatable(c,{__index = multi})
c.Type = multi.registerType("s_process", "s_processes")
c.threads = {}
c.cores = cores or 8
c.Name = name
c.Mainloop = {}
c.__count = 0
c.processors = {}
c.proc_list = {}
c.OnObjectCreated = multi:newConnection()
c.parent = self
c.jobqueue = multi:newSystemThreadedJobQueue(c.cores)
function c:pushJob(ID, name, ...)
local tq = THREAD.waitFor(self.Name .. "_target_tq_" .. ID):init()
tq:push{name, jid, multi.pack(...)}
jid = jid - 1
return jid + 1
end
c.jobqueue:registerFunction("packObj",function(obj)
local multi, thread = require("multi"):init()
local list = multi:chop(obj)
obj.__link_name = list[0]
local proxy = multi:newProxy(list):init()
return proxy
end)
c.spawnThread = c.jobqueue:newFunction("__spawnThread__", function(name, func, ...)
local multi, thread = require("multi"):init()
local obj = thread:newThread(name, func, ...)
return packObj(obj)
end, true)
c.spawnTask = c.jobqueue:newFunction("__spawnTask__", function(obj, func, ...)
local multi, thread = require("multi"):init()
local obj = multi[obj](multi, func, ...)
return packObj(obj)
end, true)
local implement = {
"newLoop",
"newTLoop",
"newUpdater",
"newEvent",
"newAlarm",
"newStep",
"newTStep",
"newService"
}
for _, method in pairs(implement) do
c[method] = thread:newFunction(function(self, ...)
proxy = self.spawnTask(method, ...)
proxy:init()
references[proxy] = self
return proxy
end, true)
end
function c:newThread(name, func, ...)
proxy = self.spawnThread(name, func, ...):init(self.Name)
references[proxy] = self
table.insert(self.threads, proxy)
return proxy
end
function c:newFunction(func, holdme)
return self.jobqueue:newFunction(func, holdme)
end
function c:newSharedTable(name)
if not name then multi.error("You must provide a name when creating a table!") end
local tbl_name = "TABLE_"..multi.randomString(8)
self.jobqueue:doToAll(function(tbl_name, interaction)
_G[interaction] = THREAD.waitFor(tbl_name):init()
end, tbl_name, name)
return multi:newSystemThreadedTable(tbl_name):init()
end
function c:getHandler()
return function() end -- return empty function
end
function c:getThreads()
return self.threads
end
function c:getFullName()
return self.parent:getFullName() .. "." .. c.Name
end
function c:getName()
return self.Name
end
function c.run()
return self
end
function c.isActive()
return true
end
function c.Start()
return self
end
function c.Stop()
return self
end
function c:Destroy()
return false
end
return c
end
+1
View File
@@ -0,0 +1 @@
-- Allows the creation of states
+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
View File
@@ -0,0 +1,20 @@
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.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 = true -- Enable the system module (boolean)
-- t.modules.timer = true -- Enable the timer module (boolean)
-- t.modules.window = false -- Enable the window module (boolean)
-- t.modules.thread = true -- Enable the thread module (boolean)
end
+75
View File
@@ -0,0 +1,75 @@
package.path = "../?/init.lua;../?.lua;"..package.path
local multi, thread = require("multi"):init{print=true, warning = true, error=true}
local utils = require("multi.integration.loveManager.utils")
local people = {1,2,3}
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. '('..type(v):sub(1,1)..'),'
end
return s .. '} '
else
return tostring(o)
end
end
local fpeople = utils.pack(people)
print("Pack:", dump(fpeople))
local people = utils.unpack(fpeople)
print("Unpack:", dump(people))
print(type(people[3]))
-- GLOBAL, THREAD = require("multi.integration.loveManager"):init()
-- local queue = multi:newSystemThreadedQueue("TestQueue")
-- local tab = multi:newSystemThreadedTable("TestTable")
-- local test = multi:newSystemThread("Test",function()
-- local queue = THREAD.waitFor("TestQueue")
-- local tab = THREAD.waitFor("TestTable")
-- print("THREAD_ID:",THREAD_ID)
-- queue:push("Did it work?")
-- tab["Test"] = true
-- return 1,2,3
-- end)
-- multi:newThread("QueueTest", function()
-- print(thread.hold(queue))
-- print(thread.hold(tab, {key="Test"}))
-- print("Done!")
-- end)
-- local jq = multi:newSystemThreadedJobQueue(n)
-- jq:registerFunction("test2",function()
-- print("This works!")
-- end)
-- jq:registerFunction("test",function(a, b, c)
-- print(a, b+c)
-- test2()
-- return a+b+c
-- end)
-- print("Job:",jq:pushJob("test",1,2,3))
-- print("Job:",jq:pushJob("test",2,3,4))
-- print("Job:",jq:pushJob("test",5,6,7))
-- jq.OnJobCompleted(function(...)
-- print("Job Completed!", ...)
-- end)
-- function love.draw()
-- --
-- end
-- function love.update()
-- multi:uManager()
-- end
+1
View File
@@ -0,0 +1 @@
../
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",
} }
} }
+39
View File
@@ -0,0 +1,39 @@
package = "multi"
version = "15.3-1"
source = {
url = "git://github.com/rayaman/multi.git",
tag = "15.3.1",
}
description = {
summary = "Lua Multi tasking library",
detailed = [[
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
Check github for documentation.
]],
homepage = "https://github.com/rayaman/multi",
license = "MIT"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pesudoManager"] = "integration/pesudoManager/init.lua",
["multi.integration.pesudoManager.extensions"] = "integration/pesudoManager/extensions.lua",
["multi.integration.pesudoManager.threads"] = "integration/pesudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua",
}
}
+42
View File
@@ -0,0 +1,42 @@
package = "multi"
version = "16.0-0"
source = {
url = "git://github.com/rayaman/multi.git",
tag = "v16.0.0",
}
description = {
summary = "Lua Multi tasking library",
detailed = [[
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
Check github for documentation.
]],
homepage = "https://github.com/rayaman/multi",
license = "MIT"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua",
}
}
+42
View File
@@ -0,0 +1,42 @@
package = "multi"
version = "16.0-1"
source = {
url = "git://github.com/rayaman/multi.git",
tag = "v16.0.1",
}
description = {
summary = "Lua Multi tasking library",
detailed = [[
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
Check github for documentation.
]],
homepage = "https://github.com/rayaman/multi",
license = "MIT"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua",
}
}
+42
View File
@@ -0,0 +1,42 @@
package = "multi"
version = "16.1-0"
source = {
url = "git://github.com/rayaman/multi.git",
tag = "v16.1.0",
}
description = {
summary = "Lua Multi tasking library",
detailed = [[
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
Check github for documentation.
]],
homepage = "https://github.com/rayaman/multi",
license = "MIT"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua",
}
}
+42
View File
@@ -0,0 +1,42 @@
package = "multi"
version = "16.2-0"
source = {
url = "git://github.com/rayaman/multi.git",
tag = "v16.2.0",
}
description = {
summary = "Lua Multi tasking library",
detailed = [[
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
Check github for documentation.
]],
homepage = "https://github.com/rayaman/multi",
license = "MIT"
}
dependencies = {
"lua >= 5.1"
}
build = {
type = "builtin",
modules = {
["multi"] = "init.lua",
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
["multi.integration.threading"] = "integration/threading.lua",
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
--["multi.integration.networkManager"] = "integration/networkManager.lua",
}
}
+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
+1095
View File
File diff suppressed because it is too large Load Diff
-185
View File
@@ -1,185 +0,0 @@
if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
package.path="multi/?.lua;multi/?/init.lua;multi/?.lua;multi/?/?/init.lua;"..package.path
require("lldebugger").start()
else
package.path = "../?/init.lua;../?.lua;"..package.path
end
--[[
This file runs all tests.
Format:
Expected:
...
...
...
Actual:
...
...
...
Each test that is ran should have a 5 second pause after the test is complete
The expected and actual should "match" (Might be impossible when playing with threads)
This will be pushed directly to the master as tests start existing.
]]
local multi, thread = require("multi"):init{print=true}--{priority=true}
local good = false
local proc = multi:newProcessor("Test",true)
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
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
print("Alarms: Ok")
print("Events: Ok")
if tsteps == 10 then print("TSteps: Ok") else print("TSteps: Bad!") end
if steps == 10 then print("Steps: Ok") else print("Steps: Bad!") end
if loops > 100 then print("Loops: Ok") else print("Loops: Bad!") end
if tloops > 10 then print("TLoops: Ok") else print("TLoops: Bad!") end
if updaters > 100 then print("Updaters: Ok") else print("Updaters: Bad!") end
end)
thread.hold(event.OnEvent)
print("Starting Connection and Thread tests!")
func = thread:newFunction(function(count)
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(...)
print("Func 1:",...)
end)
ret2.OnError(function(...)
print("Func 2:",...)
end)
ret3.OnError(function(...)
print("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(...)
print("Done 1",...)
end)
ret2.OnReturn(function(...)
print("Done 2",...)
end)
ret3.OnReturn(function(...)
print("Done 3",...)
end)
local err, timeout = thread.hold(ret.OnReturn * ret2.OnReturn * ret3.OnReturn)
if s1 == 100 and s2 == 100 and s3 == 100 then
print("Threads: All tests Ok")
else
if s1>0 and s2>0 and s3 > 0 then
print("Thread OnStatus: Ok")
else
print("Threads OnStatus or thread.hold(conn) Error!")
end
if timeout then
print("Connection Error!")
else
print("Connection Test 1: Ok")
end
print("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
print("Connection Test 2: Ok")
else
print("Connection Test 2: Error")
end
c3 = false
c4 = false
d:Destroy()
conn3:Fire()
if c3 and not(c4) then
print("Connection Test 3: Ok")
else
print("Connection Test 3: Error removing connection")
end
os.exit() -- End of tests
end)
print(runTest().OnError(function(...)
print("Error: Something went wrong with the test!")
print(...)
os.exit(1)
end))
print("Pumping proc")
while true do
proc.run()
end
-133
View File
@@ -1,133 +0,0 @@
package.path = "../?/init.lua;../?.lua;"..package.path
multi, thread = require("multi"):init{print=true,findopt=true}
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
multi:getOptimizationConnection()(function(msg)
print(msg)
end)
local conn1, conn2, conn3 = multi:newConnection(), multi:newConnection():fastMode(), multi:newConnection()
local link = conn1(function()
print("Conn1, first")
end)
local link2 = conn1(function()
print("Conn1, second")
end)
local link3 = conn1(function()
print("Conn1, third")
end)
local link4 = conn2(function()
print("Conn2, first")
end)
local link5 = conn2(function()
print("Conn2, second")
end)
local link6 = conn2(function()
print("Conn2, third")
end)
print("All conns\n-------------")
conn1:Fire()
conn2:Fire()
conn1:Unconnect(link3)
conn2:Unconnect(link6)
print("All conns Edit\n---------------------")
conn1:Fire()
conn2:Fire()
-- thread:newThread(function()
-- print("Awaiting status")
-- thread.hold(conn1 + (conn2 * conn3))
-- print("Conn or Conn2 and Conn3")
-- end)
-- multi:newAlarm(1):OnRing(function()
-- print("Conn")
-- conn1:Fire()
-- end)
-- multi:newAlarm(2):OnRing(function()
-- print("Conn2")
-- conn2:Fire()
-- end)
-- multi:newAlarm(3):OnRing(function()
-- print("Conn3")
-- conn3:Fire()
-- end)
-- local conn = multi:newSystemThreadedConnection("conn"):init()
-- multi:newSystemThread("Thread_Test_1", function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print(THREAD:getName().." was triggered!",a,b,c)
-- end)
-- multi:mainloop()
-- end)
-- multi:newSystemThread("Thread_Test_2", function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print(THREAD:getName().." was triggered!",a,b,c)
-- end)
-- multi:newAlarm(2):OnRing(function()
-- console.print("Fire 2!!!")
-- conn:Fire(4,5,6)
-- THREAD.kill()
-- end)
-- multi:mainloop()
-- end)
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print("Mainloop conn got triggered!",a,b,c)
-- end)
-- alarm = multi:newAlarm(1)
-- alarm:OnRing(function()
-- console.print("Fire 1!!!")
-- conn:Fire(1,2,3)
-- end)
-- alarm = multi:newAlarm(3):OnRing(function()
-- multi:newSystemThread("Thread_Test_3",function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local console = THREAD.getConsole()
-- conn(function(a,b,c)
-- console.print(THREAD:getName().." was triggered!",a,b,c)
-- end)
-- multi:newAlarm(4):OnRing(function()
-- console.print("Fire 3!!!")
-- conn:Fire(7,8,9)
-- end)
-- multi:mainloop()
-- end)
-- end)
-- multi:newSystemThread("Thread_Test_4",function()
-- local multi, thread = require("multi"):init()
-- local conn = GLOBAL["conn"]:init()
-- local conn2 = multi:newConnection()
-- local console = THREAD.getConsole()
-- multi:newAlarm(2):OnRing(function()
-- conn2:Fire()
-- end)
-- multi:newThread(function()
-- console.print("Conn Test!")
-- thread.hold(conn + conn2)
-- console.print("It held!")
-- end)
-- multi:mainloop()
-- end)
-- multi:mainloop()
+246
View File
@@ -0,0 +1,246 @@
package.path = "../?/init.lua;../?.lua;../init.lua;../?.lua;" .. package.path
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}
proc = multi:newProcessor("Thread Test",true)
local LANES, LOVE, PSEUDO = 1, 2, 3
local env, we_good
if love then
GLOBAL, THREAD = require("multi.integration.loveManager"):init()
env = LOVE
elseif arg[1] == "l" then
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
env = LANES
elseif arg[1] == "p" then
GLOBAL, THREAD = require("multi.integration.pseudoManager"):init()
env = PSEUDO
else
io.write("Test Pseudo(p), Lanes(l), or love(Run in love environment) Threading: ")
choice = io.read()
if choice == "p" then
GLOBAL, THREAD = require("multi.integration.pseudoManager"):init()
env = PSEUDO
elseif choice == "l" then
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
env = LANES
else
error("Invalid threading choice")
end
end
multi.print("Testing THREAD.setENV() if the multi_assert is not found then there is a problem")
THREAD.setENV({
multi_assert = function(expected, actual, s)
if expected ~= actual then
multi.error(s .. " Expected: '".. tostring(expected) .."' Actual: '".. tostring(actual) .."'")
end
end
})
multi:newThread("Scheduler Thread",function()
multi:newThread(function()
thread.sleep(30)
print("Timeout tests took longer than 30 seconds")
multi:Stop()
os.exit(1)
end)
queue = multi:newSystemThreadedQueue("Test_Queue")
defer_queue = multi:newSystemThreadedQueue("Defer_Queue")
multi:newSystemThread("Test_Thread_0", function()
defer_queue = THREAD.waitFor("Defer_Queue"):init()
THREAD.defer(function()
defer_queue:push("done")
multi.print("This function was defered until the end of the threads life")
end)
multi.print("Testing defer, should print below this")
if THREAD_NAME~="Test_Thread_0" then
multi.error("The name should be Test_Thread_0",THREAD_NAME,THREAD_NAME,_G.THREAD_NAME)
end
end)
if thread.hold(function()
return defer_queue:pop() == "done"
end,{sleep=3}) == nil then
multi.error("Thread.defer didn't work!")
end
th1 = multi:newSystemThread("Test_Thread_1", function(a,b,c,d,e,f)
queue = THREAD.waitFor("Test_Queue"):init()
multi_assert("Test_Thread_1", THREAD_NAME, "Thread name does not match!")
multi_assert("Passing some args", a, "First argument is not as expected 'Passing some args'")
multi_assert(true, e, "Argument e is not true!")
multi_assert("table", type(f), "Argument f is not a table!")
queue:push("done")
end,"Passing some args", 1, 2, 3, true, {"Table"}).OnError(function(self,err)
multi.error(err)
os.exit(1)
end)
if thread.hold(function()
return queue:pop() == "done"
end,{sleep=1}) == nil then
thread.kill()
end
multi.success("Thread Spawning, THREAD namaspace in threads, global's working, and queues for passing data: Ok")
func = THREAD:newFunction(function(a,b,c)
assert(a == 3, "First argument expected '3' got '".. a .."'!")
assert(b == 2, "Second argument expected '2' got '".. b .."'!")
assert(c == 1, "Third argument expected '1' got '".. c .."'!")
return 1, 2, 3, {"a table"}
end, true) -- Hold this
a, b, c, d = func(3,2,1)
assert(a == 1, "First return was not '1'!")
assert(b == 2, "Second return was not '2'!")
assert(c == 3, "Third return was not '3'!")
assert(d[1] == "a table", "Fourth return is not table, or doesn't contain 'a table'!")
multi.success("Threaded Functions, arg passing, return passing, holding: Ok")
test=multi:newSystemThreadedTable("YO"):init()
test["test1"]="tabletest"
local worked = false
multi:newSystemThread("testing tables",function()
tab=THREAD.waitFor("YO")
THREAD.hold(function() return tab["test1"] end)
THREAD.sleep(.1)
tab["test2"] = "Whats so funny?"
end).OnError(multi.error)
multi:newThread("test2",function()
thread.hold(function() return test["test2"] end)
worked = true
end)
t, val = thread.hold(function()
return worked
end,{sleep=2})
if val == multi.TIMEOUT then
multi.error("SystemThreadedTables: Failed")
os.exit(1)
end
multi.success("SystemThreadedTables: Ok")
local ready = false
jq = multi:newSystemThreadedJobQueue(4) -- Job queue with 4 worker threads
func2 = jq:newFunction("sleep",function(a,b)
THREAD.sleep(.2)
end)
func = jq:newFunction("test-thread",function(a,b)
sleep()
return a+b
end)
local count = 0
for i = 1,10 do
func(i, i*3).OnReturn(function(data)
count = count + 1
end)
end
t, val = thread.hold(function()
return count == 10
end,{sleep=3})
if val == multi.TIMEOUT then
multi.error("SystemThreadedJobQueues: Failed")
os.exit(1)
end
multi.success("SystemThreadedJobQueues: Ok")
local proxy_test = false
local stp = multi:newSystemThreadedProcessor(5)
local tloop = stp:newTLoop(function()
--print("Test")
end, 1)
multi:newSystemThread("PROX_THREAD",function(tloop)
local multi, thread = require("multi"):init()
tloop = tloop:init()
multi.print("tloop type:",tloop.Type)
multi.print("Testing proxies on other threads")
thread:newThread(function()
while true do
thread.hold(tloop.OnLoop)
print(THREAD_NAME,"Loopy")
end
end)
tloop.OnLoop(function(a)
print(THREAD_NAME, "Got loop...")
end)
multi:mainloop()
end, tloop:getTransferable())
local test = tloop:getTransferable()
multi.print("tloop", tloop.Type)
multi.print("tloop.OnLoop", tloop.OnLoop.Type)
thread:newThread("Proxy Test Thread",function()
multi.print("Testing holding on a proxy connection!")
thread.hold(tloop.OnLoop)
multi.print("Held on proxy connection... once")
thread.hold(tloop.OnLoop)
multi.print("Held on proxy connection... twice")
thread.hold(tloop.OnLoop)
multi.print("Held on proxy connection... finally")
proxy_test = true
end).OnError(print)
thread:newThread(function()
thread.defer(function()
multi.print("Something happened!")
end)
while true do
thread.hold(tloop.OnLoop)
multi.print(THREAD_NAME,"Local Loopy")
end
end).OnError(function(...)
print("Error",...)
end)
tloop.OnLoop(function()
print("OnLoop", THREAD_NAME)
end)
t, val = thread.hold(function()
return proxy_test
end,{sleep=10})
if val == multi.TIMEOUT then
multi.error("SystemThreadedProcessor/Proxies: Failed")
os.exit(1)
else
multi.success("SystemThreadedProcessor: OK")
end
thread.sleep(2)
we_good = true
multi:Stop() -- Needed in love2d tests to stop the main runner
os.exit(0)
end)
multi.OnExit(function(err_or_errorcode)
multi.print("EC: ", err_or_errorcode)
if not we_good then
multi.print("There was an error running some tests!")
return
else
multi.success("Tests complete!")
end
end)
multi:mainloop()