diff --git a/README.md b/README.md index dbec4df..48b44c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# Multi Version: 16.0.1 - Bug fix - +# Multi Version: 16.1.0 - +**Key Changes** +- Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it! My multitasking library for lua. It is a pure lua binding, with exceptions of the integrations. diff --git a/docs/changes.md b/docs/changes.md index 2b2a6d6..ebaacb0 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,7 +1,8 @@ # Changelog Table of contents --- -[Update 16.0.1 - Bug fix](#update-1531---bug-fix)
+[Update 16.1.0 - TBA](#update-1610---tba)
+[Update 16.0.1 - Bug fix](#update-1601---bug-fix)
[Update 16.0.0 - Connecting the dots](#update-1600---getting-the-priorities-straight)
[Update 15.3.1 - Bug fix](#update-1531---bug-fix)
[Update 15.3.0 - A world of connections](#update-1530---a-world-of-connections)
@@ -59,6 +60,57 @@ Table of contents [Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)
[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different) +# Update 16.1.0 - TBA +Added +--- +- `multi.hasType(typ)` returns true if a type has been registered +- `multi.isMultiObj(obj)` returns true if the object is a multi object +- `multi.forwardConnection(src, dest)` forwards events from one connection to another connection. Doesn't modify anything and both connections are triggered when src is Fired, but not when dest is fired. +- `multi.isTimeout(res)` returns true if the response it gets is a timeout type or a string equal to `multi.TIMEOUT`'s value +- `multi:newTimeout(seconds)` returns a connection that will trigger after a certain amount of time. See example below: +```lua +local multi, thread = require("multi"):init() + +data = multi:newConnection() + +-- This alarm takes too long... We will timeout +multi:newAlarm(4):OnRing(function() + sitedata:Fire({Type="request"},"data is tasty") +end) + +multi:newThread(function() + res, data = thread.hold(data + multi:newTimeout(3)) + if multi.isTimeout(res) then + print("We timed out!") + else + print("We got the data:", data) + end + os.exit() +end) + +multi:mainloop() +``` +- `connection % function` can now modify the arguments of a connection. See above example modified below +```lua +local multi, thread = require("multi"):init() + +local data = multi:newAlarm(1).OnRing % function() return {Type="request"}, "data is tasty" end + +multi:newThread(function() + res, data = thread.hold(data + multi:newTimeout(3)) + if multi.isTimeout(res) then + print("We timed out!") + else + print("We got the data:", data) + end + os.exit() +end) + +multi:mainloop() +``` + +If the alarm takes longer the the timeout: `We timed out!` If the alarm is shorter: `We got the data: data is tasty` + # Update 16.0.1 - Bug fix Fixed --- diff --git a/init.lua b/init.lua index 9543ce5..d23e527 100644 --- a/init.lua +++ b/init.lua @@ -76,17 +76,23 @@ end local types = {} function multi.registerType(typ, p) - if multi[typ:upper():gsub("_","")] then return typ end - multi[typ:upper():gsub("_","")] = typ + if multi["$"..typ:upper():gsub("_","")] then return typ end + multi["$"..typ:upper():gsub("_","")] = typ table.insert(types, {typ, p or typ}) return typ end +function multi.hasType(typ) + if multi["$"..typ:upper():gsub("_","")] then + return multi["$"..typ:upper():gsub("_","")] + end +end + function multi.getTypes() return types end -multi.Version = "16.0.1" +multi.Version = "16.1.0" multi.Name = "root" multi.NIL = {Type="NIL"} local NIL = multi.NIL @@ -95,7 +101,7 @@ multi.Children = {} multi.Active = true multi.Type = multi.registerType("rootprocess") multi.LinkedPath = multi -multi.TIMEOUT = "TIMEOUT" +multi.TIMEOUT = multi.registerType("TIMEOUT", "timeouts") multi.TID = 0 multi.defaultSettings = {} @@ -185,9 +191,29 @@ function multi.randomString(n) return str end +function multi.isMulitObj(obj) + if type(obj)=="table" then + if obj.Type ~= nil then + return multi.hasType(obj.Type) ~= nil + end + end + return false +end + +function multi.forwardConnection(src, dest) + if multi.isMulitObj(src) and multi.isMulitObj(dest) then + src(function(...) + dest:Fire(...) + end) + else + multi.error("Cannot forward non-connection objects") + end +end + local optimization_stats = {} local ignoreconn = true local empty_func = function() end + function multi:newConnection(protect,func,kill) local processor = self local c={} @@ -221,6 +247,7 @@ function multi:newConnection(protect,func,kill) for i = #conns, 1, -1 do obj.rawadd = true obj(conns[i]) + obj.rawadd = false end return obj end, @@ -230,6 +257,22 @@ function multi:newConnection(protect,func,kill) obj2(function(...) cn:Fire(obj1(...)) end) + elseif type(obj1) == "table" and type(obj2) == "function" then + local conns = obj1:Bind({}) + for i = 1,#conns do + obj1(function(...) + conns[i](obj2(...)) + end) + end + obj1.__connectionAdded = function(conn, func) + obj1:Unconnect(conn) + obj1.rawadd = true + obj1:Connect(function(...) + func(obj2(...)) + end) + obj1.rawadd = false + end + return obj1 else error("Invalid mod!", type(obj1), type(obj2),"Expected function, connection(table)") end @@ -277,6 +320,7 @@ function multi:newConnection(protect,func,kill) end end) end + return obj1 elseif type(obj1) == "table" and type(obj2) == "table" then -- else @@ -492,6 +536,10 @@ function multi:newConnection(protect,func,kill) return temp end + function c:Get() + return fast + end + function c:Remove() local temp = fast fast={} @@ -702,6 +750,12 @@ function multi:newBase(ins) return c end +function multi:newTimeout(timeout) + local c={} + c.Type = multi.registerType(multi.TIMEOUT, "timeouts") + return function(self) self:Destroy() return c end % self:newAlarm(timeout).OnRing +end + function multi:newTimer() local c={} c.Type=multi.registerType("timer", "timers") @@ -2228,6 +2282,13 @@ end -- UTILS -------- +function multi.isTimeout(res) + if type(res) == "table" then + return res.Type == multi.TIMEOUT + end + return res == multi.TIMEOUT +end + function table.merge(t1, t2) for k,v in pairs(t2) do if type(v) == 'table' then diff --git a/integration/stateManager/init.lua b/integration/stateManager/init.lua new file mode 100644 index 0000000..2f9e653 --- /dev/null +++ b/integration/stateManager/init.lua @@ -0,0 +1 @@ +-- Allows the creation of states \ No newline at end of file diff --git a/tests/test.lua b/tests/test.lua deleted file mode 100644 index d5056db..0000000 --- a/tests/test.lua +++ /dev/null @@ -1,298 +0,0 @@ -package.path = "../?/init.lua;../?.lua;"..package.path -multi, thread = require("multi"):init{print=true,warn=true,debugging=true} --- for i,v in pairs(thread) do --- print(i,v) --- end - --- require("multi.integration.priorityManager") - --- multi.debugging.OnObjectCreated(function(obj, process) --- multi.print("Created:", obj.Type, "in", process.Type, process:getFullName()) --- end) - --- multi.debugging.OnObjectDestroyed(function(obj, process) --- multi.print("Destroyed:", obj.Type, "in", process.Type, process:getFullName()) --- end) - - --- test = multi:newProcessor("Test") --- test:setPriorityScheme(multi.priorityScheme.TimeBased) - --- test:newUpdater(10000000):OnUpdate(function() --- print("Print is slowish") --- end) - --- print("Running...") - --- local conn1, conn2 = multi:newConnection(), multi:newConnection() --- conn3 = conn1 + conn2 - --- conn1(function() --- print("Hi 1") --- end) - --- conn2(function() --- print("Hi 2") --- end) - --- conn3(function() --- print("Hi 3") --- end) - --- function test(a,b,c) --- print("I run before all and control if execution should continue!") --- return a>b --- end - --- conn4 = test .. conn1 - --- conn5 = conn2 .. function() print("I run after it all!") end - --- conn4:Fire(3,2,3) --- -- This second one won't trigger the Hi's --- conn4:Fire(1,2,3) - --- conn5(function() --- print("Test 1") --- end) - --- conn5(function() --- print("Test 2") --- end) - --- conn5(function() --- print("Test 3") --- end) - --- conn5:Fire() - - - - --- multi.print("Testing thread:newProcessor()") - --- proc = thread:newProcessor("Test") - --- proc:newLoop(function() --- multi.print("Running...") --- thread.sleep(1) --- end) - --- proc:newThread(function() --- while true do --- multi.warn("Everything is a thread in this proc!") --- thread.sleep(1) --- end --- end) - --- proc:newAlarm(5):OnRing(function(a) --- multi.print(";) Goodbye") --- a:Destroy() --- end) - --- local func = thread:newFunction(function() --- thread.sleep(4) --- print("Hello!") --- end) - --- multi:newTLoop(func, 1) - --- multi:mainloop() - --- multi:setTaskDelay(.05) --- multi:newTask(function() --- for i = 1, 10 do --- multi:newTask(function() --- print("Task "..i) --- end) --- end --- end) - --- local conn = multi:newConnection() --- conn(function() print("Test 1") end) --- conn(function() print("Test 2") end) --- conn(function() print("Test 3") end) --- conn(function() print("Test 4") end) - --- print("Fire 1") --- conn:Fire() --- conn = -conn --- print("Fire 2") --- conn:Fire() - --- print(#conn) - --- thread:newThread("Test thread", function() --- print("Starting thread!") --- thread.defer(function() -- Runs when the thread finishes execution --- print("Clean up time!") --- end) --- --[[ --- Do lot's of stuff --- ]] --- thread.sleep(3) --- end) - -multi:mainloop() - --- local conn1, conn2, conn3 = multi:newConnection(nil,nil,true), multi:newConnection(), multi:newConnection() - --- local link = conn1(function() --- print("Conn1, first") --- end) - --- local link2 = conn1(function() --- print("Conn1, second") --- end) - --- local link3 = conn1(function() --- print("Conn1, third") --- end) - --- local link4 = conn2(function() --- print("Conn2, first") --- end) - --- local link5 = conn2(function() --- print("Conn2, second") --- end) - --- local link6 = conn2(function() --- print("Conn2, third") --- end) - --- print("Links 1-6",link,link2,link3,link4,link5,link6) --- conn1:Lock(link) --- print("All conns\n-------------") --- conn1:Fire() --- conn2:Fire() - --- conn1:Unlock(link) - --- conn1:Unconnect(link3) --- conn2:Unconnect(link6) --- print("All conns Edit\n---------------------") --- conn1:Fire() --- conn2:Fire() - --- thread:newThread(function() --- print("Awaiting status") --- thread.hold(conn1 + (conn2 * conn3)) --- print("Conn or Conn2 and Conn3") --- end) - --- multi:newAlarm(1):OnRing(function() --- print("Conn") --- conn1:Fire() --- end) --- multi:newAlarm(2):OnRing(function() --- print("Conn2") --- conn2:Fire() --- end) --- multi:newAlarm(3):OnRing(function() --- print("Conn3") --- conn3:Fire() --- os.exit() --- end) - - --- local conn = multi:newSystemThreadedConnection("conn"):init() - --- multi:newSystemThread("Thread_Test_1", function() --- local multi, thread = require("multi"):init() --- local conn = GLOBAL["conn"]:init() --- local console = THREAD.getConsole() --- conn(function(a,b,c) --- console.print(THREAD:getName().." was triggered!",a,b,c) --- end) --- multi:mainloop() --- end) - --- multi:newSystemThread("Thread_Test_2", function() --- local multi, thread = require("multi"):init() --- local conn = GLOBAL["conn"]:init() --- local console = THREAD.getConsole() --- conn(function(a,b,c) --- console.print(THREAD:getName().." was triggered!",a,b,c) --- end) --- multi:newAlarm(2):OnRing(function() --- console.print("Fire 2!!!") --- conn:Fire(4,5,6) --- THREAD.kill() --- end) - --- multi:mainloop() --- end) --- local console = THREAD.getConsole() --- conn(function(a,b,c) --- console.print("Mainloop conn got triggered!",a,b,c) --- end) - --- alarm = multi:newAlarm(1) --- alarm:OnRing(function() --- console.print("Fire 1!!!") --- conn:Fire(1,2,3) --- end) - --- alarm = multi:newAlarm(3):OnRing(function() --- multi:newSystemThread("Thread_Test_3",function() --- local multi, thread = require("multi"):init() --- local conn = GLOBAL["conn"]:init() --- local console = THREAD.getConsole() --- conn(function(a,b,c) --- console.print(THREAD:getName().." was triggered!",a,b,c) --- end) --- multi:newAlarm(4):OnRing(function() --- console.print("Fire 3!!!") --- conn:Fire(7,8,9) --- end) --- multi:mainloop() --- end) --- end) - --- multi:newSystemThread("Thread_Test_4",function() --- local multi, thread = require("multi"):init() --- local conn = GLOBAL["conn"]:init() --- local conn2 = multi:newConnection() --- local console = THREAD.getConsole() --- multi:newAlarm(2):OnRing(function() --- conn2:Fire() --- end) --- multi:newThread(function() --- console.print("Conn Test!") --- thread.hold(conn + conn2) --- console.print("It held!") --- end) --- multi:mainloop() --- end) - --- multi:mainloop() ---[[ - newFunction function: 0x00fad170 - waitFor function: 0x00fad0c8 - request function: 0x00fa4f10 - newThread function: 0x00fad1b8 - --__threads table: 0x00fa4dc8 - defer function: 0x00fa4f98 - isThread function: 0x00facd40 - holdFor function: 0x00fa5058 - yield function: 0x00faccf8 - hold function: 0x00fa51a0 - chain function: 0x00fa5180 - __CORES 32 - newISOThread function: 0x00fad250 - newFunctionBase function: 0x00fad128 - requests table: 0x00fa4e68 - newProcessor function: 0x00fad190 - exec function: 0x00fa50e8 - pushStatus function: 0x00fad108 - kill function: 0x00faccd8 - get function: 0x00fad0a8 - set function: 0x00fad088 - getCores function: 0x00facd60 - skip function: 0x00faccb0 - --_Requests function: 0x00fa50a0 - getRunningThread function: 0x00fa4fb8 - holdWithin function: 0x00facc80 - sleep function: 0x00fa4df0 -]] \ No newline at end of file