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:
|
||||
---
|
||||
|
||||
- `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)
|
||||
- Added option table to thread.hold
|
||||
| Option | Description |
|
||||
---|---
|
||||
| interval | Time between each poll |
|
||||
| cycles | Number of cycles 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
|
||||
- `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
|
||||
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
|
||||
for v,i in pairs(multi.PausedObjects) do
|
||||
for v,i in pairs(self.PausedObjects) do
|
||||
local name = v.Name or ""
|
||||
if name~="" then
|
||||
name = " <"..name..">"
|
||||
@ -1007,6 +1007,10 @@ function thread.hold(n,opt)
|
||||
dRef[2] = opt.sleep
|
||||
dRef[3] = n or dFunc
|
||||
return coroutine.yield(dRef)
|
||||
elseif opt.skip then
|
||||
dRef[1] = "_skip_"
|
||||
dRef[2] = opt.skip or 1
|
||||
return coroutine.yield(dRef)
|
||||
end
|
||||
end
|
||||
if type(n) == "number" then
|
||||
@ -1126,7 +1130,17 @@ local function cleanReturns(...)
|
||||
return unpack(returns,1,ind)
|
||||
end
|
||||
function thread:newFunction(func,holdme)
|
||||
return function(...)
|
||||
local tfunc = {}
|
||||
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)
|
||||
if thread.isThread() and not (no) then
|
||||
@ -1147,6 +1161,19 @@ function thread:newFunction(func,holdme)
|
||||
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
|
||||
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,...)
|
||||
t.OnDeath(function(self,status,...) rets = {...} end)
|
||||
t.OnError(function(self,e) err = e end)
|
||||
@ -1158,11 +1185,13 @@ function thread:newFunction(func,holdme)
|
||||
wait = wait,
|
||||
connect = function(f)
|
||||
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
|
||||
}
|
||||
return temp
|
||||
end
|
||||
setmetatable(tfunc,tfunc)
|
||||
return tfunc
|
||||
end
|
||||
-- A cross version way to set enviroments, not the same as fenv though
|
||||
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()
|
||||
--GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
||||
|
||||
|
||||
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
|
||||
test = thread:newFunction(function(a,b)
|
||||
thread.sleep(1)
|
||||
a = a + 1
|
||||
print("Thread Test: ".. multi.getCurrentProcess().Name)
|
||||
if a == 10 then
|
||||
sandbox.Stop()
|
||||
end
|
||||
end
|
||||
end).OnError(function(...)
|
||||
print(...)
|
||||
return a,b
|
||||
end)
|
||||
multi:newThread("Test Thread",function()
|
||||
while true do
|
||||
thread.sleep(1)
|
||||
print("Thread Test: ".. multi.getCurrentProcess().Name)
|
||||
end
|
||||
end).OnError(function(...)
|
||||
print(test(1,2).connect(function(...)
|
||||
print(...)
|
||||
end)
|
||||
end))
|
||||
test:Pause()
|
||||
print(test(1,2).connect(function(...)
|
||||
print(...)
|
||||
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()
|
||||
Loading…
x
Reference in New Issue
Block a user