Working on psuedo threading
This commit is contained in:
parent
61dcb9da01
commit
9d97eac146
32
changes.md
32
changes.md
@ -24,18 +24,48 @@ for i = 1,100 do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test = true
|
||||||
|
local haha = true
|
||||||
|
multi:newThread("Standard Thread 1",function()
|
||||||
|
print(self.Name,haha)
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
print("Testing "..self.Name..":",test)
|
||||||
|
thread.sleep(.1)
|
||||||
|
prient("...")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
multi:newThread("Standard Thread 2",function()
|
||||||
|
print(self.Name)
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
print("Testing "..self.Name..":",test)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
multi:newISOThread("Isolated Thread",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
print("Testing Isolated:",test)
|
||||||
|
--errhor("huh")
|
||||||
|
end
|
||||||
|
end).OnError(function(...)
|
||||||
|
print(...)
|
||||||
|
end)
|
||||||
|
|
||||||
multi:lightloop()
|
multi:lightloop()
|
||||||
```
|
```
|
||||||
|
|
||||||
Added:
|
Added:
|
||||||
---
|
---
|
||||||
|
- multi:newISOThread(name,func)
|
||||||
|
- Creates an isolated thread that prevents both locals and globals from being accessed.
|
||||||
- Added new integration: pesudoManager, functions just like lanesManager and loveManager, but it's actually single threaded
|
- 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.
|
- 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.
|
- 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()
|
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.
|
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.
|
||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
---
|
---
|
||||||
|
|||||||
128
multi/init.lua
128
multi/init.lua
@ -1072,13 +1072,21 @@ function thread:newFunction(func,holdme)
|
|||||||
return temp
|
return temp
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- A cross version way to set enviroments, not the same as fenv though
|
||||||
|
function multi.setEnv(func,env)
|
||||||
|
local f = string.dump(func)
|
||||||
|
local chunk = load(f,"env","bt",env)
|
||||||
|
return chunk
|
||||||
|
end
|
||||||
|
|
||||||
function multi:newThread(name,func,...)
|
function multi:newThread(name,func,...)
|
||||||
multi.OnLoad:Fire()
|
multi.OnLoad:Fire()
|
||||||
local func = func or name
|
local func = func or name
|
||||||
if type(name) == "function" then
|
if type(name) == "function" then
|
||||||
name = "Thread#"..threadCount
|
name = "Thread#"..threadCount
|
||||||
end
|
end
|
||||||
local env = {}
|
local c={}
|
||||||
|
local env = {self=c}
|
||||||
setmetatable(env,{
|
setmetatable(env,{
|
||||||
__index = Gref,
|
__index = Gref,
|
||||||
__newindex = function(t,k,v)
|
__newindex = function(t,k,v)
|
||||||
@ -1090,7 +1098,117 @@ function multi:newThread(name,func,...)
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
setfenv(func,env)
|
setfenv(func,env)
|
||||||
|
c.TempRets = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
|
||||||
|
c.startArgs = {...}
|
||||||
|
c.ref={}
|
||||||
|
c.Name=name
|
||||||
|
c.thread=coroutine.create(func)
|
||||||
|
c.sleep=1
|
||||||
|
c.Type="thread"
|
||||||
|
c.TID = threadid
|
||||||
|
c.firstRunDone=false
|
||||||
|
c.timer=multi:newTimer()
|
||||||
|
c._isPaused = false
|
||||||
|
c.returns = {}
|
||||||
|
c.OnError = multi:newConnection(true,nil,true)
|
||||||
|
c.OnDeath = multi:newConnection(true,nil,true)
|
||||||
|
function c:isPaused()
|
||||||
|
return self._isPaused
|
||||||
|
end
|
||||||
|
local resumed = false
|
||||||
|
function c:Pause()
|
||||||
|
if not self._isPaused then
|
||||||
|
thread.request(self,"exec",function()
|
||||||
|
thread.hold(function()
|
||||||
|
return resumed
|
||||||
|
end)
|
||||||
|
resumed = false
|
||||||
|
self._isPaused = false
|
||||||
|
end)
|
||||||
|
self._isPaused = true
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function c:Resume()
|
||||||
|
resumed = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
function c:Kill()
|
||||||
|
thread.request(self,"kill")
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
c.Destroy = c.Kill
|
||||||
|
function c.ref:send(name,val)
|
||||||
|
ret=coroutine.yield({Name=name,Value=val})
|
||||||
|
end
|
||||||
|
function c.ref:get(name)
|
||||||
|
return self.Globals[name]
|
||||||
|
end
|
||||||
|
function c.ref:kill()
|
||||||
|
dRef[1] = "_kill_"
|
||||||
|
dRef[2] = "I Was killed by You!"
|
||||||
|
err = coroutine.yield(dRef)
|
||||||
|
if err then
|
||||||
|
error("Failed to kill a thread! Exiting...")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function c.ref:sleep(n)
|
||||||
|
if type(n)=="function" then
|
||||||
|
ret=thread.hold(n)
|
||||||
|
elseif type(n)=="number" then
|
||||||
|
ret=thread.sleep(tonumber(n) or 0)
|
||||||
|
else
|
||||||
|
error("Invalid Type for sleep!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function c.ref:syncGlobals(v)
|
||||||
|
self.Globals=v
|
||||||
|
end
|
||||||
|
table.insert(threads,c)
|
||||||
|
if initT==false then
|
||||||
|
multi.initThreads()
|
||||||
|
end
|
||||||
|
c.creationTime = os.clock()
|
||||||
|
threadid = threadid + 1
|
||||||
|
self:create(c)
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
function multi:newISOThread(name,func,...)
|
||||||
|
multi.OnLoad:Fire()
|
||||||
|
local func = func or name
|
||||||
|
if type(name) == "function" then
|
||||||
|
name = "Thread#"..threadCount
|
||||||
|
end
|
||||||
|
local env = {
|
||||||
|
thread = thread,
|
||||||
|
multi = multi,
|
||||||
|
coroutine = coroutine,
|
||||||
|
debug = debug,
|
||||||
|
io = io,
|
||||||
|
math = math,
|
||||||
|
os = os,
|
||||||
|
package = package,
|
||||||
|
string = string,
|
||||||
|
table = table,
|
||||||
|
utf8 = utf8
|
||||||
|
}
|
||||||
|
for i,v in pairs(_G) do
|
||||||
|
if tostring(v):match("builtin") then
|
||||||
|
env[i]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
setmetatable(env,{
|
||||||
|
__newindex = function(t,k,v)
|
||||||
|
if type(v)=="function" then
|
||||||
|
rawset(t,k,thread:newFunction(v))
|
||||||
|
else
|
||||||
|
Gref[k]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
local func = multi.setEnv(func,env)
|
||||||
local c={}
|
local c={}
|
||||||
|
env.self = c
|
||||||
c.TempRets = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
|
c.TempRets = {nil,nil,nil,nil,nil,nil,nil,nil,nil,nil}
|
||||||
c.startArgs = {...}
|
c.startArgs = {...}
|
||||||
c.ref={}
|
c.ref={}
|
||||||
@ -1255,9 +1373,11 @@ function multi.initThreads(justThreads)
|
|||||||
multi.scheduler:OnLoop(function(self)
|
multi.scheduler:OnLoop(function(self)
|
||||||
for i=#threads,1,-1 do
|
for i=#threads,1,-1 do
|
||||||
if threads[i].isError then
|
if threads[i].isError then
|
||||||
threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets))
|
if coroutine.status(threads[i].thread)=="dead" then
|
||||||
multi.setType(threads[i],multi.DestroyedObj)
|
threads[i].OnError:Fire(threads[i],unpack(threads[i].TempRets))
|
||||||
table.remove(threads,i)
|
multi.setType(threads[i],multi.DestroyedObj)
|
||||||
|
table.remove(threads,i)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if threads[i] and not threads[i].__started then
|
if threads[i] and not threads[i].__started then
|
||||||
if coroutine.running() ~= threads[i].thread then
|
if coroutine.running() ~= threads[i].thread then
|
||||||
|
|||||||
@ -43,7 +43,9 @@ function multi:getPlatform()
|
|||||||
end
|
end
|
||||||
|
|
||||||
THREAD.newFunction=thread.newFunction
|
THREAD.newFunction=thread.newFunction
|
||||||
multi.newSystemThread = multi.newThread
|
multi.newSystemThread = multi.newISOThread
|
||||||
|
-- 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
|
||||||
|
|
||||||
print("Integrated Pesudo Threading!")
|
print("Integrated Pesudo Threading!")
|
||||||
multi.integration = {} -- for module creators
|
multi.integration = {} -- for module creators
|
||||||
|
|||||||
15
test.lua
15
test.lua
@ -1,7 +1,18 @@
|
|||||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
||||||
multi,thread = require("multi"):init()
|
multi,thread = require("multi"):init()
|
||||||
GLOBAL,THREAD = require("multi.integration.pesudoManager"):init()
|
GLOBAL,THREAD = require("multi.integration.pesudoManager"):init()
|
||||||
|
test = true
|
||||||
|
local haha = true
|
||||||
|
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:mainloop()
|
||||||
multi:mainloop({print=true})
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user