Meta Mastery

This commit is contained in:
Ryan Ward 2020-02-03 14:00:47 -05:00
parent a5b71985a6
commit 91abd762cb
3 changed files with 101 additions and 7 deletions

View File

@ -2,6 +2,76 @@
[TOC] [TOC]
Update 14.1.0 Bug Fixes and a change Update 14.1.0 Bug Fixes and a change
------------- -------------
# Full Update Example - I plan on doing full example for each future update. Every feature added gets touched and I litter it with comments.
```lua
package.path="?/init.lua;?.lua;"..package.path
multi,thread = require("multi"):init()
multi.OnLoad(function()
print("Code Loaded!") -- Connect to the load event
end)
t = os.clock()
co = 0
multi.OnExit(function(n)
print("Code Exited: ".. os.clock()-t .." Count: ".. co) -- Lets print when things have ended
end)
test = thread:newFunction(function()
thread.sleep(1) -- Internally this throws a yield call which sends to the scheduler to sleep 1 second for this thread!
return 1,math.random(2,100)
end)
multi:newThread(function()
while true do
thread.skip() -- Even though we have a few metamethods "yielding" I used this as an example of things still happening and counting. It connects to the Code Exited event later on.
co = co + 1
end
end)
-- We can get around the yielding across metamethods by using a threadedFunction
-- For Example
example = {}
setmetatable(example,{
__newindex = function(t,k,v) -- Using a threaded function inside of a normal function
print("Inside metamethod",t,k,v)
local a,b = test().wait() -- This function holds the code and "yields" see comment inside the test function!
-- we should see a 1 seconde delay since the function sleeps for a second than returns
print("We did it!",a,b)
rawset(t,k,v)
-- This means by using a threaded function we can get around the yielding across metamethods.
-- This is useful if you aren't using luajit, or if you using lua in an enviroment that is on version 5.1
-- There is a gotcha however, if using code that was meant to work with another coroutine based scheduler this may not work
end,
__index = thread:newFunction(function(t,k,v) -- Using a threaded function as the metamethod
-- This works by returning a table with a __call metamethod. Will this work? Will lua detect this as a function or a table?
thread.sleep(1)
return "You got a string"
end,true) -- Tell the code to force a wait and to identify as a function. We need to do this for metamethods
-- If we don't pass true this is a table with a __call metamethod
})
example["test"] = "We set a variable!"
print(example["test"])
print(example.hi)
-- When not in a threaded enviroment at root level we need to tell the code that we are waiting! Alternitavely after the function argument we can pass true to force a wait
c,d = test().wait()
print(c,d)
a,b = 6,7
multi:newThread(function()
-- a,b = test().wait() -- Will modify Global
-- when wait is used the special metamethod routine is not triggered and variables are set as normal
a,b = test() -- Will modify GLocal
-- the threaded function test triggers a special routine within the metamethod that alters the thread's enviroment instead of the global enviroment.
print("Waited:",a,b)
--This returns instantly even though the function isn't done!
test().connect(function(a,b)
print("Connected:",a,b)
os.exit()
end)
-- This waits for the returns since we are demanding them
end)
multi:mainloop()
```
# Changed:
- thread:newFunction(func,holdme) -- Added an argument holdme to always force the threaded funcion to wait. Meaning you don't need to tell it to func().wait() or func().connect()
- multi:newConnection(protect,callback,kill) -- Added the kill argument. Makes connections work sort of like a stack. Pop off the connections as they get called. So a one time connection handler.
- I'm not sure callback has been documented in any form. callback gets called each and everytime conn:Fire() gets called! As well as being triggered for each connfunc that is part of the connection.
# Added: # Added:
- multi.OnLoad(func) -- A special connection that allows you to connect to the an event that triggers when the multi engine starts! This is slightly different from multi.PreLoad(func) Which connects before any variables have been set up in the multi table, before any settings are cemented into the core. In most cases they will operate exactly the same. This is a feature that was created with module creators in mind. This way they can have code be loaded and managed before the main loop starts. - multi.OnLoad(func) -- A special connection that allows you to connect to the an event that triggers when the multi engine starts! This is slightly different from multi.PreLoad(func) Which connects before any variables have been set up in the multi table, before any settings are cemented into the core. In most cases they will operate exactly the same. This is a feature that was created with module creators in mind. This way they can have code be loaded and managed before the main loop starts.
- multi.OnExit(func) -- A special connection that allows you to connect onto the lua state closing event. - multi.OnExit(func) -- A special connection that allows you to connect onto the lua state closing event.

View File

@ -1476,9 +1476,8 @@ function multi.holdFor(n,func)
end end
end) end)
end end
function thread:newFunction(func) function thread:newFunction(func,holdme)
local c = {Type = "tfunc"} return function(self,...)
c.__call = function(self,...)
local rets, err 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
@ -1499,6 +1498,9 @@ function thread:newFunction(func)
local t = multi:newThread("TempThread",func,...) local t = multi: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)
if holdme then
return wait()
end
local temp = { local temp = {
isTFunc = true, isTFunc = true,
wait = wait, wait = wait,
@ -1509,8 +1511,6 @@ function thread:newFunction(func)
} }
return temp,temp,temp,temp,temp,temp,temp return temp,temp,temp,temp,temp,temp,temp
end end
setmetatable(c,c)
return c
end end
function thread.run(func) function thread.run(func)
local threaddata,t2,t3,t4,t5,t6 local threaddata,t2,t3,t4,t5,t6

View File

@ -9,7 +9,7 @@ multi.OnExit(function(n)
print("Code Exited: ".. os.clock()-t .." Count: ".. co) print("Code Exited: ".. os.clock()-t .." Count: ".. co)
end) end)
test = thread:newFunction(function() test = thread:newFunction(function()
thread.sleep(1) thread.sleep(1) -- Internally this throws a yield call which sends to the scheduler to sleep 1 second for this thread!
return 1,math.random(2,100) return 1,math.random(2,100)
end) end)
multi:newThread(function() multi:newThread(function()
@ -18,7 +18,31 @@ multi:newThread(function()
co = co + 1 co = co + 1
end end
end) end)
-- When not in a threaded enviroment at root level we need to tell the code that we are waiting! -- We can get around the yielding across metamethods by using a threadedFunction
-- For Example
example = {}
setmetatable(example,{
__newindex = function(t,k,v) -- Using a threaded function inside of a normal function
print("Inside metamethod",t,k,v)
local a,b = test().wait() -- This function holds the code and "yields" see comment inside the test function!
-- we should see a 1 seconde delay since the function sleeps for a second than returns
print("We did it!",a,b)
rawset(t,k,v)
-- This means by using a threaded function we can get around the yielding across metamethods.
-- This is useful if you aren't using luajit, or if you using lua in an enviroment that is on version 5.1
-- There is a gotcha however, if using code that was meant to work with another coroutine based scheduler this may not work
end,
__index = thread:newFunction(function(t,k,v) -- Using a threaded function as the metamethod
-- This works by returning a table with a __call metamethod. Will this work? Will lua detect this as a function or a table?
thread.sleep(1)
return "You got a string"
end,true) -- Tell the code to force a wait and to identify as a function. We need to do this for metamethods
-- If we don't pass true this is a table with a __call metamethod
})
example["test"] = "We set a variable!"
print(example["test"])
print(example.hi)
-- When not in a threaded enviroment at root level we need to tell the code that we are waiting! Alternitavely after the function argument we can pass true to force a wait
c,d = test().wait() c,d = test().wait()
print(c,d) print(c,d)
a,b = 6,7 a,b = 6,7