-
multi v15.2.x Stable
released this
2022-04-19 18:45:14 -04:00 | 0 commits to v15.2.0 since this releaseUpdate 15.2.1 - Bug Fix
- Fixed issue
Update 15.2.0 - Upgrade Complete
Full Update Showcase
package.path = "./?/init.lua;"..package.path multi, thread = require("multi"):init{print=true} GLOBAL, THREAD = require("multi.integration.threading"):init() -- Using a system thread, but both system and local threads support this! -- Don't worry if you don't have lanes or love2d. PesudoThreading will kick in to emulate the threading features if you do not have access to system threading. func = THREAD:newFunction(function(count) print("Starting Status test: ",count) local a = 0 while true do a = a + 1 THREAD.sleep(.1) -- Push the status from the currently running threaded function to the main thread THREAD.pushStatus(a,count) if a == count then break end end return "Done" end) thread:newThread("test",function() local ret = func(10) ret.OnStatus(function(part,whole) print("Ret1: ",math.ceil((part/whole)*1000)/10 .."%") end) print("TEST",func(5).wait()) -- The results from the OnReturn connection is passed by thread.hold print("Status:",thread.hold(ret.OnReturn)) print("Function Done!") end).OnError(function(...) print("Error:",...) end) local ret = func(10) local ret2 = func(15) local ret3 = func(20) local s1,s2,s3 = 0,0,0 ret.OnError(function(...) print("Error:",...) end) ret2.OnError(function(...) print("Error:",...) end) ret3.OnError(function(...) print("Error:",...) end) ret.OnStatus(function(part,whole) s1 = math.ceil((part/whole)*1000)/10 print(s1) end) ret2.OnStatus(function(part,whole) s2 = math.ceil((part/whole)*1000)/10 print(s2) end) ret3.OnStatus(function(part,whole) s3 = math.ceil((part/whole)*1000)/10 print(s3) end) loop = multi:newTLoop() function loop:testing() print("testing haha") end loop:Set(1) t = loop:OnLoop(function() print("Looping...") end):testing() local proc = multi:newProcessor("Test") local proc2 = multi:newProcessor("Test2") local proc3 = proc2:newProcessor("Test3") proc.Start() proc2.Start() proc3.Start() proc:newThread("TestThread_1",function() while true do thread.sleep(1) end end) proc:newThread("TestThread_2",function() while true do thread.sleep(1) end end) proc2:newThread("TestThread_3",function() while true do thread.sleep(1) end end) thread:newThread(function() thread.sleep(1) local tasks = multi:getStats() for i,v in pairs(tasks) do print("Process: " ..i.. "\n\tTasks:") for ii,vv in pairs(v.tasks) do print("\t\t"..vv:getName()) end print("\tThreads:") for ii,vv in pairs(v.threads) do print("\t\t"..vv:getName()) end end thread.sleep(10) -- Wait 10 seconds then kill the process! os.exit() end) multi:mainloop()Added:
-
multi:getStats()- Returns a structured table where you can access data on processors there tasks and threads:
-- Upon calling multi:getStats() the table below is returned get_Stats_Table { proc_1 -- table proc_2 -- table ... proc_n -- table } proc_Table { tasks = {alarms,steps,loops,etc} -- All multi objects threads = {thread_1,thread_2,thread_3,etc} -- Thread objects } -- Refer to the objects documentation to see how you can interact with them - Reference the Full update showcase for the method in action
- Returns a structured table where you can access data on processors there tasks and threads:
-
multi:newProcessor(name, nothread)- If no thread is true auto sets the processor as Active, so proc.run() will start without the need for proc.Start()
-
multi:getProcessors()- Returns a list of all processors
-
multi:getName()- Returns the name of a processor
-
multi:getFullName()- Returns the fullname/entire process tree of a process
-
Processors can be attached to processors
-
multi:getTasks()- Returns a list of all non thread based objects (loops, alarms, steps, etc)
-
multi:getThreads()- Returns a list of all threads on a process
-
multi:newProcessor(name, nothread).run()- New function run to the processor object to
-
multi:newProcessor(name, nothread):newFunction(func, holdme)- Acts like thread:newFunction(), but binds the execution of that threaded function to the processor
-
multi:newTLoop()member functionsTLoop:Set(set)- Sets the time to wait for the TLoop
-
multi:newStep()member functionsStep:Count(count)- Sets the amount a step should count by
-
multi:newTStep()member functionsTStep:Set(set)- Sets the time to wait for the TStep
Changed:
-
thread.hold(connectionObj)now passes the returns of that connection tothread.hold()! See Exampe below:multi, thread = require("multi"):init() func = thread:newFunction(function(count) local a = 0 while true do a = a + 1 thread.sleep(.1) thread.pushStatus(a,count) if a == count then break end end return "Done", 1, 2, 3 end) thread:newThread("test",function() local ret = func(10) ret.OnStatus(function(part,whole) print("Ret1: ",math.ceil((part/whole)*1000)/10 .."%") end) print("Status:",thread.hold(ret.OnReturn)) print("Function Done!") os.exit() end).OnError(function(...) print("Error:",...) end) multi:mainloop()Output:
Ret1: 10% Ret1: 20% Ret1: 30% Ret1: 40% Ret1: 50% Ret1: 60% Ret1: 70% Ret1: 80% Ret1: 90% Ret1: 100% Status: Done 1 2 3 nil nil nil nil nil nil nil nil nil nil nil nil Function Done! -
Modified how threads are handled internally. This changes makes it so threads "regardless of amount" should not impact performance. What you do in the threads might. This change was made by internally only processing one thread per step per processor. If you have 10 processors that are all active expect one step to process 10 threads. However if one processor has 10 threads each step will only process one thread. Simply put each addition of a thread shouldn't impact performance as it did before.
-
Moved
multi:newThread(...)into the thread interface (thread:newThread(...)), code usingmulti:newThread(...)will still work. Also usingprocess:newThread(...)binds the thread to the process, meaning if the process the thread is bound to is paused so is the thread. -
multi:mainloop(
settings)/multi:uManager(settings) no longer takes a settings argument, that has been moved to multi:init(settings)Setting Description print When set to true parts of the library will print out updates otherwise no internal printing will be done priority When set to true, the library will prioritize different objects based on their priority -
multi:newProcessor(name,nothread)The new argument allows you to tell the system you won't be using the Start() and Stop() functions, rather you will handle the process yourself. Using the proc.run() function. This function needs to be called to pump the events.- Processors now also use lManager instead of uManager.
-
multi.hold(n,opt)now supports an option table like thread.hold does. -
Connection Objects now pass on the parent object if created on a multiobj. This was to allow chaining to work properly with the new update
multi,thread = require("multi"):init() loop = multi:newTLoop() function loop:testing() print("testing haha") end loop:Set(1) t = loop:OnLoop(function() print("Looping...") end):testing() multi:mainloop() --[[Returns as expected: testing haha Looping... Looping... Looping... ... Looping... Looping... Looping... ]]While chaining on the OnSomeEventMethod() wasn't really a used feature, I still wanted to keep it just incase someone was relying on this working. And it does have it uses
-
All Multi Objects now use Connection objects
multiobj:OnSomeEvent(func)ormultiobj.OnSomeEvent(func) -
Connection Objects no longer Fire with syntax sugar when attached to an object:
multiobj:OnSomeEvent(...)No longer triggers the Fire event. As part of the update to make all objects use connections internally this little used feature had to be scrapped! -
multi:newTStep now derives it's functionality from multi:newStep (Cut's down on code length a bit)
Removed:
-
multi:getTasksDetails()Remade completely and now calledmulti:getStats() -
multi:getError()Removed when setting protect was removed -
multi:FreeMainEvent()The new changes with connections make's this function unnecessary -
multi:OnMainConnect(func)See above -
multi:connectFinal(func)See above -
multi:lightloop()Cleaned up the mainloop/uManager method, actually faster than lightloop (Which should have been called liteloop) -
multi:threadloop()See above for reasons -
multi setting: protectThis added extra complexity to the mainloop and not much benefit. If you feel a function will error use pcall yourself. This saves a decent amount of cycles, about 6.25% increase in performance. -
multi:GetParentProcess()usemulti.getCurrentProcess()instead -
priority scheme 2, 3 and auto-priority have been removed! Only priority scheme 1 actually performed in a reasonable fashion so that one remained.
-
multi:newFunction(func)thread:newFunction(func)Has many more features and replaces what multi:newFunction did
-
multi.holdFor()Now that multi.hold takes the option table that thread.hold has this feature can be emulated using that. -
Calling Fire on a connection no longer returns anything! Now that internal features use connections, I noticed how slow connections are and have increased their speed quite a bit. From 50,000 Steps per seconds to almost 7 Million. All other features should work just fine. Only returning values has been removed
Fixed:
-
Issue with Lanes crashing the lua state. Issue seemed to be related to my filesystem, since remounting the drive caused the issue to stop. (Windows)
-
Issue where System threaded functions not being up to date with threaded functions
-
Issue where gettasksdetails() would try to process a destroyed object causing it to crash
-
Issue with multi.hold() not pumping the mainloop and only the scheduler
ToDo:
- Work on network parallelism
Downloads