threaded functions can now be paused
This commit is contained in:
parent
ea77b934b6
commit
9cff2735ba
73
changes.md
73
changes.md
@ -120,15 +120,84 @@ process|Thread|thread| A handle to a multi thread object
|
|||||||
Changed:
|
Changed:
|
||||||
---
|
---
|
||||||
|
|
||||||
|
- `f = thread:newFunction(func,holdme)`
|
||||||
|
- Nothing changed that will affect how the object functions defaulty. The returned function is now a table that is callable and 2 new methods have been added:
|
||||||
|
|
||||||
|
Method | Description
|
||||||
|
---|---
|
||||||
|
Pause() | Pauses the function, Will cause the function to return `nil, Function is paused`
|
||||||
|
Resume() | Resumes the function
|
||||||
|
|
||||||
|
```lua
|
||||||
|
package.path = "./?/init.lua;"..package.path
|
||||||
|
multi, thread = require("multi"):init()
|
||||||
|
|
||||||
|
test = thread:newFunction(function(a,b)
|
||||||
|
thread.sleep(1)
|
||||||
|
return a,b
|
||||||
|
end, true)
|
||||||
|
|
||||||
|
print(test(1,2))
|
||||||
|
|
||||||
|
test:Pause()
|
||||||
|
|
||||||
|
print(test(1,2))
|
||||||
|
|
||||||
|
test:Resume()
|
||||||
|
|
||||||
|
print(test(1,2))
|
||||||
|
|
||||||
|
--[[ -- If you left holdme nil/false
|
||||||
|
|
||||||
|
print(test(1,2).connect(function(...)
|
||||||
|
print(...)
|
||||||
|
end))
|
||||||
|
|
||||||
|
test:Pause()
|
||||||
|
|
||||||
|
print(test(1,2).connect(function(...)
|
||||||
|
print(...)
|
||||||
|
end))
|
||||||
|
|
||||||
|
test:Resume()
|
||||||
|
|
||||||
|
print(test(1,2).connect(function(...)
|
||||||
|
print(...)
|
||||||
|
end))
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output:**
|
||||||
|
|
||||||
|
```
|
||||||
|
1 2
|
||||||
|
nil Function is paused
|
||||||
|
1 2
|
||||||
|
```
|
||||||
|
|
||||||
|
**If holdme is nil/false:**
|
||||||
|
|
||||||
|
```
|
||||||
|
nil Function is paused
|
||||||
|
|
||||||
|
|
||||||
|
1 2 nil...
|
||||||
|
1 2 nil...
|
||||||
|
```
|
||||||
|
|
||||||
- thread.hold(n,opt) [Ref. Issue](https://github.com/rayaman/multi/issues/24)
|
- thread.hold(n,opt) [Ref. Issue](https://github.com/rayaman/multi/issues/24)
|
||||||
- Added option table to thread.hold
|
- Added option table to thread.hold
|
||||||
| Option | Description |
|
| Option | Description |
|
||||||
---|---
|
---|---
|
||||||
|
| interval | Time between each poll |
|
||||||
| cycles | Number of cycles before timing out |
|
| cycles | Number of cycles before timing out |
|
||||||
| sleep | Number of seconds before timing out |
|
| sleep | Number of seconds before timing out |
|
||||||
| interval | Time between each poll |
|
| skip | Number of cycles before testing again, does not cause a timeout! |
|
||||||
|
|
||||||
**Note:** cycles and sleep options cannot both be used at the same time. Cycles take priority if both are present! HoldFor and HoldWithin can be emulated using the new features. Old functions will remain for backward compatibility.
|
**Note:** cycles and sleep options cannot both be used at the same time. Interval and skip cannot be used at the same time either. Cycles take priority than sleep if both are present! HoldFor and HoldWithin can be emulated using the new features. Old functions will remain for backward compatibility.
|
||||||
|
|
||||||
Using cycles, sleep or interval will cause a timeout; returning nil, multi.TIMEOUT
|
Using cycles, sleep or interval will cause a timeout; returning nil, multi.TIMEOUT
|
||||||
- `n` can be a number and thread.hold will act like thread.sleep. When `n` is a number the option table will be ignored!
|
- `n` can be a number and thread.hold will act like thread.sleep. When `n` is a number the option table will be ignored!
|
||||||
|
|||||||
@ -102,7 +102,7 @@ function multi:getTasksDetails(t)
|
|||||||
count = count + 1
|
count = count + 1
|
||||||
table.insert(str,{v.Type:sub(1,1):upper()..v.Type:sub(2,-1)..name,multi.Round(os.clock()-v.creationTime,3),self.PriorityResolve[v.Priority],v.TID})
|
table.insert(str,{v.Type:sub(1,1):upper()..v.Type:sub(2,-1)..name,multi.Round(os.clock()-v.creationTime,3),self.PriorityResolve[v.Priority],v.TID})
|
||||||
end
|
end
|
||||||
for v,i in pairs(multi.PausedObjects) do
|
for v,i in pairs(self.PausedObjects) do
|
||||||
local name = v.Name or ""
|
local name = v.Name or ""
|
||||||
if name~="" then
|
if name~="" then
|
||||||
name = " <"..name..">"
|
name = " <"..name..">"
|
||||||
@ -1007,6 +1007,10 @@ function thread.hold(n,opt)
|
|||||||
dRef[2] = opt.sleep
|
dRef[2] = opt.sleep
|
||||||
dRef[3] = n or dFunc
|
dRef[3] = n or dFunc
|
||||||
return coroutine.yield(dRef)
|
return coroutine.yield(dRef)
|
||||||
|
elseif opt.skip then
|
||||||
|
dRef[1] = "_skip_"
|
||||||
|
dRef[2] = opt.skip or 1
|
||||||
|
return coroutine.yield(dRef)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if type(n) == "number" then
|
if type(n) == "number" then
|
||||||
@ -1126,27 +1130,50 @@ local function cleanReturns(...)
|
|||||||
return unpack(returns,1,ind)
|
return unpack(returns,1,ind)
|
||||||
end
|
end
|
||||||
function thread:newFunction(func,holdme)
|
function thread:newFunction(func,holdme)
|
||||||
return function(...)
|
local tfunc = {}
|
||||||
local rets, err
|
tfunc.Active = true
|
||||||
|
function tfunc:Pause()
|
||||||
|
self.Active = false
|
||||||
|
end
|
||||||
|
function tfunc:Resume()
|
||||||
|
self.Active = true
|
||||||
|
end
|
||||||
|
local function noWait()
|
||||||
|
return nil, "Function is paused"
|
||||||
|
end
|
||||||
|
local rets, err
|
||||||
local function wait(no)
|
local function wait(no)
|
||||||
if thread.isThread() and not (no) then
|
if thread.isThread() and not (no) then
|
||||||
return multi.hold(function()
|
return multi.hold(function()
|
||||||
if err then
|
|
||||||
return multi.NIL, err
|
|
||||||
elseif rets then
|
|
||||||
return cleanReturns((rets[1] or multi.NIL),rets[2],rets[3],rets[4],rets[5],rets[6],rets[7],rets[8],rets[9],rets[10],rets[11],rets[12],rets[13],rets[14],rets[15],rets[16])
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
while not rets and not err do
|
|
||||||
multi.scheduler:Act()
|
|
||||||
end
|
|
||||||
if err then
|
if err then
|
||||||
return nil,err
|
return multi.NIL, err
|
||||||
|
elseif rets then
|
||||||
|
return cleanReturns((rets[1] or multi.NIL),rets[2],rets[3],rets[4],rets[5],rets[6],rets[7],rets[8],rets[9],rets[10],rets[11],rets[12],rets[13],rets[14],rets[15],rets[16])
|
||||||
end
|
end
|
||||||
return cleanReturns(rets[1],rets[2],rets[3],rets[4],rets[5],rets[6],rets[7],rets[8],rets[9],rets[10],rets[11],rets[12],rets[13],rets[14],rets[15],rets[16])
|
end)
|
||||||
|
else
|
||||||
|
while not rets and not err do
|
||||||
|
multi.scheduler:Act()
|
||||||
end
|
end
|
||||||
|
if err then
|
||||||
|
return nil,err
|
||||||
|
end
|
||||||
|
return cleanReturns(rets[1],rets[2],rets[3],rets[4],rets[5],rets[6],rets[7],rets[8],rets[9],rets[10],rets[11],rets[12],rets[13],rets[14],rets[15],rets[16])
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
tfunc.__call = function(t,...)
|
||||||
|
if not t.Active then
|
||||||
|
if holdme then
|
||||||
|
return nil, "Function is paused"
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
isTFunc = true,
|
||||||
|
wait = noWait,
|
||||||
|
connect = function(f)
|
||||||
|
f(nil,"Function is paused")
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
local t = multi.getCurrentProcess():newThread("TempThread",func,...)
|
local t = multi.getCurrentProcess():newThread("TempThread",func,...)
|
||||||
t.OnDeath(function(self,status,...) rets = {...} end)
|
t.OnDeath(function(self,status,...) rets = {...} end)
|
||||||
t.OnError(function(self,e) err = e end)
|
t.OnError(function(self,e) err = e end)
|
||||||
@ -1158,11 +1185,13 @@ function thread:newFunction(func,holdme)
|
|||||||
wait = wait,
|
wait = wait,
|
||||||
connect = function(f)
|
connect = function(f)
|
||||||
t.OnDeath(function(self,status,...) f(...) end)
|
t.OnDeath(function(self,status,...) f(...) end)
|
||||||
t.OnError(function(self,err) f(err) end)
|
t.OnError(function(self,err) f(nil,err) end)
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
return temp
|
return temp
|
||||||
end
|
end
|
||||||
|
setmetatable(tfunc,tfunc)
|
||||||
|
return tfunc
|
||||||
end
|
end
|
||||||
-- A cross version way to set enviroments, not the same as fenv though
|
-- A cross version way to set enviroments, not the same as fenv though
|
||||||
function multi.setEnv(func,env)
|
function multi.setEnv(func,env)
|
||||||
|
|||||||
117
test.lua
117
test.lua
@ -2,60 +2,75 @@ package.path = "./?/init.lua;"..package.path
|
|||||||
multi,thread = require("multi"):init()
|
multi,thread = require("multi"):init()
|
||||||
--GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
--GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
||||||
|
|
||||||
|
test = thread:newFunction(function(a,b)
|
||||||
test = thread:newFunction(function()
|
thread.sleep(1)
|
||||||
return 1,2,nil,3,4,5,6,7,8,9
|
return a,b
|
||||||
end,true)
|
|
||||||
print(test())
|
|
||||||
multi:newThread("testing",function()
|
|
||||||
print("#Test = ",test())
|
|
||||||
print(thread.hold(function()
|
|
||||||
print("Hello!")
|
|
||||||
return false
|
|
||||||
end,{
|
|
||||||
interval = 2,
|
|
||||||
cycles = 3
|
|
||||||
})) -- End result, 3 attempts within 6 seconds. If still false then timeout
|
|
||||||
print("held")
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
|
||||||
end)
|
end)
|
||||||
|
print(test(1,2).connect(function(...)
|
||||||
sandbox = multi:newProcessor()
|
|
||||||
for i,v in pairs(sandbox.process) do
|
|
||||||
print(i,v)
|
|
||||||
end
|
|
||||||
io.read()
|
|
||||||
sandbox:newTLoop(function()
|
|
||||||
print("testing...")
|
|
||||||
end,1)
|
|
||||||
|
|
||||||
test2 = multi:newTLoop(function()
|
|
||||||
print("testing2...")
|
|
||||||
end,1)
|
|
||||||
|
|
||||||
sandbox:newThread("Test Thread",function()
|
|
||||||
local a = 0
|
|
||||||
while true do
|
|
||||||
thread.sleep(1)
|
|
||||||
a = a + 1
|
|
||||||
print("Thread Test: ".. multi.getCurrentProcess().Name)
|
|
||||||
if a == 10 then
|
|
||||||
sandbox.Stop()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
print(...)
|
||||||
end)
|
end))
|
||||||
multi:newThread("Test Thread",function()
|
test:Pause()
|
||||||
while true do
|
print(test(1,2).connect(function(...)
|
||||||
thread.sleep(1)
|
|
||||||
print("Thread Test: ".. multi.getCurrentProcess().Name)
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
print(...)
|
||||||
end)
|
end))
|
||||||
|
test:Resume()
|
||||||
|
print(test(1,2).connect(function(...)
|
||||||
|
print(...)
|
||||||
|
end))
|
||||||
|
|
||||||
sandbox.Start()
|
-- test = thread:newFunction(function()
|
||||||
|
-- return 1,2,nil,3,4,5,6,7,8,9
|
||||||
|
-- end,true)
|
||||||
|
-- print(test())
|
||||||
|
-- multi:newThread("testing",function()
|
||||||
|
-- print("#Test = ",test())
|
||||||
|
-- print(thread.hold(function()
|
||||||
|
-- print("Hello!")
|
||||||
|
-- return false
|
||||||
|
-- end,{
|
||||||
|
-- interval = 2,
|
||||||
|
-- cycles = 3
|
||||||
|
-- })) -- End result, 3 attempts within 6 seconds. If still false then timeout
|
||||||
|
-- print("held")
|
||||||
|
-- end).OnError(function(...)
|
||||||
|
-- print(...)
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
-- sandbox = multi:newProcessor()
|
||||||
|
-- for i,v in pairs(sandbox.process) do
|
||||||
|
-- print(i,v)
|
||||||
|
-- end
|
||||||
|
-- io.read()
|
||||||
|
-- sandbox:newTLoop(function()
|
||||||
|
-- print("testing...")
|
||||||
|
-- end,1)
|
||||||
|
|
||||||
|
-- test2 = multi:newTLoop(function()
|
||||||
|
-- print("testing2...")
|
||||||
|
-- end,1)
|
||||||
|
|
||||||
|
-- sandbox:newThread("Test Thread",function()
|
||||||
|
-- local a = 0
|
||||||
|
-- while true do
|
||||||
|
-- thread.sleep(1)
|
||||||
|
-- a = a + 1
|
||||||
|
-- print("Thread Test: ".. multi.getCurrentProcess().Name)
|
||||||
|
-- if a == 10 then
|
||||||
|
-- sandbox.Stop()
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end).OnError(function(...)
|
||||||
|
-- print(...)
|
||||||
|
-- end)
|
||||||
|
-- multi:newThread("Test Thread",function()
|
||||||
|
-- while true do
|
||||||
|
-- thread.sleep(1)
|
||||||
|
-- print("Thread Test: ".. multi.getCurrentProcess().Name)
|
||||||
|
-- end
|
||||||
|
-- end).OnError(function(...)
|
||||||
|
-- print(...)
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
-- sandbox.Start()
|
||||||
|
|
||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
Loading…
x
Reference in New Issue
Block a user