commit
1bb7410210
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,7 +1,2 @@
|
|||||||
*lua5.1
|
|
||||||
*lua5.2
|
|
||||||
*lua5.3
|
|
||||||
*lua5.4
|
|
||||||
*luajit
|
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
*.dat
|
lua5.4/*
|
||||||
18
README.md
18
README.md
@ -1,6 +1,8 @@
|
|||||||
# Multi Version: 15.2.1
|
# Multi Version: 15.3.0 A world of Connections
|
||||||
**Key Changes**
|
**Key Changes**
|
||||||
- Bug fix
|
- SystemThreadedConnections
|
||||||
|
- Restructured the directory structure of the repo (Allows for keeping multi as a submodule and being able to require it as is)
|
||||||
|
- Bug fixes
|
||||||
|
|
||||||
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
|
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
|
||||||
|
|
||||||
@ -8,7 +10,7 @@ My multitasking library for lua. It is a pure lua binding, with exceptions of th
|
|||||||
|
|
||||||
</br>
|
</br>
|
||||||
|
|
||||||
Progress is being made in [v15.3.0](https://github.com/rayaman/multi/tree/v15.3.0)
|
Progress is being made in [v15.4.0](https://github.com/rayaman/multi/tree/v15.4.0)
|
||||||
---
|
---
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
@ -16,12 +18,16 @@ Progress is being made in [v15.3.0](https://github.com/rayaman/multi/tree/v15.3.
|
|||||||
INSTALLING
|
INSTALLING
|
||||||
----------
|
----------
|
||||||
Link to optional dependencies:
|
Link to optional dependencies:
|
||||||
[lanes](https://github.com/LuaLanes/lanes)
|
- [lanes](https://github.com/LuaLanes/lanes)
|
||||||
[love2d](https://love2d.org/)
|
|
||||||
|
- [love2d](https://love2d.org/)
|
||||||
|
|
||||||
To install copy the multi folder into your environment and you are good to go</br>
|
To install copy the multi folder into your environment and you are good to go</br>
|
||||||
If you want to use the system threads, then you'll need to install lanes or love2d game engine!
|
If you want to use the system threads, then you'll need to install lanes or love2d game engine!
|
||||||
**or** use luarocks `luarocks install multi`
|
|
||||||
|
```
|
||||||
|
luarocks install multi
|
||||||
|
```
|
||||||
|
|
||||||
Discord
|
Discord
|
||||||
-------
|
-------
|
||||||
|
|||||||
@ -1,11 +1,173 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
Table of contents
|
Table of contents
|
||||||
---
|
---
|
||||||
|
[Update 15.3.0 - A world of connections](#update-1530---a-world-of-connections)</br>
|
||||||
[Update 15.2.1 - Bug fix](#update-1521---bug-fix)</br>
|
[Update 15.2.1 - Bug fix](#update-1521---bug-fix)</br>
|
||||||
[Update 15.2.0 - Upgrade Complete](#update-1520---upgrade-complete)</br>[Update 15.1.0 - Hold the thread!](#update-1510---hold-the-thread)</br>[Update 15.0.0 - The art of faking it](#update-1500---the-art-of-faking-it)</br>[Update 14.2.0 - Bloatware Removed](#update-1420---bloatware-removed)</br>[Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)</br>[Update 14.0.0 - Consistency, Additions and Stability](#update-1400---consistency-additions-and-stability)</br>[Update 13.1.0 - Bug fixes and features added](#update-1310---bug-fixes-and-features-added)</br>[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300---added-some-documentation-and-some-new-features-too-check-it-out)</br>[Update 12.2.2 - Time for some more bug fixes!](#update-1222---time-for-some-more-bug-fixes)</br>[Update 12.2.1 - Time for some bug fixes!](#update-1221---time-for-some-bug-fixes)</br>[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)</br>[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)</br>[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200---big-update-lots-of-additions-some-changes)</br>[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)</br>[Update: 1.11.0](#update-1110)</br>[Update: 1.10.0](#update-1100)</br>[Update: 1.9.2](#update-192)</br>[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)</br>[Update: 1.9.0](#update-190)</br>[Update: 1.8.7](#update-187)</br>[Update: 1.8.6](#update-186)</br>[Update: 1.8.5](#update-185)</br>[Update: 1.8.4](#update-184)</br>[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)</br>[Update: 1.8.2](#update-182)</br>[Update: 1.8.1](#update-181)</br>[Update: 1.7.6](#update-176)</br>[Update: 1.7.5](#update-175)</br>[Update: 1.7.4](#update-174)</br>[Update: 1.7.3](#update-173)</br>[Update: 1.7.2](#update-172)</br>[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)</br>[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)</br>[Update: 1.6.0](#update-160)</br>[Update: 1.5.0](#update-150)</br>[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)</br>[Update: 1.4.0 (3/20/2017)](#update-140-3202017)</br>[Update: 1.3.0 (1/29/2017)](#update-130-1292017)</br>[Update: 1.2.0 (12.31.2016)](#update-120-12312016)</br>[Update: 1.1.0](#update-110)</br>[Update: 1.0.0](#update-100)</br>[Update: 0.6.3](#update-063)</br>[Update: 0.6.2](#update-062)</br>[Update: 0.6.1-6](#update-061-6)</br>[Update: 0.5.1-6](#update-051-6)</br>[Update: 0.4.1](#update-041)</br>[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)</br>[Update: EventManager 2.0.0](#update-eventmanager-200)</br>[Update: EventManager 1.2.0](#update-eventmanager-120)</br>[Update: EventManager 1.1.0](#update-eventmanager-110)</br>[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</br>[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different)
|
[Update 15.2.0 - Upgrade Complete](#update-1520---upgrade-complete)</br>[Update 15.1.0 - Hold the thread!](#update-1510---hold-the-thread)</br>[Update 15.0.0 - The art of faking it](#update-1500---the-art-of-faking-it)</br>[Update 14.2.0 - Bloatware Removed](#update-1420---bloatware-removed)</br>[Update 14.1.0 - A whole new world of possibilities](#update-1410---a-whole-new-world-of-possibilities)</br>[Update 14.0.0 - Consistency, Additions and Stability](#update-1400---consistency-additions-and-stability)</br>[Update 13.1.0 - Bug fixes and features added](#update-1310---bug-fixes-and-features-added)</br>[Update 13.0.0 - Added some documentation, and some new features too check it out!](#update-1300---added-some-documentation-and-some-new-features-too-check-it-out)</br>[Update 12.2.2 - Time for some more bug fixes!](#update-1222---time-for-some-more-bug-fixes)</br>[Update 12.2.1 - Time for some bug fixes!](#update-1221---time-for-some-bug-fixes)</br>[Update 12.2.0 - The chains of binding](#update-1220---the-chains-of-binding)</br>[Update 12.1.0 - Threads just can't hold on anymore](#update-1210---threads-just-cant-hold-on-anymore)</br>[Update: 12.0.0 - Big update (Lots of additions some changes)](#update-1200---big-update-lots-of-additions-some-changes)</br>[Update: 1.11.1 - Small Clarification on Love](#update-1111---small-clarification-on-love)</br>[Update: 1.11.0](#update-1110)</br>[Update: 1.10.0](#update-1100)</br>[Update: 1.9.2](#update-192)</br>[Update: 1.9.1 - Threads can now argue](#update-191---threads-can-now-argue)</br>[Update: 1.9.0](#update-190)</br>[Update: 1.8.7](#update-187)</br>[Update: 1.8.6](#update-186)</br>[Update: 1.8.5](#update-185)</br>[Update: 1.8.4](#update-184)</br>[Update: 1.8.3 - Mainloop recieves some needed overhauling](#update-183---mainloop-recieves-some-needed-overhauling)</br>[Update: 1.8.2](#update-182)</br>[Update: 1.8.1](#update-181)</br>[Update: 1.7.6](#update-176)</br>[Update: 1.7.5](#update-175)</br>[Update: 1.7.4](#update-174)</br>[Update: 1.7.3](#update-173)</br>[Update: 1.7.2](#update-172)</br>[Update: 1.7.1 - Bug Fixes Only](#update-171---bug-fixes-only)</br>[Update: 1.7.0 - Threading the systems](#update-170---threading-the-systems)</br>[Update: 1.6.0](#update-160)</br>[Update: 1.5.0](#update-150)</br>[Update: 1.4.1 (4/10/2017) - First Public release of the library](#update-141-4102017---first-public-release-of-the-library)</br>[Update: 1.4.0 (3/20/2017)](#update-140-3202017)</br>[Update: 1.3.0 (1/29/2017)](#update-130-1292017)</br>[Update: 1.2.0 (12.31.2016)](#update-120-12312016)</br>[Update: 1.1.0](#update-110)</br>[Update: 1.0.0](#update-100)</br>[Update: 0.6.3](#update-063)</br>[Update: 0.6.2](#update-062)</br>[Update: 0.6.1-6](#update-061-6)</br>[Update: 0.5.1-6](#update-051-6)</br>[Update: 0.4.1](#update-041)</br>[Update: 0.3.0 - The update that started it all](#update-030---the-update-that-started-it-all)</br>[Update: EventManager 2.0.0](#update-eventmanager-200)</br>[Update: EventManager 1.2.0](#update-eventmanager-120)</br>[Update: EventManager 1.1.0](#update-eventmanager-110)</br>[Update: EventManager 1.0.0 - Error checking](#update-eventmanager-100---error-checking)</br>[Version: EventManager 0.0.1 - In The Beginning things were very different](#version-eventmanager-001---in-the-beginning-things-were-very-different)
|
||||||
|
|
||||||
|
# Update 15.3.0 - A world of Connections
|
||||||
|
|
||||||
|
Full Update Showcase
|
||||||
|
```lua
|
||||||
|
multi, thread = require("multi"):init{print=true}
|
||||||
|
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
|
||||||
|
|
||||||
|
local conn = multi:newSystemThreadedConnection("conn"):init()
|
||||||
|
|
||||||
|
multi:newSystemThread("Thread_Test_1",function()
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
local conn = GLOBAL["conn"]:init()
|
||||||
|
conn(function()
|
||||||
|
print(THREAD:getName().." was triggered!")
|
||||||
|
end)
|
||||||
|
multi:mainloop()
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:newSystemThread("Thread_Test_2",function()
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
local conn = GLOBAL["conn"]:init()
|
||||||
|
conn(function(a,b,c)
|
||||||
|
print(THREAD:getName().." was triggered!",a,b,c)
|
||||||
|
end)
|
||||||
|
multi:newAlarm(2):OnRing(function()
|
||||||
|
print("Fire 2!!!")
|
||||||
|
conn:Fire(4,5,6)
|
||||||
|
THREAD.kill()
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn(function(a,b,c)
|
||||||
|
print("Mainloop conn got triggered!",a,b,c)
|
||||||
|
end)
|
||||||
|
|
||||||
|
alarm = multi:newAlarm(1)
|
||||||
|
alarm:OnRing(function()
|
||||||
|
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()
|
||||||
|
conn(function(a,b,c)
|
||||||
|
print(THREAD:getName().." was triggered!",a,b,c)
|
||||||
|
end)
|
||||||
|
multi:newAlarm(2):OnRing(function()
|
||||||
|
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()
|
||||||
|
multi:newAlarm(2):OnRing(function()
|
||||||
|
conn2:Fire()
|
||||||
|
end)
|
||||||
|
multi:newThread(function()
|
||||||
|
print("Conn Test!")
|
||||||
|
thread.hold(conn + conn2)
|
||||||
|
print("It held!")
|
||||||
|
end)
|
||||||
|
multi:mainloop()
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
|
||||||
|
Added
|
||||||
|
---
|
||||||
|
- `multi:newConnection():Unconnect(conn_link)` Fastmode previously didn't have the ability to be unconnected to. This method works with both fastmode and non fastmode. `fastMode` will be made the default in v16.0.0 (This is a breaking change for those using the Destroy method, use this time to migrate to using `Unconnect()`)
|
||||||
|
- `thread.chain(...)` allows you to chain `thread.hold(FUNCTIONs)` together
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
thread.chain(hold_function_1, hold_function_2)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
If the first function returns true, it moves on to the next one. if expanded it follows:
|
||||||
|
```lua
|
||||||
|
while true do
|
||||||
|
thread.hold(hold_function_1)
|
||||||
|
thread.hold(hold_function_2)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
- Experimental option to multi settings: `findopt`. When set to `true` it will print out a message when certain pattern are used with this library. For example if an anonymous function is used in thread.hold() within a loop. The library will trigger a message alerting you that this isn't the most performant way to use thread.hold().
|
||||||
|
- `multi:newSystemThreadedConnection()`
|
||||||
|
|
||||||
|
Allows one to trigger connection events across threads. Works like how any connection would work. Supports all of the features, can even be `added` with non SystemThreadedConnections as demonstrated in the full showcase.
|
||||||
|
- `multi:newConnection():SetHelper(func)`
|
||||||
|
|
||||||
|
Sets the helper function that the connection object uses when creating connection links.
|
||||||
|
|
||||||
|
- `multi.ForEach(table, callback_function)`
|
||||||
|
|
||||||
|
Loops through the table and calls callback_function with each element of the array.
|
||||||
|
|
||||||
|
- If a name is not supplied when creating threads and threaded objects; a name is randomly generated. Unless sending through an established channel/queue you might not be able to easily init the object.
|
||||||
|
|
||||||
|
Changed
|
||||||
|
---
|
||||||
|
- Internally all `OnError` events are now connected to with multi.print, you must pass `print=true` to the init settings when initializing the multi object. `require("multi"):init{print=true}`
|
||||||
|
- All actors now use fastmode on connections
|
||||||
|
- Performance enhancement with processes that are pumped. Instead of automatically running, by suppressing the creation of an internal loop object that would manage the process, we bypass that freeing up memory and adding a bit more speed.
|
||||||
|
- `Connection:fastMode() or Connection:SetHelper()` now returns a reference to itself
|
||||||
|
- `Connection:[connect, hasConnections, getConnection]` changed to be `Connection:[Connect, HasConnections, getConnections]`. This was done in an attempt to follow a consistent naming scheme. The old methods still will work to prevent old code breaking.
|
||||||
|
- `Connections when added(+) together now act like 'or', to get the 'and' feature multiply(*) them together.`
|
||||||
|
|
||||||
|
**Note:** This is a potentially breaking change for using connections.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
multi, thread = require("multi"):init{print=true}
|
||||||
|
-- GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
|
||||||
|
|
||||||
|
local conn1, conn2, conn3 = multi:newConnection(), multi:newConnection(), multi:newConnection()
|
||||||
|
|
||||||
|
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()
|
||||||
|
end)
|
||||||
|
```
|
||||||
|
|
||||||
|
Removed
|
||||||
|
---
|
||||||
|
- Connection objects methods removed:
|
||||||
|
- holdUT(), HoldUT() -- With the way `thread.hold(conn)` interacts with connections this method was no longer needed. To emulate this use `multi.hold(conn)`. `multi.hold()` is able to emulate what `thread.hold()` outside of a thread, albeit with some drawbacks.
|
||||||
|
|
||||||
|
Fixed
|
||||||
|
---
|
||||||
|
- SystemThreaded Objects variables weren't consistent.
|
||||||
|
- Issue with connections being multiplied only being able to have a combined fire once
|
||||||
|
|
||||||
|
ToDo
|
||||||
|
---
|
||||||
|
|
||||||
|
- Work on network parallelism (I am really excited to start working on this. Not because it will have much use, but because it seems like a cool addition/project to work on. I just need time to actually do work on stuff)
|
||||||
|
|
||||||
# Update 15.2.1 - Bug fix
|
# Update 15.2.1 - Bug fix
|
||||||
Fixed issue #41
|
Fixed issue #41
|
||||||
|
---
|
||||||
|
|
||||||
# Update 15.2.0 - Upgrade Complete
|
# Update 15.2.0 - Upgrade Complete
|
||||||
|
|
||||||
@ -29,12 +29,13 @@ local clock = os.clock
|
|||||||
local thread = {}
|
local thread = {}
|
||||||
local in_proc = false
|
local in_proc = false
|
||||||
local processes = {}
|
local processes = {}
|
||||||
|
local find_optimization = false
|
||||||
|
|
||||||
if not _G["$multi"] then
|
if not _G["$multi"] then
|
||||||
_G["$multi"] = {multi=multi,thread=thread}
|
_G["$multi"] = {multi=multi,thread=thread}
|
||||||
end
|
end
|
||||||
|
|
||||||
multi.Version = "15.2.1"
|
multi.Version = "15.3.0"
|
||||||
multi.Name = "root"
|
multi.Name = "root"
|
||||||
multi.NIL = {Type="NIL"}
|
multi.NIL = {Type="NIL"}
|
||||||
local NIL = multi.NIL
|
local NIL = multi.NIL
|
||||||
@ -58,15 +59,15 @@ multi.Priority_Very_Low = 16384
|
|||||||
multi.Priority_Idle = 65536
|
multi.Priority_Idle = 65536
|
||||||
|
|
||||||
multi.PriorityResolve = {
|
multi.PriorityResolve = {
|
||||||
[1]="Core",
|
[1] = "Core",
|
||||||
[4]="Very High",
|
[4] = "Very High",
|
||||||
[16]="High",
|
[16] = "High",
|
||||||
[64]="Above Normal",
|
[64] = "Above Normal",
|
||||||
[256]="Normal",
|
[256] = "Normal",
|
||||||
[1024]="Below Normal",
|
[1024] = "Below Normal",
|
||||||
[4096]="Low",
|
[4096] = "Low",
|
||||||
[16384]="Very Low",
|
[16384] = "Very Low",
|
||||||
[65536]="Idle",
|
[65536] = "Idle",
|
||||||
}
|
}
|
||||||
|
|
||||||
local PList = {multi.Priority_Core,multi.Priority_Very_High,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Very_Low,multi.Priority_Idle}
|
local PList = {multi.Priority_Core,multi.Priority_Very_High,multi.Priority_High,multi.Priority_Above_Normal,multi.Priority_Normal,multi.Priority_Below_Normal,multi.Priority_Low,multi.Priority_Very_Low,multi.Priority_Idle}
|
||||||
@ -109,6 +110,15 @@ function multi:getStats()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--Helpers
|
--Helpers
|
||||||
|
|
||||||
|
function multi.ForEach(tab,func)
|
||||||
|
for i=1,#tab do func(tab[i]) end
|
||||||
|
end
|
||||||
|
local CRef = {
|
||||||
|
Fire = function() end
|
||||||
|
}
|
||||||
|
|
||||||
|
local optimization_stats = {}
|
||||||
local ignoreconn = true
|
local ignoreconn = true
|
||||||
function multi:newConnection(protect,func,kill)
|
function multi:newConnection(protect,func,kill)
|
||||||
local c={}
|
local c={}
|
||||||
@ -116,70 +126,75 @@ function multi:newConnection(protect,func,kill)
|
|||||||
local lock = false
|
local lock = false
|
||||||
c.callback = func
|
c.callback = func
|
||||||
c.Parent=self
|
c.Parent=self
|
||||||
|
|
||||||
setmetatable(c,{__call=function(self,...)
|
setmetatable(c,{__call=function(self,...)
|
||||||
local t = ...
|
local t = ...
|
||||||
if type(t)=="table" then
|
if type(t)=="table" then
|
||||||
for i,v in pairs(t) do
|
for i,v in pairs(t) do
|
||||||
if v==self then
|
if v==self then
|
||||||
local ref = self:connect(select(2,...))
|
local ref = self:Connect(select(2,...))
|
||||||
|
if ref then
|
||||||
ref.root_link = select(1,...)
|
ref.root_link = select(1,...)
|
||||||
return ref
|
return ref
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
return self:connect(...)
|
end
|
||||||
|
return self:Connect(...)
|
||||||
else
|
else
|
||||||
return self:connect(...)
|
return self:Connect(...)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
__add = function(c1,c2)
|
__add = function(c1,c2) -- Or
|
||||||
cn = multi:newConnection()
|
local cn = multi:newConnection()
|
||||||
if not c1.__hasInstances then
|
|
||||||
cn.__hasInstances = 2
|
|
||||||
cn.__count = 0
|
|
||||||
else
|
|
||||||
cn.__hasInstances = c1.__hasInstances + 1
|
|
||||||
cn.__count = c1.__count
|
|
||||||
end
|
|
||||||
c1(function(...)
|
c1(function(...)
|
||||||
cn.__count = cn.__count + 1
|
|
||||||
if cn.__count == cn.__hasInstances then
|
|
||||||
cn:Fire(...)
|
cn:Fire(...)
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
c2(function(...)
|
c2(function(...)
|
||||||
cn.__count = cn.__count + 1
|
|
||||||
if cn.__count == cn.__hasInstances then
|
|
||||||
cn:Fire(...)
|
cn:Fire(...)
|
||||||
|
end)
|
||||||
|
return cn
|
||||||
|
end,
|
||||||
|
__mul = function(c1,c2) -- And
|
||||||
|
local cn = multi:newConnection()
|
||||||
|
if c1.__hasInstances == nil then
|
||||||
|
cn.__hasInstances = {2}
|
||||||
|
cn.__count = {0}
|
||||||
|
else
|
||||||
|
cn.__hasInstances = c1.__hasInstances
|
||||||
|
cn.__hasInstances[1] = cn.__hasInstances[1] + 1
|
||||||
|
cn.__count = c1.__count
|
||||||
|
end
|
||||||
|
|
||||||
|
c1(function(...)
|
||||||
|
cn.__count[1] = cn.__count[1] + 1
|
||||||
|
if cn.__count[1] == cn.__hasInstances[1] then
|
||||||
|
cn:Fire(...)
|
||||||
|
cn.__count[1] = 0
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
c2(function(...)
|
||||||
|
cn.__count[1] = cn.__count[1] + 1
|
||||||
|
if cn.__count[1] == cn.__hasInstances[1] then
|
||||||
|
cn:Fire(...)
|
||||||
|
cn.__count[1] = 0
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
return cn
|
return cn
|
||||||
end})
|
end})
|
||||||
|
|
||||||
c.Type='connector'
|
c.Type='connector'
|
||||||
c.func={}
|
c.func={}
|
||||||
c.ID=0
|
c.ID=0
|
||||||
local protect=protect or false
|
local protect=protect or false
|
||||||
local connections={}
|
local connections={}
|
||||||
c.FC=0
|
c.FC=0
|
||||||
|
|
||||||
function c:hasConnections()
|
function c:hasConnections()
|
||||||
return #call_funcs~=0
|
return #call_funcs~=0
|
||||||
end
|
end
|
||||||
function c:holdUT(n)
|
|
||||||
local n=n or 0
|
|
||||||
self.waiting=true
|
|
||||||
local count=0
|
|
||||||
local id=self:connect(function()
|
|
||||||
count = count + 1
|
|
||||||
if n<=count then
|
|
||||||
self.waiting=false
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
repeat
|
|
||||||
self.Parent:uManager()
|
|
||||||
until self.waiting==false
|
|
||||||
id:Destroy()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
c.HoldUT=c.holdUT
|
|
||||||
function c:getConnection(name,ignore)
|
function c:getConnection(name,ignore)
|
||||||
if ignore then
|
if ignore then
|
||||||
return connections[name] or CRef
|
return connections[name] or CRef
|
||||||
@ -187,20 +202,26 @@ function multi:newConnection(protect,func,kill)
|
|||||||
return connections[name] or self
|
return connections[name] or self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function c:Lock()
|
function c:Lock()
|
||||||
lock = true
|
lock = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function c:Unlock()
|
function c:Unlock()
|
||||||
lock = false
|
lock = false
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
if protect then
|
if protect then
|
||||||
function c:Fire(...)
|
function c:Fire(...)
|
||||||
if lock then return end
|
if lock then return end
|
||||||
for i=#call_funcs,1,-1 do
|
for i=#call_funcs,1,-1 do
|
||||||
if not call_funcs[i] then return end
|
if not call_funcs[i] then return end
|
||||||
pcall(call_funcs[i],...)
|
local suc, err = pcall(call_funcs[i],...)
|
||||||
|
if not suc then
|
||||||
|
print(err)
|
||||||
|
end
|
||||||
if kill then
|
if kill then
|
||||||
table.remove(call_funcs,i)
|
table.remove(call_funcs,i)
|
||||||
end
|
end
|
||||||
@ -208,6 +229,7 @@ function multi:newConnection(protect,func,kill)
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
function c:Fire(...)
|
function c:Fire(...)
|
||||||
|
if lock then return end
|
||||||
for i=#call_funcs,1,-1 do
|
for i=#call_funcs,1,-1 do
|
||||||
call_funcs[i](...)
|
call_funcs[i](...)
|
||||||
if kill then
|
if kill then
|
||||||
@ -216,48 +238,37 @@ function multi:newConnection(protect,func,kill)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local fast = {}
|
local fast = {}
|
||||||
function c:getConnections()
|
function c:getConnections()
|
||||||
return call_funcs
|
return call_funcs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function c:Unconnect(conn)
|
||||||
|
if conn.fast then
|
||||||
|
for i = 1, #fast do
|
||||||
|
if conn.ref == fast[i] then
|
||||||
|
table.remove(fast, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif conn.Destroy then
|
||||||
|
conn:Destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function c:fastMode()
|
function c:fastMode()
|
||||||
|
if find_optimization then return self end
|
||||||
function self:Fire(...)
|
function self:Fire(...)
|
||||||
for i=1,#fast do
|
for i=1,#fast do
|
||||||
fast[i](...)
|
fast[i](...)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function self:connect(func)
|
function self:Connect(func)
|
||||||
table.insert(fast,func)
|
table.insert(fast, func)
|
||||||
end
|
local temp = {fast = true}
|
||||||
end
|
|
||||||
function c:Bind(t)
|
|
||||||
local temp = call_funcs
|
|
||||||
call_funcs=t
|
|
||||||
return temp
|
|
||||||
end
|
|
||||||
function c:Remove()
|
|
||||||
local temp = call_funcs
|
|
||||||
call_funcs={}
|
|
||||||
return temp
|
|
||||||
end
|
|
||||||
local function conn_helper(self,func,name,num)
|
|
||||||
self.ID=self.ID+1
|
|
||||||
if num then
|
|
||||||
table.insert(call_funcs,num,func)
|
|
||||||
else
|
|
||||||
table.insert(call_funcs,1,func)
|
|
||||||
end
|
|
||||||
local temp = {
|
|
||||||
func=func,
|
|
||||||
Type="connector_link",
|
|
||||||
Parent=self,
|
|
||||||
connect = function(s,...)
|
|
||||||
return self:connect(...)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
setmetatable(temp,{
|
setmetatable(temp,{
|
||||||
__call=function(s,...)
|
__call=function(s,...)
|
||||||
return self:connect(...)
|
return self:Connect(...)
|
||||||
end,
|
end,
|
||||||
__index = function(t,k)
|
__index = function(t,k)
|
||||||
if rawget(t,"root_link") then
|
if rawget(t,"root_link") then
|
||||||
@ -272,18 +283,66 @@ function multi:newConnection(protect,func,kill)
|
|||||||
rawset(t,k,v)
|
rawset(t,k,v)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
function temp:Fire(...)
|
temp.ref = func
|
||||||
if lock then return end
|
return temp
|
||||||
if protect then
|
|
||||||
local t=pcall(call_funcs,...)
|
|
||||||
if t then
|
|
||||||
return t
|
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:Bind(t)
|
||||||
|
local temp = call_funcs
|
||||||
|
call_funcs=t
|
||||||
|
return temp
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:Remove()
|
||||||
|
local temp = call_funcs
|
||||||
|
call_funcs={}
|
||||||
|
return temp
|
||||||
|
end
|
||||||
|
|
||||||
|
local function conn_helper(self,func,name,num)
|
||||||
|
self.ID=self.ID+1
|
||||||
|
|
||||||
|
if num then
|
||||||
|
table.insert(call_funcs,num,func)
|
||||||
else
|
else
|
||||||
|
table.insert(call_funcs,1,func)
|
||||||
|
end
|
||||||
|
|
||||||
|
local temp = {
|
||||||
|
func=func,
|
||||||
|
Type="connector_link",
|
||||||
|
Parent=self,
|
||||||
|
connect = function(s,...)
|
||||||
|
return self:Connect(...)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
setmetatable(temp,{
|
||||||
|
__call=function(s,...)
|
||||||
|
return self:Connect(...)
|
||||||
|
end,
|
||||||
|
__index = function(t,k)
|
||||||
|
if rawget(t,"root_link") then
|
||||||
|
return t["root_link"][k]
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end,
|
||||||
|
__newindex = function(t,k,v)
|
||||||
|
if rawget(t,"root_link") then
|
||||||
|
t["root_link"][k] = v
|
||||||
|
end
|
||||||
|
rawset(t,k,v)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
function temp:Fire(...)
|
||||||
return call_funcs(...)
|
return call_funcs(...)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
function temp:Destroy()
|
function temp:Destroy()
|
||||||
|
multi.print("Calling Destroy on a connection link is deprecated and will be removed in v16.0.0")
|
||||||
for i=#call_funcs,1,-1 do
|
for i=#call_funcs,1,-1 do
|
||||||
if call_funcs[i]~=nil then
|
if call_funcs[i]~=nil then
|
||||||
if call_funcs[i]==self.func then
|
if call_funcs[i]==self.func then
|
||||||
@ -294,15 +353,19 @@ function multi:newConnection(protect,func,kill)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if name then
|
if name then
|
||||||
connections[name]=temp
|
connections[name]=temp
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.callback then
|
if self.callback then
|
||||||
self.callback(temp)
|
self.callback(temp)
|
||||||
end
|
end
|
||||||
|
|
||||||
return temp
|
return temp
|
||||||
end
|
end
|
||||||
function c:connect(...)--func,name,num
|
|
||||||
|
function c:Connect(...)--func,name,num
|
||||||
local tab = {...}
|
local tab = {...}
|
||||||
local funcs={}
|
local funcs={}
|
||||||
for i=1,#tab do
|
for i=1,#tab do
|
||||||
@ -320,14 +383,45 @@ function multi:newConnection(protect,func,kill)
|
|||||||
return conn_helper(self,tab[1],tab[2],tab[3])
|
return conn_helper(self,tab[1],tab[2],tab[3])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
c.Connect=c.connect
|
|
||||||
|
function c:SetHelper(func)
|
||||||
|
conn_helper = func
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
if find_optimization then
|
||||||
|
--
|
||||||
|
end
|
||||||
|
|
||||||
|
c.connect=c.Connect
|
||||||
c.GetConnection=c.getConnection
|
c.GetConnection=c.getConnection
|
||||||
|
c.HasConnections = c.hasConnections
|
||||||
|
c.GetConnection = c.getConnection
|
||||||
|
|
||||||
if not(ignoreconn) then
|
if not(ignoreconn) then
|
||||||
multi:create(c)
|
multi:create(c)
|
||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
multi.enableOptimization = multi:newConnection()
|
||||||
|
multi.optConn = multi:newConnection(true)
|
||||||
|
multi.optConn(function(msg)
|
||||||
|
table.insert(optimization_stats, msg)
|
||||||
|
end)
|
||||||
|
|
||||||
|
function multi:getOptimizationConnection()
|
||||||
|
return multi.optConn
|
||||||
|
end
|
||||||
|
|
||||||
|
function multi:getOptimizationStats()
|
||||||
|
return optimization_stats
|
||||||
|
end
|
||||||
|
|
||||||
|
function multi:isFindingOptimizing()
|
||||||
|
return find_optimization
|
||||||
|
end
|
||||||
|
|
||||||
-- Used with ISO Threads
|
-- Used with ISO Threads
|
||||||
local function isolateFunction(func,env)
|
local function isolateFunction(func,env)
|
||||||
local dmp = string.dump(func)
|
local dmp = string.dump(func)
|
||||||
@ -508,10 +602,6 @@ function multi:newConnector()
|
|||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
local CRef = {
|
|
||||||
Fire = function() end
|
|
||||||
}
|
|
||||||
|
|
||||||
multi.OnObjectCreated=multi:newConnection()
|
multi.OnObjectCreated=multi:newConnection()
|
||||||
multi.OnObjectDestroyed=multi:newConnection()
|
multi.OnObjectDestroyed=multi:newConnection()
|
||||||
multi.OnLoad = multi:newConnection(nil,nil,true)
|
multi.OnLoad = multi:newConnection(nil,nil,true)
|
||||||
@ -565,7 +655,7 @@ function multi:newEvent(task)
|
|||||||
task=func
|
task=func
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
c.OnEvent = self:newConnection()
|
c.OnEvent = self:newConnection():fastMode()
|
||||||
self:setPriority("core")
|
self:setPriority("core")
|
||||||
c:SetName(c.Type)
|
c:SetName(c.Type)
|
||||||
multi:create(c)
|
multi:create(c)
|
||||||
@ -588,7 +678,7 @@ function multi:newUpdater(skip)
|
|||||||
skip=n
|
skip=n
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
c.OnUpdate = self:newConnection()
|
c.OnUpdate = self:newConnection():fastMode()
|
||||||
c:SetName(c.Type)
|
c:SetName(c.Type)
|
||||||
multi:create(c)
|
multi:create(c)
|
||||||
return c
|
return c
|
||||||
@ -620,7 +710,7 @@ function multi:newAlarm(set)
|
|||||||
t = clock()
|
t = clock()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
c.OnRing = self:newConnection()
|
c.OnRing = self:newConnection():fastMode()
|
||||||
function c:Pause()
|
function c:Pause()
|
||||||
count = clock()
|
count = clock()
|
||||||
self.Parent.Pause(self)
|
self.Parent.Pause(self)
|
||||||
@ -644,10 +734,7 @@ function multi:newLoop(func,notime)
|
|||||||
self.OnLoop:Fire(self,clock()-start)
|
self.OnLoop:Fire(self,clock()-start)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
c.OnLoop = self:newConnection()
|
c.OnLoop = self:newConnection():fastMode()
|
||||||
function c:fastMode()
|
|
||||||
self.OnLoop:fastMode()
|
|
||||||
end
|
|
||||||
|
|
||||||
if func then
|
if func then
|
||||||
c.OnLoop(func)
|
c.OnLoop(func)
|
||||||
@ -694,9 +781,9 @@ function multi:newStep(start,reset,count,skip)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
c.Reset=c.Resume
|
c.Reset=c.Resume
|
||||||
c.OnStart = self:newConnection()
|
c.OnStart = self:newConnection():fastMode()
|
||||||
c.OnStep = self:newConnection()
|
c.OnStep = self:newConnection():fastMode()
|
||||||
c.OnEnd = self:newConnection()
|
c.OnEnd = self:newConnection():fastMode()
|
||||||
function c:Break()
|
function c:Break()
|
||||||
self.Active=nil
|
self.Active=nil
|
||||||
return self
|
return self
|
||||||
@ -744,7 +831,7 @@ function multi:newTLoop(func,set)
|
|||||||
self.Parent.Pause(self)
|
self.Parent.Pause(self)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
c.OnLoop = self:newConnection()
|
c.OnLoop = self:newConnection():fastMode()
|
||||||
if func then
|
if func then
|
||||||
c.OnLoop(func)
|
c.OnLoop(func)
|
||||||
end
|
end
|
||||||
@ -803,6 +890,32 @@ function multi:newTStep(start,reset,count,set)
|
|||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local tasks = {}
|
||||||
|
local _tasks = 0
|
||||||
|
|
||||||
|
local function _task_handler()
|
||||||
|
tasks[#tasks + 1] = func
|
||||||
|
_tasks = _tasks + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
function multi:newTask(func)
|
||||||
|
multi:newThread("Task Handler",function()
|
||||||
|
while true do
|
||||||
|
thread.hold(function()
|
||||||
|
return _tasks > 0
|
||||||
|
end)
|
||||||
|
for i=1,_tasks do
|
||||||
|
tasks[i]()
|
||||||
|
end
|
||||||
|
_tasks = 0
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
-- Re bind this method to use the one that doesn't init a thread!
|
||||||
|
multi.newTask = _task_handler
|
||||||
|
tasks[#tasks + 1] = func
|
||||||
|
_tasks = _tasks + 1
|
||||||
|
end
|
||||||
|
|
||||||
local scheduledjobs = {}
|
local scheduledjobs = {}
|
||||||
local sthread
|
local sthread
|
||||||
|
|
||||||
@ -864,25 +977,28 @@ function multi:newProcessor(name,nothread)
|
|||||||
c.Type = "process"
|
c.Type = "process"
|
||||||
local Active = nothread or false
|
local Active = nothread or false
|
||||||
c.Name = name or ""
|
c.Name = name or ""
|
||||||
c.pump = false
|
|
||||||
c.threads = {}
|
c.threads = {}
|
||||||
c.startme = {}
|
c.startme = {}
|
||||||
c.parent = self
|
c.parent = self
|
||||||
|
|
||||||
local handler = c:createHandler(c.threads,c.startme)
|
local handler = c:createHandler(c.threads,c.startme)
|
||||||
|
|
||||||
|
if not nothread then -- Don't create a loop if we are triggering this manually
|
||||||
c.process = self:newLoop(function()
|
c.process = self:newLoop(function()
|
||||||
if Active then
|
if Active then
|
||||||
c:uManager()
|
c:uManager()
|
||||||
handler()
|
handler()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
c.process.__ignore = true
|
c.process.__ignore = true
|
||||||
|
|
||||||
c.process.isProcessThread = true
|
c.process.isProcessThread = true
|
||||||
c.process.PID = sandcount
|
c.process.PID = sandcount
|
||||||
c.OnError = c.process.OnError
|
c.OnError = c.process.OnError
|
||||||
|
else
|
||||||
|
c.OnError = multi:newConnection()
|
||||||
|
end
|
||||||
|
c.OnError(multi.print)
|
||||||
|
|
||||||
|
|
||||||
function c:getThreads()
|
function c:getThreads()
|
||||||
return c.threads
|
return c.threads
|
||||||
@ -911,10 +1027,8 @@ function multi:newProcessor(name,nothread)
|
|||||||
|
|
||||||
function c.run()
|
function c.run()
|
||||||
if not Active then return end
|
if not Active then return end
|
||||||
c.pump = true
|
|
||||||
c:uManager()
|
c:uManager()
|
||||||
handler()
|
handler()
|
||||||
c.pump = false
|
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1033,6 +1147,28 @@ function thread.sleep(n)
|
|||||||
return yield(CMD, t_sleep, n or 1)
|
return yield(CMD, t_sleep, n or 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function conn_test(conn)
|
||||||
|
local ready = false
|
||||||
|
local args
|
||||||
|
local func = function(...)
|
||||||
|
ready = true
|
||||||
|
args = {...}
|
||||||
|
end
|
||||||
|
conn(func)
|
||||||
|
return function()
|
||||||
|
if ready then
|
||||||
|
return unpack(args) or multi.NIL
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function thread.chain(...)
|
||||||
|
local args = select("#",...)
|
||||||
|
for i=1,args do
|
||||||
|
thread.hold(select(i,...))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function thread.hold(n,opt)
|
function thread.hold(n,opt)
|
||||||
thread._Requests()
|
thread._Requests()
|
||||||
local opt = opt or {}
|
local opt = opt or {}
|
||||||
@ -1051,20 +1187,7 @@ function thread.hold(n,opt)
|
|||||||
thread.getRunningThread().lastSleep = clock()
|
thread.getRunningThread().lastSleep = clock()
|
||||||
return yield(CMD, t_sleep, n or 0, nil, interval)
|
return yield(CMD, t_sleep, n or 0, nil, interval)
|
||||||
elseif type(n) == "table" and n.Type == "connector" then
|
elseif type(n) == "table" and n.Type == "connector" then
|
||||||
local rdy = function()
|
return yield(CMD, t_hold, conn_test(n), nil, interval)
|
||||||
return false
|
|
||||||
end
|
|
||||||
n(function(a1,a2,a3,a4,a5,a6)
|
|
||||||
rdy = function()
|
|
||||||
if a1==nil then
|
|
||||||
return NIL,a2,a3,a4,a5,a6
|
|
||||||
end
|
|
||||||
return a1,a2,a3,a4,a5,a6
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
return yield(CMD, t_hold, function()
|
|
||||||
return rdy()
|
|
||||||
end, nil, interval)
|
|
||||||
elseif type(n) == "function" then
|
elseif type(n) == "function" then
|
||||||
return yield(CMD, t_hold, n or dFunc, nil, interval)
|
return yield(CMD, t_hold, n or dFunc, nil, interval)
|
||||||
else
|
else
|
||||||
@ -1180,7 +1303,7 @@ function thread:newFunctionBase(generator,holdme)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
tfunc.__call = function(t,...)
|
tfunc.__call = function(t,...)
|
||||||
if not t.Active then
|
if t.Active == false then
|
||||||
if holdme then
|
if holdme then
|
||||||
return nil, "Function is paused"
|
return nil, "Function is paused"
|
||||||
end
|
end
|
||||||
@ -1244,9 +1367,8 @@ local startme_len = 0
|
|||||||
function thread:newThread(name,func,...)
|
function thread:newThread(name,func,...)
|
||||||
multi.OnLoad:Fire() -- This was done incase a threaded function was called before mainloop/uManager was called
|
multi.OnLoad:Fire() -- This was done incase a threaded function was called before mainloop/uManager was called
|
||||||
local func = func or name
|
local func = func or name
|
||||||
|
if func == name then
|
||||||
if type(name) == "function" then
|
name = name or multi.randomString(16)
|
||||||
name = "Thread#"..threadCount
|
|
||||||
end
|
end
|
||||||
local c={nil,nil,nil,nil,nil,nil,nil}
|
local c={nil,nil,nil,nil,nil,nil,nil}
|
||||||
local env = {self=c}
|
local env = {self=c}
|
||||||
@ -1264,6 +1386,7 @@ function thread:newThread(name,func,...)
|
|||||||
c.isError = false
|
c.isError = false
|
||||||
c.OnError = multi:newConnection(true,nil,true)
|
c.OnError = multi:newConnection(true,nil,true)
|
||||||
c.OnDeath = multi:newConnection(true,nil,true)
|
c.OnDeath = multi:newConnection(true,nil,true)
|
||||||
|
c.OnError(multi.print)
|
||||||
|
|
||||||
function c:getName()
|
function c:getName()
|
||||||
return c.Name
|
return c.Name
|
||||||
@ -1471,7 +1594,6 @@ co_status = {
|
|||||||
switch[task](ref,thd)
|
switch[task](ref,thd)
|
||||||
cmds[r1](ref,r2,r3,r4,r5)
|
cmds[r1](ref,r2,r3,r4,r5)
|
||||||
if ret ~= CMD and _ ~= nil then -- The rework makes this necessary
|
if ret ~= CMD and _ ~= nil then -- The rework makes this necessary
|
||||||
print("Hello")
|
|
||||||
co_status["dead"](thd,ref,task,i,th)
|
co_status["dead"](thd,ref,task,i,th)
|
||||||
end
|
end
|
||||||
r1=nil r2=nil r3=nil r4=nil r5=nil
|
r1=nil r2=nil r3=nil r4=nil r5=nil
|
||||||
@ -1725,6 +1847,10 @@ function multi.init(settings, realsettings)
|
|||||||
else
|
else
|
||||||
multi.mainloop = mainloop
|
multi.mainloop = mainloop
|
||||||
end
|
end
|
||||||
|
if settings.findopt then
|
||||||
|
find_optimization = true
|
||||||
|
multi.enableOptimization:Fire(multi, thread)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return _G["$multi"].multi,_G["$multi"].thread
|
return _G["$multi"].multi,_G["$multi"].thread
|
||||||
end
|
end
|
||||||
@ -2046,13 +2172,13 @@ function multi.print(...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
multi.GetType=multi.getType
|
multi.GetType = multi.getType
|
||||||
multi.IsPaused=multi.isPaused
|
multi.IsPaused = multi.isPaused
|
||||||
multi.IsActive=multi.isActive
|
multi.IsActive = multi.isActive
|
||||||
multi.Reallocate=multi.Reallocate
|
multi.Reallocate = multi.Reallocate
|
||||||
multi.ConnectFinal=multi.connectFinal
|
multi.ConnectFinal = multi.connectFinal
|
||||||
multi.ResetTime=multi.SetTime
|
multi.ResetTime = multi.SetTime
|
||||||
multi.IsDone=multi.isDone
|
multi.IsDone = multi.isDone
|
||||||
multi.SetName = multi.setName
|
multi.SetName = multi.setName
|
||||||
|
|
||||||
-- Special Events
|
-- Special Events
|
||||||
@ -2074,5 +2200,64 @@ else
|
|||||||
multi.m.sentinel = newproxy(true)
|
multi.m.sentinel = newproxy(true)
|
||||||
getmetatable(multi.m.sentinel).__gc = multi.m.onexit
|
getmetatable(multi.m.sentinel).__gc = multi.m.onexit
|
||||||
end
|
end
|
||||||
|
local func_cache = {}
|
||||||
|
multi:newThread(function()
|
||||||
|
thread.skip()
|
||||||
|
if find_optimization then
|
||||||
|
|
||||||
|
function thread.hold(n,opt)
|
||||||
|
thread._Requests()
|
||||||
|
local opt = opt or {}
|
||||||
|
if type(opt)=="table" then
|
||||||
|
interval = opt.interval
|
||||||
|
if opt.cycles then
|
||||||
|
return yield(CMD, t_holdW, opt.cycles or 1, n or dFunc, interval)
|
||||||
|
elseif opt.sleep then
|
||||||
|
return yield(CMD, t_holdF, opt.sleep, n or dFunc, interval)
|
||||||
|
elseif opt.skip then
|
||||||
|
return yield(CMD, t_skip, opt.skip or 1, nil, interval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(n) == "number" then
|
||||||
|
thread.getRunningThread().lastSleep = clock()
|
||||||
|
return yield(CMD, t_sleep, n or 0, nil, interval)
|
||||||
|
elseif type(n) == "table" and n.Type == "connector" then
|
||||||
|
local rdy = function()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
n(function(a1,a2,a3,a4,a5,a6)
|
||||||
|
rdy = function()
|
||||||
|
if a1==nil then
|
||||||
|
return NIL,a2,a3,a4,a5,a6
|
||||||
|
end
|
||||||
|
return a1,a2,a3,a4,a5,a6
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return yield(CMD, t_hold, function()
|
||||||
|
return rdy()
|
||||||
|
end, nil, interval)
|
||||||
|
elseif type(n) == "function" then
|
||||||
|
local cache = string.dump(n)
|
||||||
|
local f_str = tostring(n)
|
||||||
|
local good = true
|
||||||
|
for i=1,#func_cache do
|
||||||
|
if func_cache[i][1] == cache and func_cache[i][2] ~= f_str and not func_cache[i][3] then
|
||||||
|
multi:getOptimizationConnection():Fire("It's better to store a function to a variable than to use an anonymous function within the hold method!\n" .. debug.traceback())
|
||||||
|
func_cache[i][3] = true
|
||||||
|
good = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if good then
|
||||||
|
table.insert(func_cache, {cache, f_str})
|
||||||
|
end
|
||||||
|
return yield(CMD, t_hold, n or dFunc, nil, interval)
|
||||||
|
else
|
||||||
|
error("Invalid argument passed to thread.hold(...)!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Add more Overrides
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
return multi
|
return multi
|
||||||
@ -22,9 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD
|
if not (GLOBAL and THREAD) then
|
||||||
|
local GLOBAL, THREAD = multi.integration.GLOBAL,multi.integration.THREAD
|
||||||
|
else
|
||||||
|
lanes = require("lanes")
|
||||||
|
end
|
||||||
function multi:newSystemThreadedQueue(name)
|
function multi:newSystemThreadedQueue(name)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
local c = {}
|
local c = {}
|
||||||
|
c.Name = name
|
||||||
c.linda = lanes.linda()
|
c.linda = lanes.linda()
|
||||||
function c:push(v)
|
function c:push(v)
|
||||||
self.linda:send("Q", v)
|
self.linda:send("Q", v)
|
||||||
@ -41,9 +47,12 @@ function multi:newSystemThreadedQueue(name)
|
|||||||
GLOBAL[name or "_"] = c
|
GLOBAL[name or "_"] = c
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newSystemThreadedTable(name)
|
function multi:newSystemThreadedTable(name)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
local c = {}
|
local c = {}
|
||||||
c.link = lanes.linda()
|
c.link = lanes.linda()
|
||||||
|
c.Name = name
|
||||||
setmetatable(c,{
|
setmetatable(c,{
|
||||||
__index = function(t,k)
|
__index = function(t,k)
|
||||||
return c.link:get(k)
|
return c.link:get(k)
|
||||||
@ -58,14 +67,15 @@ function multi:newSystemThreadedTable(name)
|
|||||||
GLOBAL[name or "_"] = c
|
GLOBAL[name or "_"] = c
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newSystemThreadedJobQueue(n)
|
function multi:newSystemThreadedJobQueue(n)
|
||||||
local c = {}
|
local c = {}
|
||||||
c.cores = n or THREAD.getCores()*2
|
c.cores = n or THREAD.getCores()*2
|
||||||
c.OnJobCompleted = multi:newConnection()
|
c.OnJobCompleted = multi:newConnection()
|
||||||
local funcs = multi:newSystemThreadedTable()
|
local funcs = multi:newSystemThreadedTable():init()
|
||||||
local queueJob = multi:newSystemThreadedQueue()
|
local queueJob = multi:newSystemThreadedQueue():init()
|
||||||
local queueReturn = multi:newSystemThreadedQueue()
|
local queueReturn = multi:newSystemThreadedQueue():init()
|
||||||
local doAll = multi:newSystemThreadedQueue()
|
local doAll = multi:newSystemThreadedQueue():init()
|
||||||
local ID=1
|
local ID=1
|
||||||
local jid = 1
|
local jid = 1
|
||||||
function c:isEmpty()
|
function c:isEmpty()
|
||||||
@ -169,3 +179,134 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function multi:newSystemThreadedConnection(name)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
|
local c = {}
|
||||||
|
c.CONN = 0x00
|
||||||
|
c.TRIG = 0x01
|
||||||
|
c.PING = 0x02
|
||||||
|
c.PONG = 0x03
|
||||||
|
local function remove(a, b)
|
||||||
|
local ai = {}
|
||||||
|
local r = {}
|
||||||
|
for k,v in pairs(a) do ai[v]=true end
|
||||||
|
for k,v in pairs(b) do
|
||||||
|
if ai[v]==nil then table.insert(r,a[k]) end
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
c.CID = THREAD.getID()
|
||||||
|
c.subscribe = multi:newSystemThreadedQueue("SUB_STC_"..self.Name):init()
|
||||||
|
c.Name = name
|
||||||
|
c.links = {} -- All triggers sent from main connection. When a connection is triggered on another thread, they speak to the main then send stuff out.
|
||||||
|
-- Locals will only live in the thread that creates the original object
|
||||||
|
local ping
|
||||||
|
local pong = function(link, links)
|
||||||
|
local res = thread.hold(function()
|
||||||
|
return link:peek()[1] == c.PONG
|
||||||
|
end,{sleep=3})
|
||||||
|
|
||||||
|
if not res then
|
||||||
|
for i=1,#links do
|
||||||
|
if links[i] == link then
|
||||||
|
table.remove(links,i,link)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
link:pop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ping = thread:newFunction(function(self)
|
||||||
|
ping:Pause()
|
||||||
|
multi.ForEach(self.links, function(link) -- Sync new connections
|
||||||
|
link:push{self.PING}
|
||||||
|
multi:newThread("pong Thread", pong, link, self.links)
|
||||||
|
end)
|
||||||
|
|
||||||
|
thread.sleep(3)
|
||||||
|
|
||||||
|
ping:Resume()
|
||||||
|
end,false)
|
||||||
|
|
||||||
|
local function fire(...)
|
||||||
|
for _, link in pairs(c.links) do
|
||||||
|
link:push {c.TRIG, {...}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
thread:newThread("STC_SUB_MAN"..name,function()
|
||||||
|
local item
|
||||||
|
local sub_func = function() -- This will keep things held up until there is something to process
|
||||||
|
return c.subscribe:pop()
|
||||||
|
end
|
||||||
|
while true do
|
||||||
|
thread.yield()
|
||||||
|
-- We need to check on broken connections
|
||||||
|
ping(c) -- Should return instantlly and process this in another thread
|
||||||
|
item = thread.hold(sub_func)
|
||||||
|
if item[1] == c.CONN then
|
||||||
|
multi.ForEach(c.links, function(link) -- Sync new connections
|
||||||
|
item[2]:push{c.CONN, link}
|
||||||
|
end)
|
||||||
|
c.links[#c.links+1] = item[2]
|
||||||
|
elseif item[1] == c.TRIG then
|
||||||
|
fire(unpack(item[2]))
|
||||||
|
c.proxy_conn:Fire(unpack(item[2]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
--- ^^^ This will only exist in the init thread
|
||||||
|
|
||||||
|
function c:Fire(...)
|
||||||
|
local args = {...}
|
||||||
|
if self.CID == THREAD.getID() then -- Host Call
|
||||||
|
for _, link in pairs(self.links) do
|
||||||
|
link:push {self.TRIG, args}
|
||||||
|
end
|
||||||
|
self.proxy_conn:Fire(...)
|
||||||
|
else
|
||||||
|
self.subscribe:push {self.TRIG, args}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function c:init()
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
self.links = {}
|
||||||
|
self.proxy_conn = multi:newConnection()
|
||||||
|
local mt = getmetatable(self.proxy_conn)
|
||||||
|
setmetatable(self, {__index = self.proxy_conn, __call = function(t,func) self.proxy_conn(func) end, __add = mt.__add})
|
||||||
|
if self.CID == THREAD.getID() then return self end
|
||||||
|
thread:newThread("STC_CONN_MAN"..name,function()
|
||||||
|
local item
|
||||||
|
local link_self_ref = multi:newSystemThreadedQueue()
|
||||||
|
self.subscribe:push{self.CONN, link_self_ref}
|
||||||
|
while true do
|
||||||
|
item = thread.hold(function()
|
||||||
|
return link_self_ref:peek()
|
||||||
|
end)
|
||||||
|
if item[1] == self.PING then
|
||||||
|
link_self_ref:push{self.PONG}
|
||||||
|
link_self_ref:pop()
|
||||||
|
elseif item[1] == self.CONN then
|
||||||
|
if item[2].Name ~= link_self_ref.Name then
|
||||||
|
table.insert(self.links, item[2])
|
||||||
|
end
|
||||||
|
link_self_ref:pop()
|
||||||
|
elseif item[1] == self.TRIG then
|
||||||
|
self.proxy_conn:Fire(unpack(item[2]))
|
||||||
|
link_self_ref:pop()
|
||||||
|
else
|
||||||
|
-- This shouldn't be the case
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
GLOBAL[name] = c
|
||||||
|
|
||||||
|
return c
|
||||||
|
end
|
||||||
@ -50,7 +50,7 @@ local __SleepingLinda = lanes.linda() -- handles sleeping stuff
|
|||||||
local __ConsoleLinda = lanes.linda() -- handles console stuff
|
local __ConsoleLinda = lanes.linda() -- handles console stuff
|
||||||
local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions
|
local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions
|
||||||
|
|
||||||
local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda)
|
local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda, __ConsoleLinda)
|
||||||
local count = 1
|
local count = 1
|
||||||
local started = false
|
local started = false
|
||||||
local livingThreads = {}
|
local livingThreads = {}
|
||||||
@ -62,6 +62,7 @@ function THREAD:newFunction(func,holdme)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function multi:newSystemThread(name, func, ...)
|
function multi:newSystemThread(name, func, ...)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
multi.InitSystemThreadErrorHandler()
|
multi.InitSystemThreadErrorHandler()
|
||||||
local rand = math.random(1, 10000000)
|
local rand = math.random(1, 10000000)
|
||||||
local return_linda = lanes.linda()
|
local return_linda = lanes.linda()
|
||||||
@ -76,6 +77,10 @@ function multi:newSystemThread(name, func, ...)
|
|||||||
c.creationTime = os.clock()
|
c.creationTime = os.clock()
|
||||||
c.alive = true
|
c.alive = true
|
||||||
c.priority = THREAD.Priority_Normal
|
c.priority = THREAD.Priority_Normal
|
||||||
|
local multi_settings = multi.defaultSettings
|
||||||
|
for i,v in pairs(multi_settings) do
|
||||||
|
print(i,v)
|
||||||
|
end
|
||||||
c.thread = lanes.gen("*",
|
c.thread = lanes.gen("*",
|
||||||
{
|
{
|
||||||
globals={ -- Set up some globals
|
globals={ -- Set up some globals
|
||||||
@ -87,6 +92,8 @@ function multi:newSystemThread(name, func, ...)
|
|||||||
},
|
},
|
||||||
priority=c.priority
|
priority=c.priority
|
||||||
},function(...)
|
},function(...)
|
||||||
|
require("multi"):init(multi_settings)
|
||||||
|
require("multi.integration.lanesManager.extensions")
|
||||||
local has_error = true
|
local has_error = true
|
||||||
return_linda:set("returns",{func(...)})
|
return_linda:set("returns",{func(...)})
|
||||||
has_error = false
|
has_error = false
|
||||||
@ -119,6 +126,7 @@ function multi.InitSystemThreadErrorHandler()
|
|||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
_,data = __ConsoleLinda:receive(0, "Q")
|
_,data = __ConsoleLinda:receive(0, "Q")
|
||||||
|
if data then print(unpack(data)) end
|
||||||
for i = #threads, 1, -1 do
|
for i = #threads, 1, -1 do
|
||||||
temp = threads[i]
|
temp = threads[i]
|
||||||
status = temp.thread.status
|
status = temp.thread.status
|
||||||
@ -29,7 +29,7 @@ local function getOS()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda)
|
local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda, __Console)
|
||||||
local THREAD = {}
|
local THREAD = {}
|
||||||
THREAD.Priority_Core = 3
|
THREAD.Priority_Core = 3
|
||||||
THREAD.Priority_High = 2
|
THREAD.Priority_High = 2
|
||||||
@ -70,12 +70,12 @@ local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda)
|
|||||||
|
|
||||||
function THREAD.getConsole()
|
function THREAD.getConsole()
|
||||||
local c = {}
|
local c = {}
|
||||||
c.queue = _Console
|
c.queue = __Console
|
||||||
function c.print(...)
|
function c.print(...)
|
||||||
c.queue:send("Q", {...})
|
c.queue:send("Q", {...})
|
||||||
end
|
end
|
||||||
function c.error(err)
|
function c.error(err)
|
||||||
c.queue:push{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__}
|
c.queue:push("Q",{"ERROR in <"..__THREADNAME__..">: "..err,__THREADID__})
|
||||||
error(err)
|
error(err)
|
||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
@ -137,6 +137,6 @@ local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda)
|
|||||||
return GLOBAL, THREAD
|
return GLOBAL, THREAD
|
||||||
end
|
end
|
||||||
|
|
||||||
return {init = function(g,s,st)
|
return {init = function(g,s,st,c)
|
||||||
return INIT(g,s,st)
|
return INIT(g,s,st,c)
|
||||||
end}
|
end}
|
||||||
@ -22,11 +22,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
-- TODO make compatible with lovr
|
if not ISTHREAD then
|
||||||
local multi, thread = require("multi").init()
|
multi, thread = require("multi").init()
|
||||||
GLOBAL = multi.integration.GLOBAL
|
GLOBAL = multi.integration.GLOBAL
|
||||||
THREAD = multi.integration.THREAD
|
THREAD = multi.integration.THREAD
|
||||||
|
else
|
||||||
|
GLOBAL = multi.integration.GLOBAL
|
||||||
|
THREAD = multi.integration.THREAD
|
||||||
|
end
|
||||||
|
|
||||||
function multi:newSystemThreadedQueue(name)
|
function multi:newSystemThreadedQueue(name)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
local c = {}
|
local c = {}
|
||||||
c.Name = name
|
c.Name = name
|
||||||
local fRef = {"func",nil}
|
local fRef = {"func",nil}
|
||||||
@ -64,10 +70,11 @@ function multi:newSystemThreadedQueue(name)
|
|||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
function multi:newSystemThreadedTable(name)
|
function multi:newSystemThreadedTable(name)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
local c = {}
|
local c = {}
|
||||||
c.name = name
|
c.Name = name
|
||||||
function c:init()
|
function c:init()
|
||||||
return THREAD.createTable(self.name)
|
return THREAD.createTable(self.Name)
|
||||||
end
|
end
|
||||||
THREAD.package(name,c)
|
THREAD.package(name,c)
|
||||||
return c
|
return c
|
||||||
@ -203,3 +210,142 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
jqc = jqc + 1
|
jqc = jqc + 1
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function multi:newSystemThreadedConnection(name)
|
||||||
|
local name = name or multi.randomString(16)
|
||||||
|
local c = {}
|
||||||
|
c.CONN = 0x00
|
||||||
|
c.TRIG = 0x01
|
||||||
|
c.PING = 0x02
|
||||||
|
c.PONG = 0x03
|
||||||
|
|
||||||
|
local subscribe = love.thread.getChannel("SUB_STC_" .. name)
|
||||||
|
|
||||||
|
function c:init()
|
||||||
|
|
||||||
|
self.subscribe = love.thread.getChannel("SUB_STC_" .. self.Name)
|
||||||
|
|
||||||
|
function self:Fire(...)
|
||||||
|
local args = {...}
|
||||||
|
if self.CID == THREAD.getID() then -- Host Call
|
||||||
|
for _, link in pairs(self.links) do
|
||||||
|
love.thread.getChannel(link):push{self.TRIG, args}
|
||||||
|
end
|
||||||
|
self.proxy_conn:Fire(...)
|
||||||
|
else
|
||||||
|
self.subscribe:push{self.TRIG, args}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local multi, thread = require("multi"):init()
|
||||||
|
self.links = {}
|
||||||
|
self.proxy_conn = multi:newConnection()
|
||||||
|
local mt = getmetatable(self.proxy_conn)
|
||||||
|
setmetatable(self, {__index = self.proxy_conn, __call = function(t,func) self.proxy_conn(func) end, __add = mt.__add})
|
||||||
|
if self.CID == THREAD.getID() then return self end
|
||||||
|
thread:newThread("STC_CONN_MAN" .. self.Name,function()
|
||||||
|
local item
|
||||||
|
local string_self_ref = "LSF_" .. multi.randomString(16)
|
||||||
|
local link_self_ref = love.thread.getChannel(string_self_ref)
|
||||||
|
self.subscribe:push{self.CONN, string_self_ref}
|
||||||
|
while true do
|
||||||
|
item = thread.hold(function()
|
||||||
|
return link_self_ref:peek()
|
||||||
|
end)
|
||||||
|
if item[1] == self.PING then
|
||||||
|
link_self_ref:push{self.PONG}
|
||||||
|
link_self_ref:pop()
|
||||||
|
elseif item[1] == self.CONN then
|
||||||
|
if string_self_ref ~= item[2] then
|
||||||
|
table.insert(self.links, love.thread.getChannel(item[2]))
|
||||||
|
end
|
||||||
|
link_self_ref:pop()
|
||||||
|
elseif item[1] == self.TRIG then
|
||||||
|
self.proxy_conn:Fire(unpack(item[2]))
|
||||||
|
link_self_ref:pop()
|
||||||
|
else
|
||||||
|
-- This shouldn't be the case
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end).OnError(print)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
local function remove(a, b)
|
||||||
|
local ai = {}
|
||||||
|
local r = {}
|
||||||
|
for k,v in pairs(a) do ai[v]=true end
|
||||||
|
for k,v in pairs(b) do
|
||||||
|
if ai[v]==nil then table.insert(r,a[k]) end
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
c.CID = THREAD.getID()
|
||||||
|
c.Name = name
|
||||||
|
c.links = {} -- All triggers sent from main connection. When a connection is triggered on another thread, they speak to the main then send stuff out.
|
||||||
|
-- Locals will only live in the thread that creates the original object
|
||||||
|
local ping
|
||||||
|
local pong = function(link, links)
|
||||||
|
local res = thread.hold(function()
|
||||||
|
return love.thread.getChannel(link):peek()[1] == c.PONG
|
||||||
|
end,{sleep=3})
|
||||||
|
|
||||||
|
if not res then
|
||||||
|
for i=1,#links do
|
||||||
|
if links[i] == link then
|
||||||
|
table.remove(links,i,link)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
love.thread.getChannel(link):pop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ping = thread:newFunction(function(self)
|
||||||
|
ping:Pause()
|
||||||
|
|
||||||
|
multi.ForEach(self.links, function(link) -- Sync new connections
|
||||||
|
love.thread.getChannel(link):push{self.PING}
|
||||||
|
multi:newThread("pong Thread", pong, link, self.links)
|
||||||
|
end)
|
||||||
|
|
||||||
|
thread.sleep(3)
|
||||||
|
|
||||||
|
ping:Resume()
|
||||||
|
end,false)
|
||||||
|
|
||||||
|
local function fire(...)
|
||||||
|
for _, link in pairs(c.links) do
|
||||||
|
love.thread.getChannel(link):push {c.TRIG, {...}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
thread:newThread("STC_SUB_MAN"..name,function()
|
||||||
|
local item
|
||||||
|
while true do
|
||||||
|
thread.yield()
|
||||||
|
-- We need to check on broken connections
|
||||||
|
ping(c) -- Should return instantlly and process this in another thread
|
||||||
|
item = thread.hold(function() -- This will keep things held up until there is something to process
|
||||||
|
return c.subscribe:pop()
|
||||||
|
end)
|
||||||
|
if item[1] == c.CONN then
|
||||||
|
|
||||||
|
multi.ForEach(c.links, function(link) -- Sync new connections
|
||||||
|
love.thread.getChannel(item[2]):push{c.CONN, link}
|
||||||
|
end)
|
||||||
|
c.links[#c.links+1] = item[2]
|
||||||
|
|
||||||
|
elseif item[1] == c.TRIG then
|
||||||
|
fire(unpack(item[2]))
|
||||||
|
c.proxy_conn:Fire(unpack(item[2]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end).OnError(print)
|
||||||
|
--- ^^^ This will only exist in the init thread
|
||||||
|
|
||||||
|
THREAD.package(name,c)
|
||||||
|
|
||||||
|
return c
|
||||||
|
end
|
||||||
@ -26,15 +26,23 @@ if ISTHREAD then
|
|||||||
end
|
end
|
||||||
local ThreadFileData = [[
|
local ThreadFileData = [[
|
||||||
ISTHREAD = true
|
ISTHREAD = true
|
||||||
THREAD = require("multi.integration.loveManager.threads") -- order is important!
|
THREAD = require("multi.integration.loveManager.threads")
|
||||||
sThread = THREAD
|
sThread = THREAD
|
||||||
__IMPORTS = {...}
|
__IMPORTS = {...}
|
||||||
__FUNC__=table.remove(__IMPORTS,1)
|
__FUNC__=table.remove(__IMPORTS,1)
|
||||||
__THREADID__=table.remove(__IMPORTS,1)
|
__THREADID__=table.remove(__IMPORTS,1)
|
||||||
__THREADNAME__=table.remove(__IMPORTS,1)
|
__THREADNAME__=table.remove(__IMPORTS,1)
|
||||||
|
math.randomseed(__THREADID__)
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
stab = THREAD.createStaticTable(__THREADNAME__)
|
stab = THREAD.createStaticTable(__THREADNAME__)
|
||||||
GLOBAL = THREAD.getGlobal()
|
GLOBAL = THREAD.getGlobal()
|
||||||
multi, thread = require("multi").init()
|
multi, thread = require("multi").init()
|
||||||
|
multi.integration={}
|
||||||
|
multi.integration.GLOBAL = GLOBAL
|
||||||
|
multi.integration.THREAD = THREAD
|
||||||
|
pcall(require,"multi.integration.loveManager.extensions")
|
||||||
stab["returns"] = {THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))}
|
stab["returns"] = {THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))}
|
||||||
]]
|
]]
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
@ -42,7 +50,6 @@ local THREAD = {}
|
|||||||
__THREADID__ = 0
|
__THREADID__ = 0
|
||||||
__THREADNAME__ = "MainThread"
|
__THREADNAME__ = "MainThread"
|
||||||
multi.integration={}
|
multi.integration={}
|
||||||
multi.integration.love2d={}
|
|
||||||
local THREAD = require("multi.integration.loveManager.threads")
|
local THREAD = require("multi.integration.loveManager.threads")
|
||||||
local GLOBAL = THREAD.getGlobal()
|
local GLOBAL = THREAD.getGlobal()
|
||||||
local THREAD_ID = 1
|
local THREAD_ID = 1
|
||||||
@ -103,13 +110,13 @@ end
|
|||||||
THREAD.newSystemThread = multi.newSystemThread
|
THREAD.newSystemThread = multi.newSystemThread
|
||||||
|
|
||||||
function love.threaderror(thread, errorstr)
|
function love.threaderror(thread, errorstr)
|
||||||
mulit.print("Thread error!\n"..errorstr)
|
multi.print("Thread error!\n"..errorstr)
|
||||||
end
|
end
|
||||||
|
|
||||||
multi.integration.GLOBAL = GLOBAL
|
multi.integration.GLOBAL = GLOBAL
|
||||||
multi.integration.THREAD = THREAD
|
multi.integration.THREAD = THREAD
|
||||||
require("multi.integration.loveManager.extensions")
|
require("multi.integration.loveManager.extensions")
|
||||||
mulit.print("Integrated Love Threading!")
|
multi.print("Integrated Love Threading!")
|
||||||
return {init=function()
|
return {init=function()
|
||||||
return GLOBAL,THREAD
|
return GLOBAL,THREAD
|
||||||
end}
|
end}
|
||||||
@ -106,7 +106,7 @@ function threads.kill()
|
|||||||
error("Thread Killed!\1")
|
error("Thread Killed!\1")
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.pushStatus(...)
|
function threads.pushStatus(...)
|
||||||
local status_channel = love.thread.getChannel("__"..__THREADID__.."__MULTI__STATUS_CHANNEL__")
|
local status_channel = love.thread.getChannel("__"..__THREADID__.."__MULTI__STATUS_CHANNEL__")
|
||||||
local args = {...}
|
local args = {...}
|
||||||
status_channel:push(__THREADID__, args)
|
status_channel:push(__THREADID__, args)
|
||||||
@ -23,7 +23,7 @@ SOFTWARE.
|
|||||||
]]
|
]]
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
local net = require("net")
|
local net = require("net")
|
||||||
local bin = require("bin")
|
--local bin = require("bin")
|
||||||
local char = string.char
|
local char = string.char
|
||||||
local byte = string.byte
|
local byte = string.byte
|
||||||
bin.setBitsInterface(infinabits)
|
bin.setBitsInterface(infinabits)
|
||||||
19
makeENV.lua
19
makeENV.lua
@ -1,19 +0,0 @@
|
|||||||
commands = [[
|
|
||||||
mkdir luajit && python -m hererocks -j 2.1.0-beta3 -r latest --patch --compat all ./luajit && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi
|
|
||||||
mkdir lua5.1 && python -m hererocks -l 5.1 -r latest --patch --compat all ./lua5.1 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi
|
|
||||||
mkdir lua5.2 && python -m hererocks -l 5.2 -r latest --patch --compat all ./lua5.2 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi
|
|
||||||
mkdir lua5.3 && python -m hererocks -l 5.3 -r latest --patch --compat all ./lua5.3 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi
|
|
||||||
mkdir lua5.4 && python -m hererocks -l 5.4 -r latest --patch --compat all ./lua5.4 && set "PATH=G:\VSCWorkspace\multi\luajit\bin;%PATH%" && lua -v && luarocks install multi
|
|
||||||
]]
|
|
||||||
function string.split (inputstr, sep)
|
|
||||||
local sep = sep or "\n"
|
|
||||||
local t={}
|
|
||||||
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
|
|
||||||
table.insert(t, str)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
local run = commands:split()
|
|
||||||
for i=1,#run do
|
|
||||||
os.execute(run[i])
|
|
||||||
end
|
|
||||||
31
makeENV.sh
31
makeENV.sh
@ -1,31 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
mkdir luajit
|
|
||||||
hererocks -j 2.1.0-beta3 -r latest --compat all ./luajit
|
|
||||||
. luajit/bin/activate
|
|
||||||
echo | lua -v
|
|
||||||
luarocks install multi
|
|
||||||
deactivate-lua
|
|
||||||
mkdir lua5.1
|
|
||||||
hererocks -l 5.1 -r latest --patch --compat all ./lua5.1
|
|
||||||
. lua5.1/bin/activate
|
|
||||||
echo | lua -v
|
|
||||||
luarocks install multi
|
|
||||||
deactivate-lua
|
|
||||||
mkdir lua5.2
|
|
||||||
hererocks -l 5.2 -r latest --patch --compat all ./lua5.2
|
|
||||||
. lua5.2/bin/activate
|
|
||||||
echo | lua -v
|
|
||||||
luarocks install multi
|
|
||||||
deactivate-lua
|
|
||||||
mkdir lua5.3
|
|
||||||
hererocks -l 5.3 -r latest --patch --compat all ./lua5.3
|
|
||||||
. lua5.3/bin/activate
|
|
||||||
echo | lua -v
|
|
||||||
luarocks install multi
|
|
||||||
deactivate-lua
|
|
||||||
mkdir lua5.4
|
|
||||||
hererocks -l 5.4 -r latest --patch --compat all ./lua5.4
|
|
||||||
. lua5.4/bin/activate
|
|
||||||
echo | lua -v
|
|
||||||
luarocks install multi
|
|
||||||
deactivate-lua
|
|
||||||
39
rockspecs/multi-15.3-0.rockspec
Normal file
39
rockspecs/multi-15.3-0.rockspec
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package = "multi"
|
||||||
|
version = "15.3-0"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/rayaman/multi.git",
|
||||||
|
tag = "v15.3.0",
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Lua Multi tasking library",
|
||||||
|
detailed = [[
|
||||||
|
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
|
||||||
|
Check github for documentation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/rayaman/multi",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["multi"] = "init.lua",
|
||||||
|
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
|
||||||
|
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
|
||||||
|
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
|
||||||
|
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
|
||||||
|
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
|
||||||
|
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
|
||||||
|
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
|
||||||
|
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
|
||||||
|
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
|
||||||
|
["multi.integration.pesudoManager"] = "integration/pesudoManager/init.lua",
|
||||||
|
["multi.integration.pesudoManager.extensions"] = "integration/pesudoManager/extensions.lua",
|
||||||
|
["multi.integration.pesudoManager.threads"] = "integration/pesudoManager/threads.lua",
|
||||||
|
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
|
||||||
|
["multi.integration.threading"] = "integration/threading.lua",
|
||||||
|
--["multi.integration.networkManager"] = "integration/networkManager.lua",
|
||||||
|
}
|
||||||
|
}
|
||||||
20
test.lua
20
test.lua
@ -1,20 +0,0 @@
|
|||||||
package.path = "./?/init.lua;?.lua;lua5.4/share/lua/?/init.lua;lua5.4/share/lua/?.lua;"..package.path
|
|
||||||
package.cpath = "lua5.4/lib/lua/?/core.dll;"..package.cpath
|
|
||||||
multi, thread = require("multi"):init{print=true}
|
|
||||||
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
|
|
||||||
|
|
||||||
test = THREAD:newFunction(function()
|
|
||||||
PNT()
|
|
||||||
return 1,2
|
|
||||||
end,true)
|
|
||||||
multi:newThread(function()
|
|
||||||
while true do
|
|
||||||
print("...")
|
|
||||||
thread.sleep(1)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
multi:newAlarm(.1):OnRing(function() os.exit() end)
|
|
||||||
print(test())
|
|
||||||
print("Hi!")
|
|
||||||
|
|
||||||
multi:mainloop()
|
|
||||||
@ -2,7 +2,7 @@ if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
|
|||||||
package.path="multi/?.lua;multi/?/init.lua;multi/?.lua;multi/?/?/init.lua;"..package.path
|
package.path="multi/?.lua;multi/?/init.lua;multi/?.lua;multi/?/?/init.lua;"..package.path
|
||||||
require("lldebugger").start()
|
require("lldebugger").start()
|
||||||
else
|
else
|
||||||
package.path="./?.lua;../?/init.lua;../?.lua;../?/?/init.lua;"..package.path
|
package.path = "../?/init.lua;../?.lua;"..package.path
|
||||||
end
|
end
|
||||||
--[[
|
--[[
|
||||||
This file runs all tests.
|
This file runs all tests.
|
||||||
@ -36,12 +36,12 @@ runTest = thread:newFunction(function()
|
|||||||
end)
|
end)
|
||||||
proc:newTStep(1,10,1,.1):OnStep(function(t)
|
proc:newTStep(1,10,1,.1):OnStep(function(t)
|
||||||
tsteps = tsteps + 1
|
tsteps = tsteps + 1
|
||||||
end).OnEnd(function(step)
|
end):OnEnd(function(step)
|
||||||
step:Destroy()
|
step:Destroy()
|
||||||
end)
|
end)
|
||||||
proc:newStep(1,10):OnStep(function(s)
|
proc:newStep(1,10):OnStep(function(s)
|
||||||
steps = steps + 1
|
steps = steps + 1
|
||||||
end).OnEnd(function(step)
|
end):OnEnd(function(step)
|
||||||
step:Destroy()
|
step:Destroy()
|
||||||
end)
|
end)
|
||||||
local loop = proc:newLoop(function(l)
|
local loop = proc:newLoop(function(l)
|
||||||
@ -78,7 +78,7 @@ runTest = thread:newFunction(function()
|
|||||||
thread.pushStatus(a,count)
|
thread.pushStatus(a,count)
|
||||||
if a == count then break end
|
if a == count then break end
|
||||||
end
|
end
|
||||||
return "Done"
|
return "Done", true, math.random(1,10000)
|
||||||
end)
|
end)
|
||||||
local ret = func(10)
|
local ret = func(10)
|
||||||
local ret2 = func(15)
|
local ret2 = func(15)
|
||||||
@ -102,26 +102,35 @@ runTest = thread:newFunction(function()
|
|||||||
ret3.OnStatus(function(part,whole)
|
ret3.OnStatus(function(part,whole)
|
||||||
s3 = math.ceil((part/whole)*1000)/10
|
s3 = math.ceil((part/whole)*1000)/10
|
||||||
end)
|
end)
|
||||||
ret.OnReturn(function()
|
|
||||||
print("Done 1")
|
ret.OnReturn(function(...)
|
||||||
|
print("Done 1",...)
|
||||||
end)
|
end)
|
||||||
ret2.OnReturn(function()
|
ret2.OnReturn(function(...)
|
||||||
print("Done 2")
|
print("Done 2",...)
|
||||||
end)
|
end)
|
||||||
ret3.OnReturn(function()
|
ret3.OnReturn(function(...)
|
||||||
print("Done 3")
|
print("Done 3",...)
|
||||||
end)
|
end)
|
||||||
local err, timeout = thread.hold(ret.OnReturn + ret2.OnReturn + ret3.OnReturn)
|
|
||||||
|
local err, timeout = thread.hold(ret.OnReturn * ret2.OnReturn * ret3.OnReturn)
|
||||||
|
|
||||||
if s1 == 100 and s2 == 100 and s3 == 100 then
|
if s1 == 100 and s2 == 100 and s3 == 100 then
|
||||||
print("Threads: Ok")
|
print("Threads: All tests Ok")
|
||||||
|
else
|
||||||
|
if s1>0 and s2>0 and s3 > 0 then
|
||||||
|
print("Thread OnStatus: Ok")
|
||||||
else
|
else
|
||||||
print("Threads OnStatus or thread.hold(conn) Error!")
|
print("Threads OnStatus or thread.hold(conn) Error!")
|
||||||
end
|
end
|
||||||
if timeout then
|
if timeout then
|
||||||
print("Threads or Connection Error!")
|
print("Connection Error!")
|
||||||
else
|
else
|
||||||
print("Connection Test 1: Ok")
|
print("Connection Test 1: Ok")
|
||||||
end
|
end
|
||||||
|
print("Connection holding Error!")
|
||||||
|
end
|
||||||
|
|
||||||
conn1 = proc:newConnection()
|
conn1 = proc:newConnection()
|
||||||
conn2 = proc:newConnection()
|
conn2 = proc:newConnection()
|
||||||
conn3 = proc:newConnection()
|
conn3 = proc:newConnection()
|
||||||
@ -164,11 +173,11 @@ runTest = thread:newFunction(function()
|
|||||||
os.exit() -- End of tests
|
os.exit() -- End of tests
|
||||||
end)
|
end)
|
||||||
|
|
||||||
runTest().OnError(function(...)
|
print(runTest().OnError(function(...)
|
||||||
print("Error: Something went wrong with the test!")
|
print("Error: Something went wrong with the test!")
|
||||||
print(...)
|
print(...)
|
||||||
os.exit(1)
|
os.exit(1)
|
||||||
end)
|
end))
|
||||||
|
|
||||||
print("Pumping proc")
|
print("Pumping proc")
|
||||||
while true do
|
while true do
|
||||||
|
|||||||
133
tests/test.lua
Normal file
133
tests/test.lua
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package.path = "../?/init.lua;../?.lua;"..package.path
|
||||||
|
multi, thread = require("multi"):init{print=true,findopt=true}
|
||||||
|
GLOBAL, THREAD = require("multi.integration.lanesManager"):init()
|
||||||
|
multi:getOptimizationConnection()(function(msg)
|
||||||
|
print(msg)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- local conn1, conn2, conn3 = multi:newConnection(), multi:newConnection():fastMode(), 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("All conns\n-------------")
|
||||||
|
-- conn1:Fire()
|
||||||
|
-- conn2:Fire()
|
||||||
|
|
||||||
|
-- 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()
|
||||||
|
-- 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()
|
||||||
Loading…
x
Reference in New Issue
Block a user