From 76dbf26793b991706503e39eea47a99ca3277912 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Sun, 26 Aug 2018 00:44:29 -0400 Subject: [PATCH] Fixed some bugs and added a minor feature --- .gitignore | 6 +++++ changes.md | 35 +++++++++++++++++++++++++++++- multi/init.lua | 20 +++++++++++++---- multi/integration/lanesManager.lua | 2 +- test.lua | 17 +++++++++++++++ 5 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 test.lua diff --git a/.gitignore b/.gitignore index ed6837d..2d543a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,8 @@ test2.lua +*.mp3 +*.exe +lanestestclient.lua +lanestest.lua +sample-node.lua +sample-master.lua diff --git a/changes.md b/changes.md index 071b970..6fa23c0 100644 --- a/changes.md +++ b/changes.md @@ -1,8 +1,41 @@ #Changes [TOC] +Update 12.1.0 +------------- +Fixed: +- bug causing arguments when spawning a new thread not going through + +Changed: +- thread.hold() now returns the arguments that were pass by the event function +- event objexts now contain a copy of what returns were made by the function that called it in a table called returns that exist inside of the object + +```lua +package.path="?/init.lua;?.lua;"..package.path +multi = require("multi") +local a = 0 +multi:newThread("test",function() + print("lets go") + b,c = thread.hold(function() -- This now returns what was managed here + return b,"We did it!" + end) + print(b,c) +end) +multi:newTLoop(function() + a=a+1 + if a == 5 then + b = "Hello" + end +end,1) +multi:mainloop() +``` +**Note:** Only if the first return is non-nil/false will any other returns be passed! So while variable b above is nil the string "We did it!" will not be passed. Also while this seems simple enough to get working, I had to modify a bit on how the scheduler worked to add such a simple feature. Quite a bit is going on behind the scenes which made this a bit tricky to implement, but not hard. Just needed a bit of tinkering. Plus event objects have not been edited since the creation of the EventManager. They have remained mostly the same since 2011 + +# Going forward: +Contunue to make small changes as I come about them. This change was inspired when working of the net library. I was addind simple binary file support over tcp, and needed to pass the data from the socket when the requested amount has been recieved. While upvalues did work, i felt returning data was cleaner and added this feature. + Update: 12.0.0 Big update (Lots of additions some changes) ------------------------ -**Note:** ~~After doing some testing, I have noticed that using multi-objects are slightly, quite a bit, faster than using (coroutines)multi:newthread(). Only create a thread if there is no other possibility! System threads are different and will improve performance if you know what you are doing. Using a (coroutine)thread as a loop with a timer is slower than using a TLoop! If you do not need the holding features I strongly recommend that you use the multi-objects. This could be due to the scheduler that I am using, and I am looking into improving the performance of the scheduler for (coroutine)threads. This is still a work in progress so expect things to only get better as time passes!~~ This was the reason threadloop was added. It binds the thread scheduler into the mainloop allowing threads to run much faster than before. Also the use of locals is now possible since I am not dealing with seperate objects. And finally reduced function overhead helps keep the threads running better. +**Note:** ~~After doing some testing, I have noticed that using multi-objects are slightly, quite a bit, faster than using (coroutines)multi:newthread(). Only create a thread if there is no other possibility! System threads are different and will improve performance if you know what you are doing. Using a (coroutine)thread as a loop with a timer is slower than using a TLoop! If you do not need the holding features I strongly recommend that you use the multi-objects. This could be due to the scheduler that I am using, and I am looking into improving the performance of the scheduler for (coroutine)threads. This is still a work in progress so expect things to only get better as time passes!~~ This was the reason threadloop was added. It binds the thread scheduler into the mainloop allowing threads to run much faster than before. Also the use of locals is now possible since I am not dealing with seperate objects. And finally, reduced function overhead help keeps the threads running better. #Added: - `nGLOBAL = require("multi.integration.networkManager").init()` diff --git a/multi/init.lua b/multi/init.lua index f2211fd..cdd2dfb 100644 --- a/multi/init.lua +++ b/multi/init.lua @@ -1025,8 +1025,10 @@ function multi:newEvent(task) c.Type='event' c.Task=task or function() end function c:Act() - if self.Task(self) then + local t = {self.Task(self)} + if t[1] then self:Pause() + self.returns = t for _E=1,#self.func do self.func[_E](self) end @@ -1456,7 +1458,7 @@ function thread.sleep(n) coroutine.yield({"_sleep_",n or 0}) end function thread.hold(n) - coroutine.yield({"_hold_",n or function() return true end}) + return coroutine.yield({"_hold_",n or function() return true end}) end function thread.skip(n) coroutine.yield({"_skip_",n or 0}) @@ -1567,9 +1569,17 @@ multi.scheduler:OnLoop(function(self) if self.Threads[i].firstRunDone==false then self.Threads[i].firstRunDone=true self.Threads[i].timer:Start() - _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) + if unpack(self.Threads[i].returns or {}) then + _,ret=coroutine.resume(self.Threads[i].thread,unpack(self.Threads[i].returns)) + else + _,ret=coroutine.resume(self.Threads[i].thread,self.Threads[i].ref) + end else - _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) + if unpack(self.Threads[i].returns or {}) then + _,ret=coroutine.resume(self.Threads[i].thread,unpack(self.Threads[i].returns)) + else + _,ret=coroutine.resume(self.Threads[i].thread,self.Globals) + end end if _==false then self.Parent.OnError:Fire(self.Threads[i],"Error in thread: <"..self.Threads[i].Name.."> "..ret) @@ -1598,9 +1608,11 @@ multi.scheduler:OnLoop(function(self) self.Threads[i].timer:Reset() self.Threads[i].sleep=math.huge local event=multi:newEvent(ret[2]) + event.returns = nil event.link=self.Threads[i] event:OnEvent(function(evnt) evnt.link.sleep=0 + evnt.link.returns = evnt.returns end) elseif ret.Name then self.Globals[ret.Name]=ret.Value diff --git a/multi/integration/lanesManager.lua b/multi/integration/lanesManager.lua index 66cb92c..68d1b47 100644 --- a/multi/integration/lanesManager.lua +++ b/multi/integration/lanesManager.lua @@ -117,7 +117,7 @@ function multi:newSystemThread(name,func,...) local THREAD_NAME=name local function func2(...) _G["THREAD_NAME"]=THREAD_NAME - func() + func(...) end c.thread=lanes.gen("*", func2)(...) function c:kill() diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..a0843af --- /dev/null +++ b/test.lua @@ -0,0 +1,17 @@ +package.path="?/init.lua;?.lua;"..package.path +multi = require("multi") +local a = 0 +multi:newThread("test",function() + print("lets go") + b,c = thread.hold(function() + return b,"We did it!" + end) + print(b,c) +end) +multi:newTLoop(function() + a=a+1 + if a == 5 then + b = "Hello" + end +end,1) +multi:mainloop()