1.8.4 Update! #3

Merged
rayaman merged 6 commits from Testing into master 2017-07-03 14:01:10 -04:00
8 changed files with 126 additions and 51 deletions
Showing only changes of commit 03c91d84e3 - Show all commits

View File

@ -186,7 +186,7 @@
<p></p><h2 id="installing"><a name="installing" href="#installing"></a>INSTALLING</h2><pre><code data-origin="<pre><code>luarocks install multi <p></p><h2 id="installing"><a name="installing" href="#installing"></a>INSTALLING</h2><pre><code data-origin="<pre><code>luarocks install multi
</code></pre>">luarocks install multi </code></pre>">luarocks install multi
</code></pre><h2 id="discord"><a name="discord" href="#discord"></a>Discord</h2><p>For real-time assistance with my libraries! A place where you can ask questions and get help with any of my libraries. Also you can request features and stuff there as well.<br><br><a href="https://discord.gg/U8UspuA">https://discord.gg/U8UspuA</a><br></p><h2 id="planned-features/todo"><a name="planned-features/todo" href="#planned-features/todo"></a>Planned features/TODO</h2><ul> </code></pre><h2 id="discord"><a name="discord" href="#discord"></a>Discord</h2><p>For real-time assistance with my libraries! A place where you can ask questions and get help with any of my libraries. Also you can request features and stuff there as well.<br><br><a href="https://discord.gg/U8UspuA">https://discord.gg/U8UspuA</a><br></p><h2 id="planned-features/todo"><a name="planned-features/todo" href="#planned-features/todo"></a>Planned features/TODO</h2><ul>
<li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="0"> <del>Add system threads for love2d that works like the lanesManager (loveManager, slight differences).</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="1"> Improve performance of the library — It has increased a bit, but I feel I can get a little more out of it</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="2"> Improve coroutine based threading scheduling</li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="3"> <del>Add more features to support module creators</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="4"> <del>Make a framework for eaiser thread task distributing</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="5"> <del>Fix Error handling on threaded multi objects</del> Non threaded multiobjs will crash your program if they error though! Use multi:newThread() of multi:newSystemThread() if your code can error! Unless you use multi:protect() this however lowers performance!</li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="6"> <del>Add multi:OnError(function(obj,err))</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="7"> sThread.wrap(obj) <strong>May or may not be completed</strong> Theory: Allows interaction in one thread to affect it in another. The addition to threaded tables may make this possible!</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="8"> SystemThreaded Actors — After some tests i figured out a way to make this work… It will work slightly different though. This is due to the actor needing to be splittable…</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="9"> LoadBalancing for system threads (Once SystemThreaded Actors are done)</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="10"> Add more integrations</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="11"> Finish the wiki stuff. (11% done)</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="12"> Test for unknown bugs</li></ul><h2 id="known-bugs/issues"><a name="known-bugs/issues" href="#known-bugs/issues"></a>Known Bugs/Issues</h2><p>In regards to integrations, thread cancellation works slightly different for love2d and lanes. Within love2d I was unable to (To lazy to…) not use the multi library within the thread. A fix for this is to call <code>multi:Stop()</code> when you are done with your threaded code! This may change however if I find a way to work around this. In love2d in order to mimic the GLOBAL table I needed the library to constantly sync tha data… You can use the sThread.waitFor(varname), or sThread.hold(func) methods to sync the globals, to get the value instead of using GLOBAL and this could work. If you want to go this route I suggest setting multi.isRunning=true to prevent the auto runner from doing its thing! This will make the multi manager no longer function, but thats the point :P</p><h2 id="usage:"><a name="usage:" href="#usage:"></a>Usage:<br></h2><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Basic usage Alarms: Have been moved to the core of the library require(&quot;multi&quot;) would work as well <li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="0"> <del>Add system threads for love2d that works like the lanesManager (loveManager, slight differences).</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="1"> <del>Improve performance of the library</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="2"> Improve coroutine based threading scheduling</li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="3"> <del>Add more features to support module creators</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="4"> <del>Make a framework for eaiser thread task distributing</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="5"> <del>Fix Error handling on threaded multi objects</del> Non threaded multiobjs will crash your program if they error though! Use multi:newThread() of multi:newSystemThread() if your code can error! Unless you use multi:protect() this however lowers performance!</li><li style="list-style: none"><input type="checkbox" class="task-list-item" checked="" data-task-index="6"> <del>Add multi:OnError(function(obj,err))</del></li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="7"> sThread.wrap(obj) <strong>May or may not be completed</strong> Theory: Allows interaction in one thread to affect it in another. The addition to threaded tables may make this possible!</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="8"> SystemThreaded Actors — After some tests i figured out a way to make this work… It will work slightly different though. This is due to the actor needing to be splittable…</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="9"> LoadBalancing for system threads (Once SystemThreaded Actors are done)</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="10"> Add more integrations</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="11"> Finish the wiki stuff. (11% done)</li><li style="list-style: none"><input type="checkbox" class="task-list-item" data-task-index="12"> Test for unknown bugs</li></ul><h2 id="known-bugs/issues"><a name="known-bugs/issues" href="#known-bugs/issues"></a>Known Bugs/Issues</h2><p>In regards to integrations, thread cancellation works slightly different for love2d and lanes. Within love2d I was unable to (To lazy to…) not use the multi library within the thread. A fix for this is to call <code>multi:Stop()</code> when you are done with your threaded code! This may change however if I find a way to work around this. In love2d in order to mimic the GLOBAL table I needed the library to constantly sync tha data… You can use the sThread.waitFor(varname), or sThread.hold(func) methods to sync the globals, to get the value instead of using GLOBAL and this could work. If you want to go this route I suggest setting multi.isRunning=true to prevent the auto runner from doing its thing! This will make the multi manager no longer function, but thats the point :P</p><h2 id="usage:"><a name="usage:" href="#usage:"></a>Usage:<br></h2><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Basic usage Alarms: Have been moved to the core of the library require(&quot;multi&quot;) would work as well
require(&quot;multi&quot;) -- gets the entire library require(&quot;multi&quot;) -- gets the entire library
alarm=multi:newAlarm(3) -- in seconds can go to .001 uses the built in os.clock() alarm=multi:newAlarm(3) -- in seconds can go to .001 uses the built in os.clock()
alarm:OnRing(function(a) alarm:OnRing(function(a)
@ -203,7 +203,7 @@ alarm:OnRing(<span class="hljs-function"><span class="hljs-keyword">function</sp
<span class="hljs-keyword">end</span>) <span class="hljs-keyword">end</span>)
multi:mainloop() <span class="hljs-comment">-- the main loop of the program, multi:umanager() exists as well to allow integration in other loops Ex: love2d love.update function. More on this binding in the wiki!</span> multi:mainloop() <span class="hljs-comment">-- the main loop of the program, multi:umanager() exists as well to allow integration in other loops Ex: love2d love.update function. More on this binding in the wiki!</span>
</code></pre><p>The library is modular so you only need to require what you need to. Because of this, the global enviroment is altered<br></p><p>There are many useful objects that you can use<br><br>Check out the wiki for detailed usage, but here are the objects:<br></p><ul> </code></pre><p>The library is modular so you only need to require what you need to. Because of this, the global enviroment is altered<br></p><p>There are many useful objects that you can use<br><br>Check out the wiki for detailed usage, but here are the objects:<br></p><ul>
<li>Process#<br></li><li>Queuer#<br></li><li>Alarm<br></li><li>Loop<br></li><li>Event<br></li><li>Step<br></li><li>Range<br></li><li>TStep<br></li><li>TLoop<br></li><li>Condition<br></li><li>Connection<br></li><li>Timer<br></li><li>Updater<br></li><li>Thread*<br></li><li>Trigger<br></li><li>Task<br></li><li>Job<br></li><li>Function<br></li><li>Watcher<br><br>Note: <em>Both a process and queue act like the multi namespace, but allows for some cool things. Because they use the other objects an example on them will be done last</em><br><br>*Uses the built in coroutine features of lua, these have an interesting interaction with the other means of multi-tasking<br><br>Triggers are kind of useless after the creation of the Connection<br><br>Watchers have no real purpose as well I made it just because.<br></li></ul><h1 id="examples-of-each-object-being-used"><a name="examples-of-each-object-being-used" href="#examples-of-each-object-being-used"></a>Examples of each object being used<br></h1><p>We already showed alarms in action so lets move on to a Loop object</p><p>Throughout these examples I am going to do some strange things in order to show other features of the library!</p><h2 id="loops"><a name="loops" href="#loops"></a>LOOPS</h2><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Loops: Have been moved to the core of the library require(&quot;multi&quot;) would work as well <li>Process#<br></li><li>QueueQueuer#<br></li><li>Alarm<br></li><li>Loop<br></li><li>Event<br></li><li>Step<br></li><li>Range<br></li><li>TStep<br></li><li>TLoop<br></li><li>Condition<br></li><li>Connection<br></li><li>Timer<br></li><li>Updater<br></li><li>Thread*<br></li><li>Trigger<br></li><li>Task<br></li><li>Job<br></li><li>Function<br></li><li>Watcher<br><br>Note: <em>Both a process and queue act like the multi namespace, but allows for some cool things. Because they use the other objects an example on them will be done last</em><br><br>*Uses the built in coroutine features of lua, these have an interesting interaction with the other means of multi-tasking<br><br>Triggers are kind of useless after the creation of the Connection<br><br>Watchers have no real purpose as well I made it just because.<br></li></ul><h1 id="examples-of-each-object-being-used"><a name="examples-of-each-object-being-used" href="#examples-of-each-object-being-used"></a>Examples of each object being used<br></h1><p>We already showed alarms in action so lets move on to a Loop object</p><p>Throughout these examples I am going to do some strange things in order to show other features of the library!</p><h2 id="loops"><a name="loops" href="#loops"></a>LOOPS</h2><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Loops: Have been moved to the core of the library require(&quot;multi&quot;) would work as well
require(&quot;multi&quot;) -- gets the entire library require(&quot;multi&quot;) -- gets the entire library
count=0 count=0
loop=multi:newLoop(function(self,dt) -- dt is delta time and self is a reference to itself loop=multi:newLoop(function(self,dt) -- dt is delta time and self is a reference to itself
@ -1132,7 +1132,7 @@ multi:systemThreadedBenchmark(<span class="hljs-number">3</span>):OnBench(<span
multi:systemThreadedBenchmark(<span class="hljs-number">3</span>,<span class="hljs-string">"All Threads: "</span>) multi:systemThreadedBenchmark(<span class="hljs-number">3</span>,<span class="hljs-string">"All Threads: "</span>)
<span class="hljs-keyword">end</span>) <span class="hljs-keyword">end</span>)
multi:mainloop() multi:mainloop()
</code></pre><h1 id="using-multi:newsystemthreadedqueue()"><a name="using-multi:newsystemthreadedqueue()" href="#using-multi:newsystemthreadedqueue()"></a>Using multi:newSystemThreadedQueue()</h1><p>Quick Note: queues shared across multiple objects will be pulling from the same “queue” keep this in mind when coding! Also the queue respects direction a push on the thread side cannot be popped on the thread side… Same goes for the mainthread!<br></p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- in love2d, this file will be in the same example folder as before, but is named main2.lua </code></pre><h1 id="using-multi:newsystemthreadedqueue()"><a name="using-multi:newsystemthreadedqueue()" href="#using-multi:newsystemthreadedqueue()"></a>Using multi:newSystemThreadedQueue()</h1><p>Quick Note: queues shared across multiple objects will be pulling from the same “queue” keep this in mind when coding! <del>Also the queue respects direction a push on the thread side cannot be popped on the thread side… Same goes for the mainthread!<br></del> Turns out i was wrong about this…</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- in love2d, this file will be in the same example folder as before, but is named main2.lua
require(&quot;core.Library&quot;) require(&quot;core.Library&quot;)
GLOBAL,sThread=require(&quot;multi.integration.loveManager&quot;).init() -- load the love2d version of the lanesManager and requires the entire multi library GLOBAL,sThread=require(&quot;multi.integration.loveManager&quot;).init() -- load the love2d version of the lanesManager and requires the entire multi library
--IMPORTANT --IMPORTANT

View File

@ -1,4 +1,4 @@
# multi Version: 1.8.3 (Performance Increase! Check changes for info) # multi Version: 1.8.4 (System Threaded Job Queues)
**Note: The changes section has information on how to use the new features as they come out. Why put the infomation twice on the readme?**</br> **Note: The changes section has information on how to use the new features as they come out. Why put the infomation twice on the readme?**</br>
My multitasking library for lua</br> My multitasking library for lua</br>
@ -23,7 +23,7 @@ https://discord.gg/U8UspuA</br>
Planned features/TODO Planned features/TODO
--------------------- ---------------------
- [x] ~~Add system threads for love2d that works like the lanesManager (loveManager, slight differences).~~ - [x] ~~Add system threads for love2d that works like the lanesManager (loveManager, slight differences).~~
- [ ] Improve performance of the library -- It has increased a bit, but I feel I can get a little more out of it - [x] ~~Improve performance of the library~~
- [ ] Improve coroutine based threading scheduling - [ ] Improve coroutine based threading scheduling
- [x] ~~Add more features to support module creators~~ - [x] ~~Add more features to support module creators~~
- [x] ~~Make a framework for eaiser thread task distributing~~ - [x] ~~Make a framework for eaiser thread task distributing~~
@ -57,7 +57,7 @@ The library is modular so you only need to require what you need to. Because of
There are many useful objects that you can use</br> There are many useful objects that you can use</br>
Check out the wiki for detailed usage, but here are the objects:</br> Check out the wiki for detailed usage, but here are the objects:</br>
- Process#</br> - Process#</br>
- Queuer#</br> - QueueQueuer#</br>
- Alarm</br> - Alarm</br>
- Loop</br> - Loop</br>
- Event</br> - Event</br>
@ -890,7 +890,7 @@ multi:mainloop()
``` ```
# Using multi:newSystemThreadedQueue() # Using multi:newSystemThreadedQueue()
Quick Note: queues shared across multiple objects will be pulling from the same "queue" keep this in mind when coding! Also the queue respects direction a push on the thread side cannot be popped on the thread side... Same goes for the mainthread!</br> Quick Note: queues shared across multiple objects will be pulling from the same "queue" keep this in mind when coding! ~~Also the queue respects direction a push on the thread side cannot be popped on the thread side... Same goes for the mainthread!</br>~~ Turns out i was wrong about this...
```lua ```lua
-- in love2d, this file will be in the same example folder as before, but is named main2.lua -- in love2d, this file will be in the same example folder as before, but is named main2.lua
require("core.Library") require("core.Library")

View File

@ -45,8 +45,8 @@ function print(...)
end end
end end
multi = {} multi = {}
multi.Version="1.8.3" multi.Version="1.8.4"
multi._VERSION="1.8.3" multi._VERSION="1.8.4"
multi.stage='stable' multi.stage='stable'
multi.__index = multi multi.__index = multi
multi.Mainloop={} multi.Mainloop={}
@ -980,6 +980,7 @@ function multi:mainloop()
end end
end end
function multi:protectedMainloop() function multi:protectedMainloop()
multi:protect()
if not multi.isRunning then if not multi.isRunning then
multi.isRunning=true multi.isRunning=true
for i=1,#self.Tasks do for i=1,#self.Tasks do
@ -994,6 +995,7 @@ function multi:protectedMainloop()
end end
end end
function multi:unprotectedMainloop() function multi:unprotectedMainloop()
multi:unProtect()
if not multi.isRunning then if not multi.isRunning then
multi.isRunning=true multi.isRunning=true
for i=1,#self.Tasks do for i=1,#self.Tasks do
@ -1018,6 +1020,7 @@ function multi:unprotectedMainloop()
end end
end end
function multi:prioritizedMainloop1() function multi:prioritizedMainloop1()
multi:enablePriority()
if not multi.isRunning then if not multi.isRunning then
multi.isRunning=true multi.isRunning=true
for i=1,#self.Tasks do for i=1,#self.Tasks do
@ -1049,6 +1052,7 @@ function multi:prioritizedMainloop1()
end end
end end
function multi:prioritizedMainloop2() function multi:prioritizedMainloop2()
multi:enablePriority2()
if not multi.isRunning then if not multi.isRunning then
multi.isRunning=true multi.isRunning=true
for i=1,#self.Tasks do for i=1,#self.Tasks do
@ -1593,7 +1597,7 @@ function multi:newThread(name,func)
end end
multi:setDomainName("Threads") multi:setDomainName("Threads")
multi:setDomainName("Globals") multi:setDomainName("Globals")
multi.scheduler=multi:newUpdater() multi.scheduler=multi:newLoop()
multi.scheduler.Type="scheduler" multi.scheduler.Type="scheduler"
function multi.scheduler:setStep(n) function multi.scheduler:setStep(n)
self.skip=tonumber(n) or 24 self.skip=tonumber(n) or 24
@ -1602,7 +1606,7 @@ multi.scheduler.skip=0
multi.scheduler.counter=0 multi.scheduler.counter=0
multi.scheduler.Threads=multi:linkDomain("Threads") multi.scheduler.Threads=multi:linkDomain("Threads")
multi.scheduler.Globals=multi:linkDomain("Globals") multi.scheduler.Globals=multi:linkDomain("Globals")
multi.scheduler:OnUpdate(function(self) multi.scheduler:OnLoop(function(self)
self.counter=self.counter+1 self.counter=self.counter+1
for i=#self.Threads,1,-1 do for i=#self.Threads,1,-1 do
ret={} ret={}
@ -1656,7 +1660,6 @@ multi.scheduler:OnUpdate(function(self)
end end
end end
end) end)
multi.scheduler:setStep()
multi.scheduler:Pause() multi.scheduler:Pause()
multi.OnError=multi:newConnection() multi.OnError=multi:newConnection()
function multi:newThreadedAlarm(name,set) function multi:newThreadedAlarm(name,set)

View File

@ -125,12 +125,9 @@ function multi:newSystemThread(name,func)
end) end)
return c return c
end end
print("Intergrated Lanes!") print("Integrated Lanes!")
multi.intergration={} -- for module creators multi.integration={} -- for module creators
multi.intergration.GLOBAL=GLOBAL multi.integration.GLOBAL=GLOBAL
multi.intergration.THREAD=THREAD multi.integration.THREAD=THREAD
multi.intergration.lanes={}
multi.intergration.lanes.GLOBAL=GLOBAL -- for module creators
multi.intergration.lanes.THREAD=THREAD -- for module creators
require("multi.integration.shared.shared") require("multi.integration.shared.shared")
return {init=function() return GLOBAL,THREAD end} return {init=function() return GLOBAL,THREAD end}

View File

@ -2,14 +2,14 @@ require("multi.compat.love2d")
function multi:canSystemThread() function multi:canSystemThread()
return true return true
end end
multi.intergration={} multi.integration={}
multi.intergration.love2d={} multi.integration.love2d={}
multi.intergration.love2d.ThreadBase=[[ multi.integration.love2d.ThreadBase=[[
__THREADNAME__=({...})[1] __THREADNAME__=({...})[1]
require("love.filesystem") require("love.filesystem")
require("love.system") require("love.system")
require("love.timer") require("love.timer")
require("multi.all") require("multi")
GLOBAL={} GLOBAL={}
setmetatable(GLOBAL,{ setmetatable(GLOBAL,{
__index=function(t,k) __index=function(t,k)
@ -79,7 +79,7 @@ function resolveType(tp,d)
elseif tp=="bool" then elseif tp=="bool" then
return (d=="true") return (d=="true")
elseif tp=="function" then elseif tp=="function" then
return loadDump(d) return loadDump("[==["..d.."]==]")
elseif tp=="table" then elseif tp=="table" then
return loadstring("return "..d)() return loadstring("return "..d)()
elseif tp=="nil" then elseif tp=="nil" then
@ -91,11 +91,11 @@ end
function resolveData(v) function resolveData(v)
local data="" local data=""
if type(v)=="table" then if type(v)=="table" then
data=ToStr(v) return ToStr(v)
elseif type(v)=="function" then elseif type(v)=="function" then
data=dump(v) return dump(v)
elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then
data=tostring(v) return tostring(v)
end end
return data return data
end end
@ -191,7 +191,7 @@ setmetatable(GLOBAL,{
end, end,
}) })
THREAD={} -- Allow main thread to interact with these objects as well THREAD={} -- Allow main thread to interact with these objects as well
multi.intergration.love2d.mainChannel=love.thread.getChannel("__MainChan__") multi.integration.love2d.mainChannel=love.thread.getChannel("__MainChan__")
function ToStr(val, name, skipnewlines, depth) function ToStr(val, name, skipnewlines, depth)
skipnewlines = skipnewlines or false skipnewlines = skipnewlines or false
depth = depth or 0 depth = depth or 0
@ -228,7 +228,7 @@ function resolveType(tp,d)
elseif tp=="bool" then elseif tp=="bool" then
return (d=="true") return (d=="true")
elseif tp=="function" then elseif tp=="function" then
return loadDump(d) return loadDump("[==["..d.."]==]")
elseif tp=="table" then elseif tp=="table" then
return loadstring("return "..d)() return loadstring("return "..d)()
elseif tp=="nil" then elseif tp=="nil" then
@ -240,11 +240,11 @@ end
function resolveData(v) function resolveData(v)
local data="" local data=""
if type(v)=="table" then if type(v)=="table" then
data=ToStr(v) return ToStr(v)
elseif type(v)=="function" then elseif type(v)=="function" then
data=dump(v) return dump(v)
elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then elseif type(v)=="string" or type(v)=="number" or type(v)=="bool" or type(v)=="nil" then
data=tostring(v) return tostring(v)
end end
return data return data
end end
@ -274,10 +274,10 @@ function multi:newSystemThread(name,func) -- the main method
local c={} local c={}
c.name=name c.name=name
c.ID=c.name.."<ID|"..randomString(8)..">" c.ID=c.name.."<ID|"..randomString(8)..">"
c.thread=love.thread.newThread(multi.intergration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func))) c.thread=love.thread.newThread(multi.integration.love2d.ThreadBase:gsub("INSERT_USER_CODE",dump(func)))
c.thread:start(c.ID) c.thread:start(c.ID)
function c:kill() function c:kill()
multi.intergration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__" multi.integration.GLOBAL["__DIEPLZ"..self.ID.."__"]="__DIEPLZ"..self.ID.."__"
end end
return c return c
end end
@ -310,11 +310,11 @@ function THREAD.hold(n)
multi.OBJ_REF:Resume() multi.OBJ_REF:Resume()
end end
__channels__={} __channels__={}
multi.intergration.GLOBAL=GLOBAL multi.integration.GLOBAL=GLOBAL
multi.intergration.THREAD=THREAD multi.integration.THREAD=THREAD
updater=multi:newUpdater() updater=multi:newUpdater()
updater:OnUpdate(function(self) updater:OnUpdate(function(self)
local data=multi.intergration.love2d.mainChannel:pop() local data=multi.integration.love2d.mainChannel:pop()
while data do while data do
--print("MAIN:",data) --print("MAIN:",data)
if type(data)=="string" then if type(data)=="string" then
@ -342,19 +342,21 @@ updater:OnUpdate(function(self)
else else
__proxy__[name]=data __proxy__[name]=data
end end
data=multi.intergration.love2d.mainChannel:pop() data=multi.integration.love2d.mainChannel:pop()
end end
end) end)
require("multi.integration.shared.shared") require("multi.integration.shared.shared")
print("Intergrated Love2d!") print("Integrated Love2d!")
return { return {
init=function(t) init=function(t)
if t then if t then
if t.threadNamespace then if t.threadNamespace then
multi.intergration.love2d.ThreadBase:gsub("sThread",t.threadNamespace) multi.integration.THREADNAME=t.threadNamespace
multi.integration.love2d.ThreadBase:gsub("sThread",t.threadNamespace)
end end
if t.globalNamespace then if t.globalNamespace then
multi.intergration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace) multi.integration.GLOBALNAME=t.globalNamespace
multi.integration.love2d.ThreadBase:gsub("GLOBAL",t.globalNamespace)
end end
end end
return GLOBAL,THREAD return GLOBAL,THREAD

View File

@ -29,10 +29,16 @@ function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a chann
function c:init() -- create an init function so we can mimic on bith love2d and lanes function c:init() -- create an init function so we can mimic on bith love2d and lanes
self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name self.chan=love.thread.getChannel(self.name) -- create channel by the name self.name
function self:push(v) -- push to the channel function self:push(v) -- push to the channel
self.chan:push(v) self.chan:push({type(v),resolveData(v)})
end end
function self:pop() -- pop from the channel function self:pop() -- pop from the channel
return self.chan:pop() local tab=self.chan:pop()
if not tab then return end
return resolveType(tab[1],tab[2])
end
function self:peek()
local tp,d=unpack{self.chan:peek()}
return resolveType(tp,d)
end end
GLOBAL[self.name]=self -- send the object to the thread through the global interface GLOBAL[self.name]=self -- send the object to the thread through the global interface
return self -- return the object return self -- return the object
@ -49,20 +55,23 @@ function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a chann
function c:pop() -- pop the queue function c:pop() -- pop the queue
return ({self.linda:receive(0,"Q")})[2] return ({self.linda:receive(0,"Q")})[2]
end end
function c:peek()
return self.linda:get("Q")
end
function c:init() -- mimic the feature that love2d requires, so code can be consistent function c:init() -- mimic the feature that love2d requires, so code can be consistent
return self return self
end end
multi.intergration.GLOBAL[name]=c -- send the object to the thread through the global interface multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface
end end
return c return c
end end
function multi:systemThreadedBenchmark(n,p) function multi:systemThreadedBenchmark(n,p)
n=n or 1 n=n or 1
local cores=multi.intergration.THREAD.getCores() local cores=multi.integration.THREAD.getCores()
local queue=multi:newSystemThreadedQueue("QUEUE") local queue=multi:newSystemThreadedQueue("QUEUE")
multi.intergration.GLOBAL["__SYSTEMBENCHMARK__"]=n multi.integration.GLOBAL["__SYSTEMBENCHMARK__"]=n
local sThread=multi.intergration.THREAD local sThread=multi.integration.THREAD
local GLOBAL=multi.intergration.GLOBAL local GLOBAL=multi.integration.GLOBAL
for i=1,cores do for i=1,cores do
multi:newSystemThread("STHREAD_BENCH",function() multi:newSystemThread("STHREAD_BENCH",function()
require("multi") require("multi")
@ -170,7 +179,71 @@ function multi:newSystemThreadedTable(name)
}) })
return self return self
end end
multi.intergration.GLOBAL[name]=c -- send the object to the thread through the global interface multi.integration.GLOBAL[name]=c -- send the object to the thread through the global interface
end end
return c return c
end end
function multi:newSystemThreadedJobQueue(numOfCores)
local c={}
c.jobnum=1
c.cores=numOfCores or multi.integration.THREAD.getCores()
c.queueIN=multi:newSystemThreadedQueue("THREADED_JQ"):init()
c.queueOUT=multi:newSystemThreadedQueue("THREADED_JQO"):init()
c.REG=multi:newSystemThreadedTable("THREADED_JQ_F_REG"):init()
-- registerJob(name,func)
-- pushJob(...)
function c:registerJob(name,func)
self.REG[name]=func
end
function c:pushJob(name,...)
self.queueOUT:push({self.jobnum,name,...})
self.jobnum=self.jobnum+1
end
local GLOBAL=multi.integration.GLOBAL -- set up locals incase we are using lanes
local sThread=multi.integration.THREAD -- set up locals incase we are using lanes
GLOBAL["__JQ_COUNT__"]=c.cores
for i=1,c.cores do
multi:newSystemThread("System Threaded Job Queue Worker Thread #"..i,function()
require("multi")
__sleep__=.001
if love then -- lets make sure we don't reference upvalues if using love2d
GLOBAL=_G.GLOBAL
sThread=_G.sThread
__sleep__=.1
end
JQI=sThread.waitFor("THREADED_JQO"):init() -- Grab it
JQO=sThread.waitFor("THREADED_JQ"):init() -- Grab it
FGLOBAL=sThread.waitFor("THREADED_JQ_F_REG"):init() -- Grab it
sThread.sleep(.1) -- lets wait for things to work out
setmetatable(_G,{
__index=FGLOBAL
})
GLOBAL["THREADED_JQ"]=nil -- remove it
GLOBAL["THREADED_JQO"]=nil -- remove it
GLOBAL["THREADED_JQ_F_REG"]=nil -- remove it
multi:newLoop(function()
sThread.sleep(__sleep__) -- lets allow cpu time for other processes on our system!
local job=JQI:pop()
if job then
local ID=table.remove(job,1) -- return and remove
local name=table.remove(job,1) -- return and remove
local ret={FGLOBAL:waitFor(name)(unpack(job))} -- unpack the rest
JQO:push({ID,ret})
end
end)
multi:mainloop()
end)
end
c.OnJobCompleted=multi:newConnection()
c.updater=multi:newLoop(function(self)
local data=self.link.queueIN:pop()
while data do
if data then
self.link.OnJobCompleted:Fire(unpack(data))
end
data=self.link.queueIN:pop()
end
end)
c.updater.link=c
return c
end

View File

@ -22,7 +22,7 @@ build = {
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua"

View File

@ -22,7 +22,7 @@ build = {
["multi.init"] = "multi/init.lua", ["multi.init"] = "multi/init.lua",
["multi.all"] = "multi/all.lua", ["multi.all"] = "multi/all.lua",
["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua", ["multi.compat.backwards[1,5,0]"] = "multi/compat/backwards[1,5,0].lua",
["multi.compat"] = "multi/compat/love2d.lua", ["multi.compat.love2d"] = "multi/compat/love2d.lua",
["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua", ["multi.integration.lanesManager"] = "multi/integration/lanesManager.lua",
["multi.integration.loveManager"] = "multi/integration/loveManager.lua", ["multi.integration.loveManager"] = "multi/integration/loveManager.lua",
["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua" ["multi.integration.shared.shared"] = "multi/integration/shared/shared.lua"