Working on 15.0.0
This commit is contained in:
parent
b597fbdf9b
commit
61dcb9da01
@ -1,4 +1,6 @@
|
||||
# Multi Version: 14.2.0 Documentation Complete, Bloat removed!
|
||||
# Multi Version: 15.0.0 Fake it, until you make it
|
||||
**Key Changes**
|
||||
- Emulating system threading on a single thread
|
||||
|
||||
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and I'll look into it!
|
||||
|
||||
|
||||
37
changes.md
37
changes.md
@ -4,6 +4,43 @@ Table of contents
|
||||
---
|
||||
[Update 14.2.0 - Bloatware Removed](#update-1420---bloatware-removed)</br>[Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)</br>[Update 14.0.0 - Consistency, Additions and Stability](#update-1400---consistency-additions-and-stability)</br>[Update 13.1.0 - Bug fixes and features added](#update-1310---bug-fixes-and-features-added)</br>[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300---added-some-documentation-and-some-new-features-too-check-it-out)</br>[Update 12.2.2 - Time for some more bug fixes!](#update-1222---time-for-some-more-bug-fixes)</br>[Update 12.2.1 - Time for some bug fixes!](#update-1221---time-for-some-bug-fixes)</br>[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)</br>[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)</br>[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200---big-update-lots-of-additions-some-changes)</br>[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)</br>[Update: 1.11.0](#update-1110)</br>[Update: 1.10.0](#update-1100)</br>[Update: 1.9.2](#update-192)</br>[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)</br>[Update: 1.9.0](#update-190)</br>[Update: 1.8.7](#update-187)</br>[Update: 1.8.6](#update-186)</br>[Update: 1.8.5](#update-185)</br>[Update: 1.8.4](#update-184)</br>[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)</br>[Update: 1.8.2](#update-182)</br>[Update: 1.8.1](#update-181)</br>[Update: 1.7.6](#update-176)</br>[Update: 1.7.5](#update-175)</br>[Update: 1.7.4](#update-174)</br>[Update: 1.7.3](#update-173)</br>[Update: 1.7.2](#update-172)</br>[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)</br>[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)</br>[Update: 1.6.0](#update-160)</br>[Update: 1.5.0](#update-150)</br>[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)</br>[Update: 1.4.0 (3/20/2017)](#update-140-3202017)</br>[Update: 1.3.0 (1/29/2017)](#update-130-1292017)</br>[Update: 1.2.0 (12.31.2016)](#update-120-12312016)</br>[Update: 1.1.0](#update-110)</br>[Update: 1.0.0](#update-100)</br>[Update: 0.6.3](#update-063)</br>[Update: 0.6.2](#update-062)</br>[Update: 0.6.1-6](#update-061-6)</br>[Update: 0.5.1-6](#update-051-6)</br>[Update: 0.4.1](#update-041)</br>[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)</br>[Update: EventManager 2.0.0](#update-eventmanager-200)</br>[Update: EventManager 1.2.0](#update-eventmanager-120)</br>[Update: EventManager 1.1.0](#update-eventmanager-110)</br>[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</br>[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different)
|
||||
|
||||
# Update 15.0.0 - The art of faking it
|
||||
Full Update Showcase
|
||||
---
|
||||
```lua
|
||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
||||
multi,thread = require("multi"):init()
|
||||
GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
||||
|
||||
jq = multi:newSystemThreadedJobQueue(100) -- Job queue with 4 worker threads
|
||||
func = jq:newFunction("test",function(a,b)
|
||||
THREAD.sleep(2)
|
||||
return a+b
|
||||
end)
|
||||
|
||||
for i = 1,100 do
|
||||
func(i,i*3).connect(function(data)
|
||||
print(data)
|
||||
end)
|
||||
end
|
||||
|
||||
multi:lightloop()
|
||||
```
|
||||
|
||||
Added:
|
||||
---
|
||||
- Added new integration: pesudoManager, functions just like lanesManager and loveManager, but it's actually single threaded
|
||||
- This was implemented because, you may want to build your code around being multi threaded, but some systems/implemetations of lua may not permit this. Since we now have a "single threaded" implementation of multi threading. We can actually create scalable code where things automatcally are threaded if built correctly. I am planning on adding more threadedOjbects.
|
||||
- In addition to adding pesudo Threading `multi.integration.threading` can now be used to autodetect which enviroment you are on and use the threading features.
|
||||
```
|
||||
GLOBAL,THREAD = require("multi.integration.threading"):init()
|
||||
```
|
||||
If you are using love2d it will use that, if you have lanes avaialble then it will use lanes. Otherwise it will use pesudo threading. This allows module creators to implement scalable features without having to worry about which enviroment they are in. And it's my job to ensure everything works properly within reason.
|
||||
|
||||
Fixed:
|
||||
---
|
||||
- lanesManager THREAD:get(STRING: name) not returning the value
|
||||
|
||||
# Update 14.2.0 - Bloatware Removed
|
||||
Full Update Showcase
|
||||
---
|
||||
|
||||
@ -30,7 +30,7 @@ if not _G["$multi"] then
|
||||
_G["$multi"] = {multi=multi,thread=thread}
|
||||
end
|
||||
|
||||
multi.Version = "14.2.0"
|
||||
multi.Version = "15.0.0"
|
||||
multi.stage = "stable"
|
||||
multi.Name = "multi.root"
|
||||
multi.Mainloop = {}
|
||||
@ -1430,7 +1430,8 @@ end
|
||||
function multi:threadloop()
|
||||
multi.initThreads(true)
|
||||
end
|
||||
function multi:lightloop()
|
||||
function multi:lightloop(settings)
|
||||
multi.defaultSettings = settings or multi.defaultSettings
|
||||
if not isRunning then
|
||||
local Loop=self.Mainloop
|
||||
while true do
|
||||
|
||||
@ -100,7 +100,7 @@ function multi:newSystemThreadedJobQueue(n)
|
||||
link = c.OnJobCompleted(function(jid,...)
|
||||
if id==jid then
|
||||
rets = {...}
|
||||
link:Remove()
|
||||
link:Destroy()
|
||||
end
|
||||
end)
|
||||
return thread.hold(function()
|
||||
|
||||
@ -23,7 +23,7 @@ SOFTWARE.
|
||||
]]
|
||||
package.path = "?/init.lua;?.lua;" .. package.path
|
||||
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 hassel
|
||||
if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassle
|
||||
return {
|
||||
init = function()
|
||||
return multi.integration.GLOBAL, multi.integration.THREAD
|
||||
@ -145,7 +145,7 @@ function multi.InitSystemThreadErrorHandler()
|
||||
end
|
||||
)
|
||||
end
|
||||
multi.print("Integrated Lanes!")
|
||||
print("Integrated Lanes!")
|
||||
multi.integration = {} -- for module creators
|
||||
multi.integration.GLOBAL = GLOBAL
|
||||
multi.integration.THREAD = THREAD
|
||||
|
||||
@ -41,7 +41,7 @@ local function INIT(__GlobalLinda,__SleepingLinda)
|
||||
__GlobalLinda:set(name, val)
|
||||
end
|
||||
function THREAD.get(name)
|
||||
__GlobalLinda:get(name)
|
||||
return __GlobalLinda:get(name)
|
||||
end
|
||||
function THREAD.waitFor(name)
|
||||
local function wait()
|
||||
|
||||
@ -116,7 +116,7 @@ function multi:newSystemThreadedJobQueue(n)
|
||||
link = c.OnJobCompleted(function(jid,...)
|
||||
if id==jid then
|
||||
rets = {...}
|
||||
link:Remove()
|
||||
link:Destroy()
|
||||
end
|
||||
end)
|
||||
return thread.hold(function()
|
||||
|
||||
@ -81,6 +81,7 @@ end
|
||||
multi.integration.GLOBAL = GLOBAL
|
||||
multi.integration.THREAD = THREAD
|
||||
require("multi.integration.loveManager.extensions")
|
||||
print("Integrated Love Threading!")
|
||||
return {init=function()
|
||||
return GLOBAL,THREAD
|
||||
end}
|
||||
126
multi/integration/pesudoManager/extensions.lua
Normal file
126
multi/integration/pesudoManager/extensions.lua
Normal file
@ -0,0 +1,126 @@
|
||||
--[[
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 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
|
||||
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
|
||||
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 = {...}
|
||||
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
|
||||
multi: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
|
||||
57
multi/integration/pesudoManager/init.lua
Normal file
57
multi/integration/pesudoManager/init.lua
Normal file
@ -0,0 +1,57 @@
|
||||
--[[
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 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.
|
||||
]]
|
||||
package.path = "?/init.lua;?.lua;" .. package.path
|
||||
local multi, thread = require("multi").init()
|
||||
|
||||
if multi.integration then
|
||||
return {
|
||||
init = function()
|
||||
return multi.integration.GLOBAL, multi.integration.THREAD
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
local GLOBAL, THREAD = require("multi.integration.pesudoManager.threads"):init()
|
||||
|
||||
function multi:canSystemThread() -- We are emulating system threading
|
||||
return true
|
||||
end
|
||||
|
||||
function multi:getPlatform()
|
||||
return "pesudo"
|
||||
end
|
||||
|
||||
THREAD.newFunction=thread.newFunction
|
||||
multi.newSystemThread = multi.newThread
|
||||
|
||||
print("Integrated Pesudo Threading!")
|
||||
multi.integration = {} -- for module creators
|
||||
multi.integration.GLOBAL = GLOBAL
|
||||
multi.integration.THREAD = THREAD
|
||||
require("multi.integration.pesudoManager.extensions")
|
||||
return {
|
||||
init = function()
|
||||
return GLOBAL, THREAD
|
||||
end
|
||||
}
|
||||
96
multi/integration/pesudoManager/threads.lua
Normal file
96
multi/integration/pesudoManager/threads.lua
Normal file
@ -0,0 +1,96 @@
|
||||
--[[
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 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 function getOS()
|
||||
if package.config:sub(1, 1) == "\\" then
|
||||
return "windows"
|
||||
else
|
||||
return "unix"
|
||||
end
|
||||
end
|
||||
local function INIT()
|
||||
local THREAD = {}
|
||||
local GLOBAL = {}
|
||||
THREAD.Priority_Core = 3
|
||||
THREAD.Priority_High = 2
|
||||
THREAD.Priority_Above_Normal = 1
|
||||
THREAD.Priority_Normal = 0
|
||||
THREAD.Priority_Below_Normal = -1
|
||||
THREAD.Priority_Low = -2
|
||||
THREAD.Priority_Idle = -3
|
||||
function THREAD.set(name, val)
|
||||
GLOBAL[name] = val
|
||||
end
|
||||
function THREAD.get(name)
|
||||
return GLOBAL[name]
|
||||
end
|
||||
function THREAD.waitFor(name)
|
||||
return thread.hold(function() return GLOBAL[name] end)
|
||||
end
|
||||
if getOS() == "windows" then
|
||||
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||
else
|
||||
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
||||
end
|
||||
function THREAD.getCores()
|
||||
return THREAD.__CORES
|
||||
end
|
||||
function THREAD.getConsole()
|
||||
local c = {}
|
||||
function c.print(...)
|
||||
print(...)
|
||||
end
|
||||
function c.error(err)
|
||||
error("ERROR in <"..__THREADNAME__..">: "..err)
|
||||
end
|
||||
return c
|
||||
end
|
||||
function THREAD.getThreads()
|
||||
return {}--GLOBAL.__THREADS__
|
||||
end
|
||||
if os.getOS() == "windows" then
|
||||
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||
else
|
||||
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
||||
end
|
||||
function THREAD.kill()
|
||||
error("Thread was killed!")
|
||||
end
|
||||
function THREAD.getName()
|
||||
return THREAD_NAME
|
||||
end
|
||||
function THREAD.getID()
|
||||
return THREAD_ID
|
||||
end
|
||||
_G.THREAD_ID = 0
|
||||
function THREAD.sleep(n)
|
||||
thread.sleep(n)
|
||||
end
|
||||
function THREAD.hold(n)
|
||||
return thread.hold(n)
|
||||
end
|
||||
return GLOBAL, THREAD
|
||||
end
|
||||
return {init = function()
|
||||
return INIT()
|
||||
end}
|
||||
13
multi/integration/threading.lua
Normal file
13
multi/integration/threading.lua
Normal file
@ -0,0 +1,13 @@
|
||||
-- We need to detect what enviroment we are running our code in.
|
||||
return {
|
||||
init = function()
|
||||
if love then
|
||||
return require("multi.integration.loveManager"):init()
|
||||
else
|
||||
if pcall(require,"lanes") then
|
||||
return require("multi.integration.lanesManager"):init()
|
||||
end
|
||||
return require("multi.integration.pesudoManager"):init()
|
||||
end
|
||||
end
|
||||
}
|
||||
43
test.lua
43
test.lua
@ -1,44 +1,7 @@
|
||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
||||
local multi,thread = require("multi"):init()
|
||||
multi,thread = require("multi"):init()
|
||||
GLOBAL,THREAD = require("multi.integration.pesudoManager"):init()
|
||||
|
||||
-- Testing destroying and fixed connections
|
||||
c = multi:newConnection()
|
||||
c1 = c(function()
|
||||
print("called 1")
|
||||
end)
|
||||
c2 = c(function()
|
||||
print("called 2")
|
||||
end)
|
||||
c3 = c(function()
|
||||
print("called 3")
|
||||
end)
|
||||
|
||||
print(c1,c2.Type,c3)
|
||||
c:Fire()
|
||||
c2:Destroy()
|
||||
print(c1,c2.Type,c3)
|
||||
c:Fire()
|
||||
c1:Destroy()
|
||||
print(c1,c2.Type,c3)
|
||||
c:Fire()
|
||||
|
||||
-- Destroying alarms and threads
|
||||
local test = multi:newThread(function()
|
||||
while true do
|
||||
thread.sleep(1)
|
||||
print("Hello!")
|
||||
end
|
||||
end)
|
||||
|
||||
test.OnDeath(function()
|
||||
os.exit() -- This is the last thing called.
|
||||
end)
|
||||
|
||||
local alarm = multi:newAlarm(4):OnRing(function(a)
|
||||
print(a.Type)
|
||||
a:Destroy()
|
||||
print(a.Type)
|
||||
test:Destroy()
|
||||
end)
|
||||
|
||||
multi:lightloop()
|
||||
multi:mainloop({print=true})
|
||||
Loading…
x
Reference in New Issue
Block a user