commit
47d8ac30c4
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,8 +3,5 @@
|
|||||||
*lua5.3
|
*lua5.3
|
||||||
*lua5.4
|
*lua5.4
|
||||||
*luajit
|
*luajit
|
||||||
test2.lua
|
|
||||||
test.lua
|
|
||||||
test3.lua
|
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
*.dat
|
*.dat
|
||||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2021 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
59
README.md
59
README.md
@ -1,8 +1,9 @@
|
|||||||
# Multi Version: 15.1.0 Hold the thread
|
# Multi Version: 15.2.0 Upgrade Complete
|
||||||
**Key Changes**
|
**Key Changes**
|
||||||
- thread.hold has been updated to allow all variants to work as well as some new features. Check the changelog or documentation for more info.
|
- All objects now use connections internally
|
||||||
- multi:newProccesor() Creates a process that acts like the multi namespace that can be managed independently from the mainloop.
|
- Connections now about 23x faster!
|
||||||
- Connections can be added together
|
- Updated getTasksDetails() to handle the new method of managing threads and processors
|
||||||
|
- Made lanes optional, install separately if needed
|
||||||
|
|
||||||
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!
|
||||||
|
|
||||||
@ -10,57 +11,65 @@ My multitasking library for lua. It is a pure lua binding, with exceptions of th
|
|||||||
|
|
||||||
</br>
|
</br>
|
||||||
|
|
||||||
Progress is being made in [v15.2.0](https://github.com/rayaman/multi/tree/v15.2.0)
|
Progress is being made in [v15.3.0](https://github.com/rayaman/multi/tree/v15.3.0)
|
||||||
---
|
---
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
|
|
||||||
INSTALLING
|
INSTALLING
|
||||||
----------
|
----------
|
||||||
Links to dependencies:
|
Link to optional dependencies:
|
||||||
[lanes](https://github.com/LuaLanes/lanes)
|
[lanes](https://github.com/LuaLanes/lanes)
|
||||||
|
[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!
|
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`
|
**or** use luarocks `luarocks install multi`
|
||||||
|
|
||||||
Going forward I will include a Release zip for love2d.
|
|
||||||
**The Network Manager rework is currently being worked on and the old version is not included in this version.**
|
|
||||||
|
|
||||||
Discord
|
Discord
|
||||||
-------
|
-------
|
||||||
Have a question? Or need realtime assistance? Feel free to join the discord!</br>
|
Have a question or need realtime assistance? Feel free to join the discord!</br>
|
||||||
https://discord.gg/U8UspuA</br>
|
https://discord.gg/U8UspuA
|
||||||
|
|
||||||
Planned features/TODO
|
Planned features/TODO
|
||||||
---------------------
|
---------------------
|
||||||
- [x] ~~Finish Documentation~~ Finished
|
- [ ] Create test suite (In progress, mostly done)
|
||||||
- [ ] Create test suite
|
|
||||||
- [ ] Network Parallelism rework
|
- [ ] Network Parallelism rework
|
||||||
|
|
||||||
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/Documentation.md)</br>
|
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/Documentation.md)
|
||||||
-----
|
-----
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
GLOBAL, THREAD = require("multi.integration.threading"):init()
|
GLOBAL, THREAD = require("multi.integration.threading"):init()
|
||||||
|
|
||||||
multi:newSystemThread("System Thread",function()
|
multi:newSystemThread("System Thread",function()
|
||||||
while true do
|
while true do
|
||||||
THREAD.sleep(1)
|
THREAD.sleep(.1)
|
||||||
print("World!")
|
io.write(" World")
|
||||||
end
|
THREAD.kill()
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
multi:newThread("Coroutine Based Thread",function()
|
multi:newThread("Coroutine Based Thread",function()
|
||||||
while true do
|
while true do
|
||||||
print("Hello")
|
io.write("Hello")
|
||||||
thread.sleep(1)
|
thread.sleep(.1)
|
||||||
end
|
thread.kill()
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
multi:newTLoop(function(loop)
|
||||||
|
print("!")
|
||||||
|
loop:Destroy()
|
||||||
|
os.exit()
|
||||||
|
end,.3)
|
||||||
|
|
||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
while true do
|
while true do
|
||||||
multi:uManager()
|
multi:uManager()
|
||||||
end
|
end
|
||||||
]]
|
]]
|
||||||
```
|
```
|
||||||
|
|||||||
425
changes.md
425
changes.md
@ -1,15 +1,323 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
Table of contents
|
Table of contents
|
||||||
---
|
---
|
||||||
[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.2.0 - Upgrade Complete
|
||||||
|
|
||||||
|
Full Update Showcase
|
||||||
|
|
||||||
|
```lua
|
||||||
|
package.path = "./?/init.lua;"..package.path
|
||||||
|
multi, thread = require("multi"):init{print=true}
|
||||||
|
GLOBAL, THREAD = require("multi.integration.threading"):init()
|
||||||
|
|
||||||
|
-- Using a system thread, but both system and local threads support this!
|
||||||
|
-- Don't worry if you don't have lanes or love2d. PesudoThreading will kick in to emulate the threading features if you do not have access to system threading.
|
||||||
|
func = THREAD:newFunction(function(count)
|
||||||
|
print("Starting Status test: ",count)
|
||||||
|
local a = 0
|
||||||
|
while true do
|
||||||
|
a = a + 1
|
||||||
|
THREAD.sleep(.1)
|
||||||
|
-- Push the status from the currently running threaded function to the main thread
|
||||||
|
THREAD.pushStatus(a,count)
|
||||||
|
if a == count then break end
|
||||||
|
end
|
||||||
|
return "Done"
|
||||||
|
end)
|
||||||
|
|
||||||
|
thread:newThread("test",function()
|
||||||
|
local ret = func(10)
|
||||||
|
ret.OnStatus(function(part,whole)
|
||||||
|
print("Ret1: ",math.ceil((part/whole)*1000)/10 .."%")
|
||||||
|
end)
|
||||||
|
print("TEST",func(5).wait())
|
||||||
|
-- The results from the OnReturn connection is passed by thread.hold
|
||||||
|
print("Status:",thread.hold(ret.OnReturn))
|
||||||
|
print("Function Done!")
|
||||||
|
end).OnError(function(...)
|
||||||
|
print("Error:",...)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local ret = func(10)
|
||||||
|
local ret2 = func(15)
|
||||||
|
local ret3 = func(20)
|
||||||
|
local s1,s2,s3 = 0,0,0
|
||||||
|
ret.OnError(function(...)
|
||||||
|
print("Error:",...)
|
||||||
|
end)
|
||||||
|
ret2.OnError(function(...)
|
||||||
|
print("Error:",...)
|
||||||
|
end)
|
||||||
|
ret3.OnError(function(...)
|
||||||
|
print("Error:",...)
|
||||||
|
end)
|
||||||
|
ret.OnStatus(function(part,whole)
|
||||||
|
s1 = math.ceil((part/whole)*1000)/10
|
||||||
|
print(s1)
|
||||||
|
end)
|
||||||
|
ret2.OnStatus(function(part,whole)
|
||||||
|
s2 = math.ceil((part/whole)*1000)/10
|
||||||
|
print(s2)
|
||||||
|
end)
|
||||||
|
ret3.OnStatus(function(part,whole)
|
||||||
|
s3 = math.ceil((part/whole)*1000)/10
|
||||||
|
print(s3)
|
||||||
|
end)
|
||||||
|
|
||||||
|
loop = multi:newTLoop()
|
||||||
|
|
||||||
|
function loop:testing()
|
||||||
|
print("testing haha")
|
||||||
|
end
|
||||||
|
|
||||||
|
loop:Set(1)
|
||||||
|
t = loop:OnLoop(function()
|
||||||
|
print("Looping...")
|
||||||
|
end):testing()
|
||||||
|
|
||||||
|
local proc = multi:newProcessor("Test")
|
||||||
|
local proc2 = multi:newProcessor("Test2")
|
||||||
|
local proc3 = proc2:newProcessor("Test3")
|
||||||
|
proc.Start()
|
||||||
|
proc2.Start()
|
||||||
|
proc3.Start()
|
||||||
|
proc:newThread("TestThread_1",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
proc:newThread("TestThread_2",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
proc2:newThread("TestThread_3",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
thread:newThread(function()
|
||||||
|
thread.sleep(1)
|
||||||
|
local tasks = multi:getStats()
|
||||||
|
|
||||||
|
for i,v in pairs(tasks) do
|
||||||
|
print("Process: " ..i.. "\n\tTasks:")
|
||||||
|
for ii,vv in pairs(v.tasks) do
|
||||||
|
print("\t\t"..vv:getName())
|
||||||
|
end
|
||||||
|
print("\tThreads:")
|
||||||
|
for ii,vv in pairs(v.threads) do
|
||||||
|
print("\t\t"..vv:getName())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
thread.sleep(10) -- Wait 10 seconds then kill the process!
|
||||||
|
os.exit()
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
|
||||||
|
Added:
|
||||||
|
---
|
||||||
|
- `multi:getStats()`
|
||||||
|
- Returns a structured table where you can access data on processors there tasks and threads:
|
||||||
|
```lua
|
||||||
|
-- Upon calling multi:getStats() the table below is returned
|
||||||
|
get_Stats_Table {
|
||||||
|
proc_1 -- table
|
||||||
|
proc_2 -- table
|
||||||
|
...
|
||||||
|
proc_n -- table
|
||||||
|
}
|
||||||
|
proc_Table {
|
||||||
|
tasks = {alarms,steps,loops,etc} -- All multi objects
|
||||||
|
threads = {thread_1,thread_2,thread_3,etc} -- Thread objects
|
||||||
|
}
|
||||||
|
-- Refer to the objects documentation to see how you can interact with them
|
||||||
|
```
|
||||||
|
- Reference the Full update showcase for the method in action
|
||||||
|
- `multi:newProcessor(name, nothread)`
|
||||||
|
- If no thread is true auto sets the processor as Active, so proc.run() will start without the need for proc.Start()
|
||||||
|
|
||||||
|
- `multi:getProcessors()`
|
||||||
|
- Returns a list of all processors
|
||||||
|
|
||||||
|
- `multi:getName()`
|
||||||
|
- Returns the name of a processor
|
||||||
|
|
||||||
|
- `multi:getFullName()`
|
||||||
|
- Returns the fullname/entire process tree of a process
|
||||||
|
|
||||||
|
- Processors can be attached to processors
|
||||||
|
|
||||||
|
- `multi:getTasks()`
|
||||||
|
- Returns a list of all non thread based objects (loops, alarms, steps, etc)
|
||||||
|
|
||||||
|
- `multi:getThreads()`
|
||||||
|
- Returns a list of all threads on a process
|
||||||
|
|
||||||
|
- `multi:newProcessor(name, nothread).run()`
|
||||||
|
- New function run to the processor object to
|
||||||
|
|
||||||
|
- `multi:newProcessor(name, nothread):newFunction(func, holdme)`
|
||||||
|
- Acts like thread:newFunction(), but binds the execution of that threaded function to the processor
|
||||||
|
|
||||||
|
- `multi:newTLoop()` member functions
|
||||||
|
- `TLoop:Set(set)` - Sets the time to wait for the TLoop
|
||||||
|
|
||||||
|
- `multi:newStep()` member functions
|
||||||
|
- `Step:Count(count)` - Sets the amount a step should count by
|
||||||
|
|
||||||
|
- `multi:newTStep()` member functions
|
||||||
|
- `TStep:Set(set)` - Sets the time to wait for the TStep
|
||||||
|
|
||||||
|
|
||||||
|
Changed:
|
||||||
|
---
|
||||||
|
- `thread.hold(connectionObj)` now passes the returns of that connection to `thread.hold()`! See Exampe below:
|
||||||
|
```lua
|
||||||
|
multi, thread = require("multi"):init()
|
||||||
|
|
||||||
|
func = thread:newFunction(function(count)
|
||||||
|
local a = 0
|
||||||
|
while true do
|
||||||
|
a = a + 1
|
||||||
|
thread.sleep(.1)
|
||||||
|
thread.pushStatus(a,count)
|
||||||
|
if a == count then break end
|
||||||
|
end
|
||||||
|
return "Done", 1, 2, 3
|
||||||
|
end)
|
||||||
|
|
||||||
|
thread:newThread("test",function()
|
||||||
|
local ret = func(10)
|
||||||
|
ret.OnStatus(function(part,whole)
|
||||||
|
print("Ret1: ",math.ceil((part/whole)*1000)/10 .."%")
|
||||||
|
end)
|
||||||
|
print("Status:",thread.hold(ret.OnReturn))
|
||||||
|
print("Function Done!")
|
||||||
|
os.exit()
|
||||||
|
end).OnError(function(...)
|
||||||
|
print("Error:",...)
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
```
|
||||||
|
Output:
|
||||||
|
```
|
||||||
|
Ret1: 10%
|
||||||
|
Ret1: 20%
|
||||||
|
Ret1: 30%
|
||||||
|
Ret1: 40%
|
||||||
|
Ret1: 50%
|
||||||
|
Ret1: 60%
|
||||||
|
Ret1: 70%
|
||||||
|
Ret1: 80%
|
||||||
|
Ret1: 90%
|
||||||
|
Ret1: 100%
|
||||||
|
Status: Done 1 2 3 nil nil nil nil nil nil nil nil nil nil nil nil
|
||||||
|
Function Done!
|
||||||
|
```
|
||||||
|
|
||||||
|
- Modified how threads are handled internally. This changes makes it so threads "regardless of amount" should not impact performance. What you do in the threads might. This change was made by internally only processing one thread per step per processor. If you have 10 processors that are all active expect one step to process 10 threads. However if one processor has 10 threads each step will only process one thread. Simply put each addition of a thread shouldn't impact performance as it did before.
|
||||||
|
- Moved `multi:newThread(...)` into the thread interface (`thread:newThread(...)`), code using `multi:newThread(...)` will still work. Also using `process:newThread(...)` binds the thread to the process, meaning if the process the thread is bound to is paused so is the thread.
|
||||||
|
|
||||||
|
- multi:mainloop(~~settings~~)/multi:uManager(~~settings~~) no longer takes a settings argument, that has been moved to multi:init(settings)
|
||||||
|
| Setting | Description |
|
||||||
|
---|---
|
||||||
|
print | When set to true parts of the library will print out updates otherwise no internal printing will be done
|
||||||
|
priority | When set to true, the library will prioritize different objects based on their priority
|
||||||
|
- `multi:newProcessor(name,nothread)` The new argument allows you to tell the system you won't be using the Start() and Stop() functions, rather you will handle the process yourself. Using the proc.run() function. This function needs to be called to pump the events.
|
||||||
|
- Processors now also use lManager instead of uManager.
|
||||||
|
- `multi.hold(n,opt)` now supports an option table like thread.hold does.
|
||||||
|
- Connection Objects now pass on the parent object if created on a multiobj. This was to allow chaining to work properly with the new update
|
||||||
|
|
||||||
|
```lua
|
||||||
|
multi,thread = require("multi"):init()
|
||||||
|
|
||||||
|
loop = multi:newTLoop()
|
||||||
|
|
||||||
|
function loop:testing()
|
||||||
|
print("testing haha")
|
||||||
|
end
|
||||||
|
|
||||||
|
loop:Set(1)
|
||||||
|
t = loop:OnLoop(function()
|
||||||
|
print("Looping...")
|
||||||
|
end):testing()
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
|
|
||||||
|
--[[Returns as expected:
|
||||||
|
|
||||||
|
testing haha
|
||||||
|
Looping...
|
||||||
|
Looping...
|
||||||
|
Looping...
|
||||||
|
...
|
||||||
|
Looping...
|
||||||
|
Looping...
|
||||||
|
Looping...
|
||||||
|
]]
|
||||||
|
```
|
||||||
|
|
||||||
|
While chaining on the OnSomeEventMethod() wasn't really a used feature, I still wanted to keep it just incase someone was relying on this working. And it does have it uses
|
||||||
|
|
||||||
|
- All Multi Objects now use Connection objects
|
||||||
|
|
||||||
|
`multiobj:OnSomeEvent(func)` or `multiobj.OnSomeEvent(func)`
|
||||||
|
|
||||||
|
- Connection Objects no longer Fire with syntax sugar when attached to an object:
|
||||||
|
|
||||||
|
`multiobj:OnSomeEvent(...)` No longer triggers the Fire event. As part of the update to make all objects use connections internally this little used feature had to be scrapped!
|
||||||
|
|
||||||
|
- multi:newTStep now derives it's functionality from multi:newStep (Cut's down on code length a bit)
|
||||||
|
|
||||||
|
Removed:
|
||||||
|
---
|
||||||
|
- `multi:getTasksDetails()` Remade completely and now called `multi:getStats()`
|
||||||
|
- `multi:getError()` Removed when setting protect was removed
|
||||||
|
- `multi:FreeMainEvent()` The new changes with connections make's this function unnecessary
|
||||||
|
- `multi:OnMainConnect(func)` See above
|
||||||
|
- `multi:connectFinal(func)` See above
|
||||||
|
- `multi:lightloop()` Cleaned up the mainloop/uManager method, actually faster than lightloop (Which should have been called liteloop)
|
||||||
|
- `multi:threadloop()` See above for reasons
|
||||||
|
- `multi setting: protect` This added extra complexity to the mainloop and not much benefit. If you feel a function will error use pcall yourself. This saves a decent amount of cycles, about 6.25% increase in performance.
|
||||||
|
- `multi:GetParentProcess()` use `multi.getCurrentProcess()` instead
|
||||||
|
- priority scheme 2, 3 and auto-priority have been removed! Only priority scheme 1 actually performed in a reasonable fashion so that one remained.
|
||||||
|
- `multi:newFunction(func)`
|
||||||
|
- `thread:newFunction(func)` Has many more features and replaces what multi:newFunction did
|
||||||
|
- `multi.holdFor()` Now that multi.hold takes the option table that thread.hold has this feature can be emulated using that.
|
||||||
|
|
||||||
|
- Calling Fire on a connection no longer returns anything! Now that internal features use connections, I noticed how slow connections are and have increased their speed quite a bit. From 50,000 Steps per seconds to almost 7 Million. All other features should work just fine. Only returning values has been removed
|
||||||
|
|
||||||
|
Fixed:
|
||||||
|
---
|
||||||
|
|
||||||
|
- [Issue](https://github.com/rayaman/multi/issues/30) with Lanes crashing the lua state. Issue seemed to be related to my filesystem, since remounting the drive caused the issue to stop. (Windows)
|
||||||
|
|
||||||
|
- [Issue](https://github.com/rayaman/multi/issues/29) where System threaded functions not being up to date with threaded functions
|
||||||
|
|
||||||
|
- Issue where gettasksdetails() would try to process a destroyed object causing it to crash
|
||||||
|
|
||||||
|
- Issue with multi.hold() not pumping the mainloop and only the scheduler
|
||||||
|
|
||||||
|
ToDo:
|
||||||
|
---
|
||||||
|
|
||||||
|
- Work on network parallelism
|
||||||
|
|
||||||
|
|
||||||
# Update 15.1.0 - Hold the thread!
|
# Update 15.1.0 - Hold the thread!
|
||||||
|
|
||||||
Full Update Showcase
|
Full Update Showcase
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;"..package.path
|
local multi,thread = require("multi"):init()
|
||||||
multi,thread = require("multi"):init()
|
|
||||||
|
|
||||||
func = thread:newFunction(function(count)
|
func = thread:newFunction(function(count)
|
||||||
local a = 0
|
local a = 0
|
||||||
@ -98,17 +406,17 @@ multi:mainloop()
|
|||||||
Added:
|
Added:
|
||||||
---
|
---
|
||||||
|
|
||||||
## multi:newSystemThreadedJobQueue(n) isEmpty()
|
- multi:newSystemThreadedJobQueue(n)
|
||||||
|
|
||||||
- returns true if the queue is empty, false if there are items in the queue.
|
`queue:isEmpty()`
|
||||||
|
|
||||||
|
Returns true if the queue is empty, false if there are items in the queue.
|
||||||
|
|
||||||
**Note:** a queue might be empty, but the job may still be running and not finished yet! Also if a registered function is called directly instead of pushed, it will not reflect inside the queue until the next cycle!
|
**Note:** a queue might be empty, but the job may still be running and not finished yet! Also if a registered function is called directly instead of pushed, it will not reflect inside the queue until the next cycle!
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```lua
|
```lua
|
||||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
local multi,thread = require("multi"):init()
|
||||||
package.cpath = [[C:\Program Files (x86)\Lua\5.1\systree\lib\lua\5.1\?.dll;C:\Program Files (x86)\Lua\5.1\systree\lib\lua\5.1\?\core.dll;]] ..package.cpath
|
|
||||||
multi,thread = require("multi"):init()
|
|
||||||
GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
||||||
|
|
||||||
jq = multi:newSystemThreadedJobQueue(5) -- Job queue with 4 worker threads
|
jq = multi:newSystemThreadedJobQueue(5) -- Job queue with 4 worker threads
|
||||||
@ -153,8 +461,7 @@ multi:mainloop()
|
|||||||
## multi:newProcessor(name)
|
## multi:newProcessor(name)
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;"..package.path
|
local multi,thread = require("multi"):init()
|
||||||
multi,thread = require("multi"):init()
|
|
||||||
|
|
||||||
-- Create a processor object, it works a lot like the multi object
|
-- Create a processor object, it works a lot like the multi object
|
||||||
sandbox = multi:newProcessor()
|
sandbox = multi:newProcessor()
|
||||||
@ -227,8 +534,7 @@ Can be chained as long as you want! See example below
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;"..package.path
|
local multi,thread = require("multi"):init()
|
||||||
multi,thread = require("multi"):init()
|
|
||||||
|
|
||||||
func = thread:newFunction(function(count)
|
func = thread:newFunction(function(count)
|
||||||
local a = 0
|
local a = 0
|
||||||
@ -283,8 +589,7 @@ Changed:
|
|||||||
holdMe(set) | Sets the holdme argument that existed at function creation
|
holdMe(set) | Sets the holdme argument that existed at function creation
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;"..package.path
|
local multi, thread = require("multi"):init()
|
||||||
multi, thread = require("multi"):init()
|
|
||||||
|
|
||||||
test = thread:newFunction(function(a,b)
|
test = thread:newFunction(function(a,b)
|
||||||
thread.sleep(1)
|
thread.sleep(1)
|
||||||
@ -378,8 +683,7 @@ ToDo
|
|||||||
Full Update Showcase
|
Full Update Showcase
|
||||||
---
|
---
|
||||||
```lua
|
```lua
|
||||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
local multi,thread = require("multi"):init()
|
||||||
multi,thread = require("multi"):init()
|
|
||||||
GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your enviroment and uses what's available
|
||||||
|
|
||||||
jq = multi:newSystemThreadedJobQueue(4) -- Job queue with 4 worker threads
|
jq = multi:newSystemThreadedJobQueue(4) -- Job queue with 4 worker threads
|
||||||
@ -413,6 +717,7 @@ multi:mainloop()
|
|||||||
Note:
|
Note:
|
||||||
---
|
---
|
||||||
This was supposed to be released over a year ago, but work and other things got in my way. Pesudo Threading now works. The goal of this is so you can write modules that can be scaled up to utilize threading features when available.
|
This was supposed to be released over a year ago, but work and other things got in my way. Pesudo Threading now works. The goal of this is so you can write modules that can be scaled up to utilize threading features when available.
|
||||||
|
|
||||||
Added:
|
Added:
|
||||||
---
|
---
|
||||||
- multi:newISOThread(name,func,env)
|
- multi:newISOThread(name,func,env)
|
||||||
@ -448,7 +753,6 @@ Todo:
|
|||||||
Full Update Showcase
|
Full Update Showcase
|
||||||
---
|
---
|
||||||
```lua
|
```lua
|
||||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
|
||||||
local multi,thread = require("multi"):init()
|
local multi,thread = require("multi"):init()
|
||||||
|
|
||||||
-- Testing destroying and fixed connections
|
-- Testing destroying and fixed connections
|
||||||
@ -515,7 +819,6 @@ Fixed:
|
|||||||
- Issue with connections not returning a handle for managing a specific conn object.
|
- Issue with connections not returning a handle for managing a specific conn object.
|
||||||
- Issue with connections where connection chaining wasn't working properly. This has been addressed.
|
- Issue with connections where connection chaining wasn't working properly. This has been addressed.
|
||||||
```lua
|
```lua
|
||||||
package.path="?.lua;?/init.lua;?.lua;?/?/init.lua;"..package.path
|
|
||||||
local multi,thread = require("multi"):init()
|
local multi,thread = require("multi"):init()
|
||||||
test = multi:newConnection()
|
test = multi:newConnection()
|
||||||
test(function(hmm)
|
test(function(hmm)
|
||||||
@ -568,7 +871,6 @@ Full Update Showcase
|
|||||||
---
|
---
|
||||||
Something I plan on doing each version going forward
|
Something I plan on doing each version going forward
|
||||||
```lua
|
```lua
|
||||||
package.path="?.lua;?/init.lua;?.lua;"..package.path
|
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
GLOBAL,THREAD = require("multi.integration.lanesManager"):init()
|
GLOBAL,THREAD = require("multi.integration.lanesManager"):init()
|
||||||
serv = multi:newService(function(self,data)
|
serv = multi:newService(function(self,data)
|
||||||
@ -790,19 +1092,21 @@ Added:
|
|||||||
-- If the created function encounters an error, it will return nil, the error message!
|
-- If the created function encounters an error, it will return nil, the error message!
|
||||||
- special variable multi.NIL was added to allow error handling in threaded functions.
|
- special variable multi.NIL was added to allow error handling in threaded functions.
|
||||||
-- multi.NIL can be used in to force a nil value when using thread.hold()
|
-- multi.NIL can be used in to force a nil value when using thread.hold()
|
||||||
- All functions created in the root of a thread are now converted to threaded functions, which allow for wait and connect features. **Note:** these functions are local to the function! And are only converted if they aren't set as local! Otherwise the function
|
- All functions created in the root of a thread are now converted to threaded functions, which allow for wait and connect features.
|
||||||
|
|
||||||
|
**Note:** these functions are local to the function! And are only converted if they aren't set as local! Otherwise the function is converted into a threaded function
|
||||||
|
|
||||||
- lanes threads can now have their priority set using: sThread.priority =
|
- lanes threads can now have their priority set using: sThread.priority =
|
||||||
-- thread.Priority_Core
|
- thread.Priority_Core
|
||||||
-- thread.Priority_High
|
- thread.Priority_High
|
||||||
-- thread.Priority_Above_Normal
|
- thread.Priority_Above_Normal
|
||||||
-- thread.Priority_Normal
|
- thread.Priority_Normal
|
||||||
-- thread.Priority_Below_Normal
|
- thread.Priority_Below_Normal
|
||||||
-- thread.Priority_Low
|
- thread.Priority_Low
|
||||||
-- thread.Priority_Idle
|
- thread.Priority_Idle
|
||||||
- thread.hold() and multi.hold() now accept connections as an argument. See example below
|
- thread.hold() and multi.hold() now accept connections as an argument. See example below
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;"..package.path
|
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init()
|
||||||
conn = multi:newConnection()
|
conn = multi:newConnection()
|
||||||
multi:newThread(function()
|
multi:newThread(function()
|
||||||
@ -833,7 +1137,6 @@ end)
|
|||||||
|
|
||||||
thread newFunction using auto convert
|
thread newFunction using auto convert
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;" .. package.path
|
|
||||||
multi, thread = require("multi").init()
|
multi, thread = require("multi").init()
|
||||||
a=5
|
a=5
|
||||||
multi:newThread("Test",function()
|
multi:newThread("Test",function()
|
||||||
@ -871,7 +1174,7 @@ Changed:
|
|||||||
---
|
---
|
||||||
- Connections connect function can now chain connections
|
- Connections connect function can now chain connections
|
||||||
```lua
|
```lua
|
||||||
package.path = "./?/init.lua;"..package.path
|
|
||||||
local multi, thread = require("multi").init()
|
local multi, thread = require("multi").init()
|
||||||
test = multi:newConnection()
|
test = multi:newConnection()
|
||||||
test(function(a)
|
test(function(a)
|
||||||
@ -1069,7 +1372,6 @@ Added:
|
|||||||
- STC: FireTo(id,...) — Described above.
|
- STC: FireTo(id,...) — Described above.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
local multi = require("multi")
|
local multi = require("multi")
|
||||||
conn = multi:newConnector()
|
conn = multi:newConnector()
|
||||||
conn.OnTest = multi:newConnection()
|
conn.OnTest = multi:newConnection()
|
||||||
@ -1141,7 +1443,6 @@ Going forward:
|
|||||||
Example
|
Example
|
||||||
---
|
---
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
multi = require("multi")
|
multi = require("multi")
|
||||||
GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
||||||
jq = multi:newSystemThreadedJobQueue()
|
jq = multi:newSystemThreadedJobQueue()
|
||||||
@ -1203,7 +1504,7 @@ L: 6543
|
|||||||
I: 1635
|
I: 1635
|
||||||
~n=n*4
|
~n=n*4
|
||||||
```
|
```
|
||||||
P3 Ignores using a basic funceion and instead bases its processing time on the amount of cpu time is there. If cpu-time is low and a process is set at a lower priority it will get its time reduced. There is no formula, at idle almost all process work at the same speed!
|
P3 Ignores using a basic function and instead bases its processing time on the amount of cpu time is there. If cpu-time is low and a process is set at a lower priority it will get its time reduced. There is no formula, at idle almost all process work at the same speed!
|
||||||
```
|
```
|
||||||
C: 2120906
|
C: 2120906
|
||||||
H: 2120906
|
H: 2120906
|
||||||
@ -1218,10 +1519,10 @@ Auto Priority works by seeing what should be set high or low. Due to lua not hav
|
|||||||
|
|
||||||
**Improved:**
|
**Improved:**
|
||||||
- Performance at the base level has been doubled! On my machine benchmark went from ~9mil to ~20 mil steps/s.
|
- Performance at the base level has been doubled! On my machine benchmark went from ~9mil to ~20 mil steps/s.
|
||||||
Note: If you write slow code this library's improbements wont make much of a difference.
|
Note: If you write slow code this library's improvements wont make much of a difference.
|
||||||
- Loops have been optimised as well! Being the most used objects I felt they needed to be made as fast as possible
|
- Loops have been optimised as well! Being the most used objects I felt they needed to be made as fast as possible
|
||||||
|
|
||||||
I usually give an example of the changes made, but this time I have an explantion for multi.nextStep(). It's not an entirely new feature since multi:newJob() does something like this, but is completely different. nextStep addes a function that is executed first on the next step. If multiple things are added to next step, then they will be executed in the order that they were added.
|
I usually give an example of the changes made, but this time I have an explantion for `multi.nextStep()`. It's not an entirely new feature since multi:newJob() does something like this, but is completely different. nextStep adds a function that is executed first on the next step. If multiple things are added to next step, then they will be executed in the order that they were added.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
The upper limit of this libraries performance on my machine is ~39mil. This is simply a while loop counting up from 0 and stops after 1 second. The 20mil that I am currently getting is probably as fast as it can get since its half of the max performance possible, and each layer I have noticed that it doubles complexity. Throughout the years with this library I have seen massive improvements in speed. In the beginning we had only ~2000 steps per second. Fast right? then after some tweaks we went to about 300000 steps per second, then 600000. Some more tweaks brought me to ~1mil steps per second, then to ~4 mil then ~9 mil and now finally ~20 mil... the doubling effect that i have now been seeing means that odds are I have reach the limit. I will aim to add more features and optimize individule objects. If its possible to make the library even faster then I will go for it.
|
The upper limit of this libraries performance on my machine is ~39mil. This is simply a while loop counting up from 0 and stops after 1 second. The 20mil that I am currently getting is probably as fast as it can get since its half of the max performance possible, and each layer I have noticed that it doubles complexity. Throughout the years with this library I have seen massive improvements in speed. In the beginning we had only ~2000 steps per second. Fast right? then after some tweaks we went to about 300000 steps per second, then 600000. Some more tweaks brought me to ~1mil steps per second, then to ~4 mil then ~9 mil and now finally ~20 mil... the doubling effect that i have now been seeing means that odds are I have reach the limit. I will aim to add more features and optimize individule objects. If its possible to make the library even faster then I will go for it.
|
||||||
@ -1235,10 +1536,9 @@ Fixed:
|
|||||||
Changed:
|
Changed:
|
||||||
---
|
---
|
||||||
- thread.hold() now returns the arguments that were pass by the event function
|
- thread.hold() now returns the arguments that were pass by the event function
|
||||||
- event objexts now contain a copy of what returns were made by the function that called it in a table called returns that exist inside of the object
|
- event objects now contain a copy of what returns were made by the function that called it in a table called returns that exist inside of the object
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
multi = require("multi")
|
multi = require("multi")
|
||||||
local a = 0
|
local a = 0
|
||||||
multi:newThread("test",function()
|
multi:newThread("test",function()
|
||||||
@ -1335,7 +1635,6 @@ Now there is a little trick you can do. If you combine both networkmanager and s
|
|||||||
|
|
||||||
**NodeManager.lua**
|
**NodeManager.lua**
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
multi = require("multi")
|
multi = require("multi")
|
||||||
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
||||||
nGLOBAL = require("multi.integration.networkManager").init()
|
nGLOBAL = require("multi.integration.networkManager").init()
|
||||||
@ -1354,7 +1653,6 @@ Side note: I had a setting called cross talk that would allow nodes to talk to e
|
|||||||
|
|
||||||
**Node.lua**
|
**Node.lua**
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
multi = require("multi")
|
multi = require("multi")
|
||||||
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
||||||
nGLOBAL = require("multi.integration.networkManager").init()
|
nGLOBAL = require("multi.integration.networkManager").init()
|
||||||
@ -1376,10 +1674,8 @@ multi:mainloop(settings)
|
|||||||
|
|
||||||
**Master.lua**
|
**Master.lua**
|
||||||
```lua
|
```lua
|
||||||
-- set up the package
|
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
-- Import the libraries
|
-- Import the libraries
|
||||||
multi = require("multi")
|
local multi = require("multi")
|
||||||
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
local GLOBAL, THREAD = require("multi.integration.lanesManager").init()
|
||||||
nGLOBAL = require("multi.integration.networkManager").init()
|
nGLOBAL = require("multi.integration.networkManager").init()
|
||||||
-- Act as a master node
|
-- Act as a master node
|
||||||
@ -1549,7 +1845,6 @@ Added:
|
|||||||
|
|
||||||
Example of threaded connections
|
Example of threaded connections
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
local GLOBAL,THREAD=require("multi.integration.lanesManager").init()
|
local GLOBAL,THREAD=require("multi.integration.lanesManager").init()
|
||||||
multi:newSystemThread("Test_Thread_1",function()
|
multi:newSystemThread("Test_Thread_1",function()
|
||||||
connOut = THREAD.waitFor("ConnectionNAMEHERE"):init()
|
connOut = THREAD.waitFor("ConnectionNAMEHERE"):init()
|
||||||
@ -1586,7 +1881,6 @@ Fixed:
|
|||||||
|
|
||||||
Example of threaded tables
|
Example of threaded tables
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;?.lua;"..package.path
|
|
||||||
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
|
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
|
||||||
multi:newSystemThread("Test_Thread_1",function()
|
multi:newSystemThread("Test_Thread_1",function()
|
||||||
require("multi")
|
require("multi")
|
||||||
@ -1912,7 +2206,6 @@ Added:</br>
|
|||||||
Using multi:systemThreadedBenchmark()
|
Using multi:systemThreadedBenchmark()
|
||||||
---
|
---
|
||||||
```lua
|
```lua
|
||||||
package.path="?/init.lua;"..package.path
|
|
||||||
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
|
local GLOBAL,sThread=require("multi.integration.lanesManager").init()
|
||||||
multi:systemThreadedBenchmark(3):OnBench(function(self,count)
|
multi:systemThreadedBenchmark(3):OnBench(function(self,count)
|
||||||
print("First Bench: "..count)
|
print("First Bench: "..count)
|
||||||
@ -1935,41 +2228,6 @@ GLOBAL,sThread=require("multi.integration.loveManager").init() -- load the love2
|
|||||||
-- Also, each thread has a .1 second delay! This is used to generate a random value for each thread!
|
-- Also, each thread has a .1 second delay! This is used to generate a random value for each thread!
|
||||||
require("core.GuiManager")
|
require("core.GuiManager")
|
||||||
gui.ff.Color=Color.Black
|
gui.ff.Color=Color.Black
|
||||||
function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends
|
|
||||||
local c={}
|
|
||||||
c.name=name
|
|
||||||
if love then
|
|
||||||
if love.thread then
|
|
||||||
function c:init()
|
|
||||||
self.chan=love.thread.getChannel(self.name)
|
|
||||||
function self:push(v)
|
|
||||||
self.chan:push(v)
|
|
||||||
end
|
|
||||||
function self:pop()
|
|
||||||
return self.chan:pop()
|
|
||||||
end
|
|
||||||
GLOBAL[self.name]=self
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
return c
|
|
||||||
else
|
|
||||||
error("Make sure you required the love.thread module!")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
c.linda=lanes.linda()
|
|
||||||
function c:push(v)
|
|
||||||
self.linda:send("Q",v)
|
|
||||||
end
|
|
||||||
function c:pop()
|
|
||||||
return ({self.linda:receive(0,"Q")})[2]
|
|
||||||
end
|
|
||||||
function c:init()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
GLOBAL[name]=c
|
|
||||||
end
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
queue=multi:newSystemThreadedQueue("QUEUE"):init()
|
queue=multi:newSystemThreadedQueue("QUEUE"):init()
|
||||||
queue:push("This is a test")
|
queue:push("This is a test")
|
||||||
queue:push("This is a test2")
|
queue:push("This is a test2")
|
||||||
@ -2251,7 +2509,7 @@ Change:
|
|||||||
|
|
||||||
Upcomming:
|
Upcomming:
|
||||||
---
|
---
|
||||||
- Threaded objects wrapped in corutines, so you can hold/sleep without problems!
|
- Threaded objects wrapped in coroutines, so you can hold/sleep without problems!
|
||||||
|
|
||||||
# Update: 1.4.0 (3/20/2017)
|
# Update: 1.4.0 (3/20/2017)
|
||||||
Added:
|
Added:
|
||||||
@ -2325,8 +2583,10 @@ Added:
|
|||||||
# Update: 1.2.0 (12.31.2016)
|
# Update: 1.2.0 (12.31.2016)
|
||||||
Added:
|
Added:
|
||||||
---
|
---
|
||||||
- connectionobj.getConnection(name) — returns a list of an instance (or instances) of a single connect made with connectionobj:connect(func,name) or connectionobj(func,name) if you can orginize data before hand you can route info to certain connections thus saving a lot of cpu time.
|
- connectionobj.getConnection(name) — returns a list of an instance (or instances) of a single connect made with connectionobj:connect(func,name) or connectionobj(func,name) if you can organize data before hand you can route info to certain connections thus saving a lot of cpu time.
|
||||||
|
|
||||||
**NOTE:** Only one name per each connection... you can't have 2 of the same names in a dictonary... the last one will be used
|
**NOTE:** Only one name per each connection... you can't have 2 of the same names in a dictonary... the last one will be used
|
||||||
|
|
||||||
Changed:
|
Changed:
|
||||||
---
|
---
|
||||||
- Started keeping track of dates
|
- Started keeping track of dates
|
||||||
@ -2385,6 +2645,7 @@ Changed:
|
|||||||
Changed:
|
Changed:
|
||||||
---
|
---
|
||||||
- Everything, complete restructuring of the library from function based to object based. Resembles the modern version of the library
|
- Everything, complete restructuring of the library from function based to object based. Resembles the modern version of the library
|
||||||
|
|
||||||
Added:
|
Added:
|
||||||
---
|
---
|
||||||
- Love2d support basic
|
- Love2d support basic
|
||||||
|
|||||||
19
makeENV.lua
Normal file
19
makeENV.lua
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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
Executable file
31
makeENV.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/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
|
||||||
@ -1,273 +0,0 @@
|
|||||||
--[[
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
]]
|
|
||||||
if table.unpack then
|
|
||||||
unpack=table.unpack
|
|
||||||
end
|
|
||||||
function table.val_to_str ( v )
|
|
||||||
if "string" == type( v ) then
|
|
||||||
v = string.gsub( v, "\n", "\\n" )
|
|
||||||
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
|
|
||||||
return "'" .. v .. "'"
|
|
||||||
end
|
|
||||||
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
|
|
||||||
else
|
|
||||||
return "table" == type( v ) and table.tostring( v ) or
|
|
||||||
tostring( v )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.key_to_str ( k )
|
|
||||||
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
|
|
||||||
return k
|
|
||||||
else
|
|
||||||
return "[" .. table.val_to_str( k ) .. "]"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.tostring( tbl )
|
|
||||||
local result, done = {}, {}
|
|
||||||
for k, v in ipairs( tbl ) do
|
|
||||||
table.insert( result, table.val_to_str( v ) )
|
|
||||||
done[ k ] = true
|
|
||||||
end
|
|
||||||
for k, v in pairs( tbl ) do
|
|
||||||
if not done[ k ] then
|
|
||||||
table.insert( result,
|
|
||||||
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return "{" .. table.concat( result, "," ) .. "}"
|
|
||||||
end
|
|
||||||
function table.merge(t1, t2)
|
|
||||||
t1,t2= t1 or {},t2 or {}
|
|
||||||
for k,v in pairs(t2) do
|
|
||||||
if type(v) == "table" then
|
|
||||||
if type(t1[k] or false) == "table" then
|
|
||||||
table.merge(t1[k] or {}, t2[k] or {})
|
|
||||||
else
|
|
||||||
t1[k] = v
|
|
||||||
end
|
|
||||||
else
|
|
||||||
t1[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return t1
|
|
||||||
end
|
|
||||||
Library={}
|
|
||||||
function Library.inject(lib,dat,arg)
|
|
||||||
if type(lib)=="table" then
|
|
||||||
if type(dat)=="table" then
|
|
||||||
table.merge(lib,dat)
|
|
||||||
elseif type(dat)=="string" then
|
|
||||||
if lib.Version and dat:match("(%d-)%.(%d-)%.(%d-)") then
|
|
||||||
lib.Version={dat:match("(%d+)%.(%d+)%.(%d+)")}
|
|
||||||
elseif dat=="meta" and type(arg)=="table" then
|
|
||||||
local _mt=getmetatable(lib) or {}
|
|
||||||
local mt={}
|
|
||||||
table.merge(mt,arg)
|
|
||||||
table.merge(_mt,mt)
|
|
||||||
setmetatable(lib,_mt)
|
|
||||||
elseif dat=="compat" then
|
|
||||||
lib["getVersion"]=function(self) return self.Version[1].."."..self.Version[2].."."..self.Version[3] end
|
|
||||||
if not lib.Version then
|
|
||||||
lib.Version={1,0,0}
|
|
||||||
end
|
|
||||||
elseif dat=="inhert" then
|
|
||||||
if not(lib["!%"..arg.."%!"]) then print("Wrong Password!!") return end
|
|
||||||
lib["!%"..arg.."%!"].__index=lib["!!%"..arg.."%!!"]
|
|
||||||
end
|
|
||||||
elseif type(dat)=="function" then
|
|
||||||
for i,v in pairs(lib) do
|
|
||||||
dat(lib,i,v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif type(lib)=="function" or type(lib)=="userdata" then
|
|
||||||
if lib==unpack then
|
|
||||||
print("function unpack cannot yet be injected!")
|
|
||||||
return unpack
|
|
||||||
elseif lib==pairs then
|
|
||||||
print("function pairs cannot yet be injected!")
|
|
||||||
return lib
|
|
||||||
elseif lib==ipairs then
|
|
||||||
print("function ipairs cannot yet be injected!")
|
|
||||||
return lib
|
|
||||||
elseif lib==type then
|
|
||||||
print("function type cannot yet be injected!")
|
|
||||||
return lib
|
|
||||||
end
|
|
||||||
temp={}
|
|
||||||
local mt={
|
|
||||||
__call=function(t,...)
|
|
||||||
local consume,MainRet,init={},{},{...}
|
|
||||||
local tt={}
|
|
||||||
for i=1,#t.__Link do
|
|
||||||
tt={}
|
|
||||||
if t.__Link[i]==t.__Main then
|
|
||||||
if #consume~=0 then
|
|
||||||
MainRet={t.__Link[i](unpack(consume))}
|
|
||||||
else
|
|
||||||
MainRet={t.__Link[i](unpack(init))}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if i==1 then
|
|
||||||
consume=(t.__Link[i](unpack(init)))
|
|
||||||
else
|
|
||||||
if type(MainRet)=="table" then
|
|
||||||
table.merge(tt,MainRet)
|
|
||||||
end
|
|
||||||
if type(consume)=="table" then
|
|
||||||
table.merge(tt,consume)
|
|
||||||
end
|
|
||||||
consume={t.__Link[i](unpack(tt))}
|
|
||||||
end
|
|
||||||
if i==#t.__Link then
|
|
||||||
return unpack(consume)
|
|
||||||
end
|
|
||||||
if consume then if consume[0]=="\1\7\6\3\2\99\125" then consume[0]=nil return unpack(consume) end end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(MainRet)=="table" then
|
|
||||||
table.merge(tt,MainRet)
|
|
||||||
end
|
|
||||||
if type(consume)=="table" then
|
|
||||||
table.merge(tt,consume)
|
|
||||||
end
|
|
||||||
return unpack(tt)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
temp.__Link={lib}
|
|
||||||
temp.__Main=lib
|
|
||||||
temp.__self=temp
|
|
||||||
function temp:inject(func,i)
|
|
||||||
if i then
|
|
||||||
table.insert(self.__Link,i,func)
|
|
||||||
else
|
|
||||||
table.insert(self.__Link,func)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function temp:consume(func)
|
|
||||||
for i=1,#self.__Link do
|
|
||||||
if self.__Link[i]==self.__Main then
|
|
||||||
self.__Link[i]=func
|
|
||||||
self.__self.__Main=func
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
setmetatable(temp,mt)
|
|
||||||
return temp
|
|
||||||
else
|
|
||||||
return "arg1 must be a table or a function"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function Library.convert(...)
|
|
||||||
local temp,rets={...},{}
|
|
||||||
for i=1,#temp do
|
|
||||||
if type(temp[i])=="function" then
|
|
||||||
table.insert(rets,Library.inject(temp[i]))
|
|
||||||
else
|
|
||||||
error("Takes only functions and returns in order from functions given. arg # "..i.." is not a function!!! It is a "..type(temp[i]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return unpack(rets)
|
|
||||||
end
|
|
||||||
|
|
||||||
local link={MainLibrary=Library}
|
|
||||||
Library.inject(Library,"meta",{
|
|
||||||
__Link=link,
|
|
||||||
__call=function(self,func) func(link) end,
|
|
||||||
})
|
|
||||||
local multi, thread = require("multi").init()
|
|
||||||
os.sleep = love.timer.sleep
|
|
||||||
multi.drawF = {}
|
|
||||||
function multi:onDraw(func, i)
|
|
||||||
i = i or 1
|
|
||||||
table.insert(self.drawF, i, func)
|
|
||||||
end
|
|
||||||
multi.OnKeyPressed = multi:newConnection()
|
|
||||||
multi.OnKeyReleased = multi:newConnection()
|
|
||||||
multi.OnMousePressed = multi:newConnection()
|
|
||||||
multi.OnMouseReleased = multi:newConnection()
|
|
||||||
multi.OnMouseWheelMoved = multi:newConnection()
|
|
||||||
multi.OnMouseMoved = multi:newConnection()
|
|
||||||
multi.OnDraw = multi:newConnection()
|
|
||||||
multi.OnTextInput = multi:newConnection()
|
|
||||||
multi.OnUpdate = multi:newConnection()
|
|
||||||
multi.OnQuit = multi:newConnection()
|
|
||||||
multi.OnPreLoad(function()
|
|
||||||
local function Hook(func, conn)
|
|
||||||
if love[func] ~= nil then
|
|
||||||
love[func] = Library.convert(love[func])
|
|
||||||
love[func]:inject(function(...)
|
|
||||||
conn:Fire(...)
|
|
||||||
return {...}
|
|
||||||
end,1)
|
|
||||||
elseif love[func] == nil then
|
|
||||||
love[func] = function(...)
|
|
||||||
conn:Fire(...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Hook("quit", multi.OnQuit)
|
|
||||||
Hook("keypressed", multi.OnKeyPressed)
|
|
||||||
Hook("keyreleased", multi.OnKeyReleased)
|
|
||||||
Hook("mousepressed", multi.OnMousePressed)
|
|
||||||
Hook("mousereleased", multi.OnMouseReleased)
|
|
||||||
Hook("wheelmoved", multi.OnMouseWheelMoved)
|
|
||||||
Hook("mousemoved", multi.OnMouseMoved)
|
|
||||||
Hook("draw", multi.OnDraw)
|
|
||||||
Hook("textinput", multi.OnTextInput)
|
|
||||||
Hook("update", multi.OnUpdate)
|
|
||||||
multi.OnDraw(function()
|
|
||||||
for i = 1, #multi.drawF do
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
multi.drawF[i]()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
function multi:loveloop(light)
|
|
||||||
local link
|
|
||||||
link = multi:newThread(function()
|
|
||||||
local mainloop = love.run()
|
|
||||||
while true do
|
|
||||||
thread.yield()
|
|
||||||
pcall(mainloop)
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
|
||||||
end)
|
|
||||||
if light==false then
|
|
||||||
multi:mainloop()
|
|
||||||
else
|
|
||||||
multi:lightloop()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
multi.OnQuit(function()
|
|
||||||
multi.Stop()
|
|
||||||
love.event.quit()
|
|
||||||
end)
|
|
||||||
return multi
|
|
||||||
@ -1,281 +0,0 @@
|
|||||||
--[[
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
]]
|
|
||||||
if table.unpack then
|
|
||||||
unpack=table.unpack
|
|
||||||
end
|
|
||||||
function table.val_to_str ( v )
|
|
||||||
if "string" == type( v ) then
|
|
||||||
v = string.gsub( v, "\n", "\\n" )
|
|
||||||
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
|
|
||||||
return "'" .. v .. "'"
|
|
||||||
end
|
|
||||||
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
|
|
||||||
else
|
|
||||||
return "table" == type( v ) and table.tostring( v ) or
|
|
||||||
tostring( v )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.key_to_str ( k )
|
|
||||||
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
|
|
||||||
return k
|
|
||||||
else
|
|
||||||
return "[" .. table.val_to_str( k ) .. "]"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function table.tostring( tbl )
|
|
||||||
local result, done = {}, {}
|
|
||||||
for k, v in ipairs( tbl ) do
|
|
||||||
table.insert( result, table.val_to_str( v ) )
|
|
||||||
done[ k ] = true
|
|
||||||
end
|
|
||||||
for k, v in pairs( tbl ) do
|
|
||||||
if not done[ k ] then
|
|
||||||
table.insert( result,
|
|
||||||
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return "{" .. table.concat( result, "," ) .. "}"
|
|
||||||
end
|
|
||||||
function table.merge(t1, t2)
|
|
||||||
t1,t2= t1 or {},t2 or {}
|
|
||||||
for k,v in pairs(t2) do
|
|
||||||
if type(v) == "table" then
|
|
||||||
if type(t1[k] or false) == "table" then
|
|
||||||
table.merge(t1[k] or {}, t2[k] or {})
|
|
||||||
else
|
|
||||||
t1[k] = v
|
|
||||||
end
|
|
||||||
else
|
|
||||||
t1[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return t1
|
|
||||||
end
|
|
||||||
Library={}
|
|
||||||
function Library.inject(lib,dat,arg)
|
|
||||||
if type(lib)=="table" then
|
|
||||||
if type(dat)=="table" then
|
|
||||||
table.merge(lib,dat)
|
|
||||||
elseif type(dat)=="string" then
|
|
||||||
if lib.Version and dat:match("(%d-)%.(%d-)%.(%d-)") then
|
|
||||||
lib.Version={dat:match("(%d+)%.(%d+)%.(%d+)")}
|
|
||||||
elseif dat=="meta" and type(arg)=="table" then
|
|
||||||
local _mt=getmetatable(lib) or {}
|
|
||||||
local mt={}
|
|
||||||
table.merge(mt,arg)
|
|
||||||
table.merge(_mt,mt)
|
|
||||||
setmetatable(lib,_mt)
|
|
||||||
elseif dat=="compat" then
|
|
||||||
lib["getVersion"]=function(self) return self.Version[1].."."..self.Version[2].."."..self.Version[3] end
|
|
||||||
if not lib.Version then
|
|
||||||
lib.Version={1,0,0}
|
|
||||||
end
|
|
||||||
elseif dat=="inhert" then
|
|
||||||
if not(lib["!%"..arg.."%!"]) then print("Wrong Password!!") return end
|
|
||||||
lib["!%"..arg.."%!"].__index=lib["!!%"..arg.."%!!"]
|
|
||||||
end
|
|
||||||
elseif type(dat)=="function" then
|
|
||||||
for i,v in pairs(lib) do
|
|
||||||
dat(lib,i,v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif type(lib)=="function" or type(lib)=="userdata" then
|
|
||||||
if lib==unpack then
|
|
||||||
print("function unpack cannot yet be injected!")
|
|
||||||
return unpack
|
|
||||||
elseif lib==pairs then
|
|
||||||
print("function pairs cannot yet be injected!")
|
|
||||||
return lib
|
|
||||||
elseif lib==ipairs then
|
|
||||||
print("function ipairs cannot yet be injected!")
|
|
||||||
return lib
|
|
||||||
elseif lib==type then
|
|
||||||
print("function type cannot yet be injected!")
|
|
||||||
return lib
|
|
||||||
end
|
|
||||||
temp={}
|
|
||||||
local mt={
|
|
||||||
__call=function(t,...)
|
|
||||||
local consume,MainRet,init={},{},{...}
|
|
||||||
local tt={}
|
|
||||||
for i=1,#t.__Link do
|
|
||||||
tt={}
|
|
||||||
if t.__Link[i]==t.__Main then
|
|
||||||
if #consume~=0 then
|
|
||||||
MainRet={t.__Link[i](unpack(consume))}
|
|
||||||
else
|
|
||||||
MainRet={t.__Link[i](unpack(init))}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if i==1 then
|
|
||||||
consume=(t.__Link[i](unpack(init)))
|
|
||||||
else
|
|
||||||
if type(MainRet)=="table" then
|
|
||||||
table.merge(tt,MainRet)
|
|
||||||
end
|
|
||||||
if type(consume)=="table" then
|
|
||||||
table.merge(tt,consume)
|
|
||||||
end
|
|
||||||
consume={t.__Link[i](unpack(tt))}
|
|
||||||
end
|
|
||||||
if i==#t.__Link then
|
|
||||||
return unpack(consume)
|
|
||||||
end
|
|
||||||
if consume then if consume[0]=="\1\7\6\3\2\99\125" then consume[0]=nil return unpack(consume) end end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(MainRet)=="table" then
|
|
||||||
table.merge(tt,MainRet)
|
|
||||||
end
|
|
||||||
if type(consume)=="table" then
|
|
||||||
table.merge(tt,consume)
|
|
||||||
end
|
|
||||||
return unpack(tt)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
temp.__Link={lib}
|
|
||||||
temp.__Main=lib
|
|
||||||
temp.__self=temp
|
|
||||||
function temp:inject(func,i)
|
|
||||||
if i then
|
|
||||||
table.insert(self.__Link,i,func)
|
|
||||||
else
|
|
||||||
table.insert(self.__Link,func)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function temp:consume(func)
|
|
||||||
for i=1,#self.__Link do
|
|
||||||
if self.__Link[i]==self.__Main then
|
|
||||||
self.__Link[i]=func
|
|
||||||
self.__self.__Main=func
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
setmetatable(temp,mt)
|
|
||||||
return temp
|
|
||||||
else
|
|
||||||
return "arg1 must be a table or a function"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function Library.convert(...)
|
|
||||||
local temp,rets={...},{}
|
|
||||||
for i=1,#temp do
|
|
||||||
if type(temp[i])=="function" then
|
|
||||||
table.insert(rets,Library.inject(temp[i]))
|
|
||||||
else
|
|
||||||
error("Takes only functions and returns in order from functions given. arg # "..i.." is not a function!!! It is a "..type(temp[i]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return unpack(rets)
|
|
||||||
end
|
|
||||||
|
|
||||||
local link={MainLibrary=Library}
|
|
||||||
Library.inject(Library,"meta",{
|
|
||||||
__Link=link,
|
|
||||||
__call=function(self,func) func(link) end,
|
|
||||||
})
|
|
||||||
local multi, thread = require("multi").init()
|
|
||||||
os.sleep = lovr.timer.sleep
|
|
||||||
multi.drawF = {}
|
|
||||||
function multi:onDraw(func, i)
|
|
||||||
i = i or 1
|
|
||||||
table.insert(self.drawF, i, func)
|
|
||||||
end
|
|
||||||
multi.OnKeyPressed = multi:newConnection()
|
|
||||||
multi.OnKeyReleased = multi:newConnection()
|
|
||||||
multi.OnErrHand = multi:newConnection()
|
|
||||||
multi.OnFocus = multi:newConnection()
|
|
||||||
multi.OnLoad = multi:newConnection()
|
|
||||||
multi.OnLog = multi:newConnection()
|
|
||||||
multi.OnPermission = multi:newConnection()
|
|
||||||
multi.OnResize = multi:newConnection()
|
|
||||||
multi.OnRestart = multi:newConnection()
|
|
||||||
multi.OnThreadError = multi:newConnection()
|
|
||||||
multi.OnDraw = multi:newConnection()
|
|
||||||
multi.OnTextInput = multi:newConnection()
|
|
||||||
multi.OnUpdate = multi:newConnection()
|
|
||||||
multi.OnQuit = multi:newConnection()
|
|
||||||
multi.OnPreLoad(function()
|
|
||||||
local function Hook(func, conn)
|
|
||||||
if lovr[func] ~= nil then
|
|
||||||
lovr[func] = Library.convert(lovr[func])
|
|
||||||
lovr[func]:inject(function(...)
|
|
||||||
conn:Fire(...)
|
|
||||||
return {...}
|
|
||||||
end,1)
|
|
||||||
elseif lovr[func] == nil then
|
|
||||||
lovr[func] = function(...)
|
|
||||||
conn:Fire(...)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Hook("quit", multi.OnQuit)
|
|
||||||
Hook("keypressed", multi.OnKeyPressed)
|
|
||||||
Hook("keyreleased", multi.OnKeyReleased)
|
|
||||||
Hook("focus", multi.OnFocus)
|
|
||||||
Hook("log", multi.OnLog)
|
|
||||||
Hook("errhand", multi.OnErrHand)
|
|
||||||
Hook("load", multi.OnLoad)
|
|
||||||
Hook("draw", multi.OnDraw)
|
|
||||||
Hook("textinput", multi.OnTextInput)
|
|
||||||
Hook("update", multi.OnUpdate)
|
|
||||||
Hook("permission", multi.OnPermission)
|
|
||||||
Hook("resize", multi.OnResize)
|
|
||||||
Hook("restart", multi.OnRestart)
|
|
||||||
Hook("threaderror", multi.OnThreadError)
|
|
||||||
multi.OnDraw(function()
|
|
||||||
for i = 1, #multi.drawF do
|
|
||||||
lovr.graphics.setColor(255, 255, 255, 255)
|
|
||||||
multi.drawF[i]()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
function multi:lovrloop(light)
|
|
||||||
local link
|
|
||||||
link = multi:newThread(function()
|
|
||||||
local mainloop = lovr.run()
|
|
||||||
while true do
|
|
||||||
thread.yield()
|
|
||||||
pcall(mainloop)
|
|
||||||
end
|
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
|
||||||
end)
|
|
||||||
if light==false then
|
|
||||||
multi:mainloop()
|
|
||||||
else
|
|
||||||
multi:lightloop()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
multi.OnQuit(function()
|
|
||||||
multi.Stop()
|
|
||||||
lovr.event.quit()
|
|
||||||
end)
|
|
||||||
return multi
|
|
||||||
2595
multi/init.lua
2595
multi/init.lua
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -113,7 +113,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end)
|
end)
|
||||||
end,holup),name
|
end,holup),name
|
||||||
end
|
end
|
||||||
multi:newThread("JobQueueManager",function()
|
thread:newThread("JobQueueManager",function()
|
||||||
while true do
|
while true do
|
||||||
local job = thread.hold(function()
|
local job = thread.hold(function()
|
||||||
return queueReturn:pop()
|
return queueReturn:pop()
|
||||||
@ -129,7 +129,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
local clock = os.clock
|
local clock = os.clock
|
||||||
local ref = 0
|
local ref = 0
|
||||||
setmetatable(_G,{__index = funcs})
|
setmetatable(_G,{__index = funcs})
|
||||||
multi:newThread("JobHandler",function()
|
thread:newThread("JobHandler",function()
|
||||||
while true do
|
while true do
|
||||||
local dat = thread.hold(function()
|
local dat = thread.hold(function()
|
||||||
return queueJob:pop()
|
return queueJob:pop()
|
||||||
@ -141,7 +141,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
queueReturn:push{jid, funcs[name](unpack(args)),queue}
|
queueReturn:push{jid, funcs[name](unpack(args)),queue}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
multi:newThread("DoAllHandler",function()
|
thread:newThread("DoAllHandler",function()
|
||||||
while true do
|
while true do
|
||||||
local dat = thread.hold(function()
|
local dat = thread.hold(function()
|
||||||
return doAll:peek()
|
return doAll:peek()
|
||||||
@ -156,7 +156,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
multi:newThread("IdleHandler",function()
|
thread:newThread("IdleHandler",function()
|
||||||
while true do
|
while true do
|
||||||
thread.hold(function()
|
thread.hold(function()
|
||||||
return clock()-idle>3
|
return clock()-idle>3
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -21,8 +21,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
package.path = "?/init.lua;?.lua;" .. package.path
|
package.path = "?/init.lua;?.lua;" .. package.path
|
||||||
multi, thread = require("multi").init() -- get it all and have it on all lanes
|
multi, thread = require("multi"):init() -- get it all and have it on all lanes
|
||||||
if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassle
|
if multi.integration then -- This allows us to call the lanes manager from supporting modules without a hassle
|
||||||
return {
|
return {
|
||||||
init = function()
|
init = function()
|
||||||
@ -34,138 +35,68 @@ end
|
|||||||
lanes = require("lanes").configure()
|
lanes = require("lanes").configure()
|
||||||
multi.SystemThreads = {}
|
multi.SystemThreads = {}
|
||||||
multi.isMainThread = true
|
multi.isMainThread = true
|
||||||
|
|
||||||
function multi:canSystemThread()
|
function multi:canSystemThread()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:getPlatform()
|
function multi:getPlatform()
|
||||||
return "lanes"
|
return "lanes"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Step 2 set up the Linda objects
|
-- Step 2 set up the Linda objects
|
||||||
local __GlobalLinda = lanes.linda() -- handles global stuff
|
local __GlobalLinda = lanes.linda() -- handles global stuff
|
||||||
local __SleepingLinda = lanes.linda() -- handles sleeping stuff
|
local __SleepingLinda = lanes.linda() -- handles sleeping stuff
|
||||||
local __ConsoleLinda = lanes.linda() -- handles console stuff
|
local __ConsoleLinda = lanes.linda() -- handles console stuff
|
||||||
multi:newLoop(function()
|
local __StatusLinda = lanes.linda() -- handles pushstatus for stfunctions
|
||||||
local _,data = __ConsoleLinda:receive(0, "Q")
|
|
||||||
if data then
|
local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda, __SleepingLinda, __StatusLinda)
|
||||||
print(unpack(data))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
local GLOBAL,THREAD = require("multi.integration.lanesManager.threads").init(__GlobalLinda,__SleepingLinda)
|
|
||||||
local threads = {}
|
|
||||||
local count = 1
|
local count = 1
|
||||||
local started = false
|
local started = false
|
||||||
local livingThreads = {}
|
local livingThreads = {}
|
||||||
|
|
||||||
function THREAD:newFunction(func,holdme)
|
function THREAD:newFunction(func,holdme)
|
||||||
local tfunc = {}
|
return thread:newFunctionBase(function(...)
|
||||||
tfunc.Active = true
|
return multi:newSystemThread("TempSystemThread",func,...)
|
||||||
function tfunc:Pause()
|
end,holdme)()
|
||||||
self.Active = false
|
|
||||||
end
|
|
||||||
function tfunc:Resume()
|
|
||||||
self.Active = true
|
|
||||||
end
|
|
||||||
function tfunc:holdMe(b)
|
|
||||||
holdme = b
|
|
||||||
end
|
|
||||||
local function noWait()
|
|
||||||
return nil, "Function is paused"
|
|
||||||
end
|
|
||||||
local rets, err
|
|
||||||
local function wait(no)
|
|
||||||
if thread.isThread() and not (no) then
|
|
||||||
return multi.hold(function()
|
|
||||||
if err then
|
|
||||||
return nil, err
|
|
||||||
elseif rets then
|
|
||||||
return unpack(rets)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
while not rets and not err do
|
|
||||||
multi.scheduler:Act()
|
|
||||||
end
|
|
||||||
if err then
|
|
||||||
return nil,err
|
|
||||||
end
|
|
||||||
return unpack(rets)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tfunc.__call = function(t,...)
|
|
||||||
if not t.Active then
|
|
||||||
if holdme then
|
|
||||||
return nil, "Function is paused"
|
|
||||||
end
|
|
||||||
return {
|
|
||||||
isTFunc = true,
|
|
||||||
wait = noWait,
|
|
||||||
connect = function(f)
|
|
||||||
f(nil,"Function is paused")
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
local t = multi:newSystemThread("SystemThreadedFunction",func,...)
|
|
||||||
t.OnDeath(function(self,...) rets = {...} end)
|
|
||||||
t.OnError(function(self,e) err = e end)
|
|
||||||
if holdme then
|
|
||||||
return wait()
|
|
||||||
end
|
|
||||||
local temp = {
|
|
||||||
OnStatus = multi:newConnection(),
|
|
||||||
OnError = multi:newConnection(),
|
|
||||||
OnReturn = multi:newConnection(),
|
|
||||||
isTFunc = true,
|
|
||||||
wait = wait,
|
|
||||||
connect = function(f)
|
|
||||||
local tempConn = multi:newConnection()
|
|
||||||
t.OnDeath(function(self,...) if f then f(...) else tempConn:Fire(...) end end)
|
|
||||||
t.OnError(function(self,err) if f then f(nil,err) else tempConn:Fire(nil,err) end end)
|
|
||||||
return tempConn
|
|
||||||
end
|
|
||||||
}
|
|
||||||
t.OnDeath(function(self,...) temp.OnReturn:Fire(...) end)
|
|
||||||
t.OnError(function(self,err) temp.OnError:Fire(err) end)
|
|
||||||
t.linkedFunction = temp
|
|
||||||
t.statusconnector = temp.OnStatus
|
|
||||||
return temp
|
|
||||||
end
|
|
||||||
setmetatable(tfunc,tfunc)
|
|
||||||
return tfunc
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi:newSystemThread(name, func, ...)
|
function multi:newSystemThread(name, func, ...)
|
||||||
multi.InitSystemThreadErrorHandler()
|
multi.InitSystemThreadErrorHandler()
|
||||||
rand = math.random(1, 10000000)
|
local rand = math.random(1, 10000000)
|
||||||
local c = {}
|
local return_linda = lanes.linda()
|
||||||
local __self = c
|
c = {}
|
||||||
c.name = name
|
c.name = name
|
||||||
c.Name = name
|
c.Name = name
|
||||||
c.Id = count
|
c.Id = count
|
||||||
c.loadString = {"base","package","os","io","math","table","string","coroutine"}
|
c.loadString = {"base","package","os","io","math","table","string","coroutine"}
|
||||||
livingThreads[count] = {true, name}
|
livingThreads[count] = {true, name}
|
||||||
|
c.returns = return_linda
|
||||||
c.Type = "sthread"
|
c.Type = "sthread"
|
||||||
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 args = {...}
|
c.thread = lanes.gen("*",
|
||||||
multi:newThread(function()
|
{
|
||||||
c.thread = lanes.gen(table.concat(c.loadString,","),
|
globals={ -- Set up some globals
|
||||||
{
|
THREAD_NAME = name,
|
||||||
globals={ -- Set up some globals
|
THREAD_ID = count,
|
||||||
THREAD_NAME=name,
|
THREAD = THREAD,
|
||||||
THREAD_ID=count,
|
GLOBAL = GLOBAL,
|
||||||
THREAD = THREAD,
|
_Console = __ConsoleLinda
|
||||||
GLOBAL = GLOBAL,
|
},
|
||||||
_Console = __ConsoleLinda
|
priority=c.priority
|
||||||
},
|
},function(...)
|
||||||
priority=c.priority
|
local has_error = true
|
||||||
},func)(unpack(args))
|
return_linda:set("returns",{func(...)})
|
||||||
thread.kill()
|
has_error = false
|
||||||
end)
|
end)(...)
|
||||||
count = count + 1
|
count = count + 1
|
||||||
|
function c:getName()
|
||||||
|
return c.Name
|
||||||
|
end
|
||||||
function c:kill()
|
function c:kill()
|
||||||
self.thread:cancel()
|
self.thread:cancel()
|
||||||
multi.print("Thread: '" .. self.name .. "' has been stopped!")
|
|
||||||
self.alive = false
|
self.alive = false
|
||||||
end
|
end
|
||||||
table.insert(multi.SystemThreads, c)
|
table.insert(multi.SystemThreads, c)
|
||||||
@ -175,59 +106,60 @@ function multi:newSystemThread(name, func, ...)
|
|||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
local function detectLuaError(str)
|
THREAD.newSystemThread = multi.newSystemThread
|
||||||
return type(str)=="string" and str:match("%.lua:%d*:")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function tableLen(tab)
|
|
||||||
local len = 0
|
|
||||||
for i,v in pairs(tab) do
|
|
||||||
len = len + 1
|
|
||||||
end
|
|
||||||
return len
|
|
||||||
end
|
|
||||||
|
|
||||||
function multi.InitSystemThreadErrorHandler()
|
function multi.InitSystemThreadErrorHandler()
|
||||||
if started == true then
|
if started == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
started = true
|
started = true
|
||||||
multi:newThread("ThreadErrorHandler",function()
|
thread:newThread("SystemThreadScheduler",function()
|
||||||
local threads = multi.SystemThreads
|
local threads = multi.SystemThreads
|
||||||
|
local _,data,status,push,temp
|
||||||
while true do
|
while true do
|
||||||
thread.sleep(.1) -- switching states often takes a huge hit on performance. half a second to tell me there is an error is good enough.
|
thread.yield()
|
||||||
|
_,data = __ConsoleLinda:receive(0, "Q")
|
||||||
for i = #threads, 1, -1 do
|
for i = #threads, 1, -1 do
|
||||||
local _,data = pcall(function()
|
temp = threads[i]
|
||||||
return {threads[i].thread:join(1)}
|
status = temp.thread.status
|
||||||
end)
|
push = __StatusLinda:get(temp.Id)
|
||||||
local v, err, t = data[1],data[2],data[3]
|
if push then
|
||||||
if detectLuaError(err) then
|
temp.statusconnector:Fire(unpack(({__StatusLinda:receive(nil, temp.Id)})[2]))
|
||||||
if err:find("Thread was killed!\1") then
|
end
|
||||||
livingThreads[threads[i].Id] = {false, threads[i].Name}
|
if status == "done" or temp.returns:get("returns") then
|
||||||
threads[i].alive = false
|
livingThreads[temp.Id] = {false, temp.Name}
|
||||||
threads[i].OnDeath:Fire(threads[i],nil,"Thread was killed!")
|
temp.alive = false
|
||||||
GLOBAL["__THREADS__"] = livingThreads
|
temp.OnDeath:Fire(unpack(({temp.returns:receive(0, "returns")})[2]))
|
||||||
table.remove(threads, i)
|
GLOBAL["__THREADS__"] = livingThreads
|
||||||
else
|
table.remove(threads, i)
|
||||||
threads[i].OnError:Fire(threads[i], err, "Error in systemThread: '" .. threads[i].name .. "' <" .. err .. ">")
|
elseif status == "running" then
|
||||||
threads[i].alive = false
|
--
|
||||||
livingThreads[threads[i].Id] = {false, threads[i].Name}
|
elseif status == "waiting" then
|
||||||
GLOBAL["__THREADS__"] = livingThreads
|
--
|
||||||
table.remove(threads, i)
|
elseif status == "error" then
|
||||||
end
|
livingThreads[temp.Id] = {false, temp.Name}
|
||||||
elseif tableLen(data)>0 then
|
temp.alive = false
|
||||||
livingThreads[threads[i].Id] = {false, threads[i].Name}
|
temp.OnError:Fire(temp,nil,unpack(temp.returns:receive(0,"returns") or {"Thread Killed!"}))
|
||||||
threads[i].alive = false
|
GLOBAL["__THREADS__"] = livingThreads
|
||||||
threads[i].OnDeath:Fire(threads[i],unpack(data))
|
table.remove(threads, i)
|
||||||
|
elseif status == "cancelled" then
|
||||||
|
livingThreads[temp.Id] = {false, temp.Name}
|
||||||
|
temp.alive = false
|
||||||
|
temp.OnError:Fire(temp,nil,"thread_cancelled")
|
||||||
|
GLOBAL["__THREADS__"] = livingThreads
|
||||||
|
table.remove(threads, i)
|
||||||
|
elseif status == "killed" then
|
||||||
|
livingThreads[temp.Id] = {false, temp.Name}
|
||||||
|
temp.alive = false
|
||||||
|
temp.OnError:Fire(temp,nil,"thread_killed")
|
||||||
GLOBAL["__THREADS__"] = livingThreads
|
GLOBAL["__THREADS__"] = livingThreads
|
||||||
table.remove(threads, i)
|
table.remove(threads, i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end).OnError(function(...)
|
|
||||||
print("Error!",...)
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
multi.print("Integrated Lanes!")
|
multi.print("Integrated Lanes!")
|
||||||
multi.integration = {} -- for module creators
|
multi.integration = {} -- for module creators
|
||||||
multi.integration.GLOBAL = GLOBAL
|
multi.integration.GLOBAL = GLOBAL
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -28,7 +28,8 @@ local function getOS()
|
|||||||
return "unix"
|
return "unix"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function INIT(__GlobalLinda,__SleepingLinda)
|
|
||||||
|
local function INIT(__GlobalLinda, __SleepingLinda, __StatusLinda)
|
||||||
local THREAD = {}
|
local THREAD = {}
|
||||||
THREAD.Priority_Core = 3
|
THREAD.Priority_Core = 3
|
||||||
THREAD.Priority_High = 2
|
THREAD.Priority_High = 2
|
||||||
@ -37,12 +38,15 @@ local function INIT(__GlobalLinda,__SleepingLinda)
|
|||||||
THREAD.Priority_Below_Normal = -1
|
THREAD.Priority_Below_Normal = -1
|
||||||
THREAD.Priority_Low = -2
|
THREAD.Priority_Low = -2
|
||||||
THREAD.Priority_Idle = -3
|
THREAD.Priority_Idle = -3
|
||||||
|
|
||||||
function THREAD.set(name, val)
|
function THREAD.set(name, val)
|
||||||
__GlobalLinda:set(name, val)
|
__GlobalLinda:set(name, val)
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.get(name)
|
function THREAD.get(name)
|
||||||
return __GlobalLinda:get(name)
|
return __GlobalLinda:get(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.waitFor(name)
|
function THREAD.waitFor(name)
|
||||||
local function wait()
|
local function wait()
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
@ -53,14 +57,17 @@ local function INIT(__GlobalLinda,__SleepingLinda)
|
|||||||
until __GlobalLinda:get(name)
|
until __GlobalLinda:get(name)
|
||||||
return __GlobalLinda:get(name)
|
return __GlobalLinda:get(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
if getOS() == "windows" then
|
if getOS() == "windows" then
|
||||||
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||||
else
|
else
|
||||||
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getCores()
|
function THREAD.getCores()
|
||||||
return THREAD.__CORES
|
return THREAD.__CORES
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getConsole()
|
function THREAD.getConsole()
|
||||||
local c = {}
|
local c = {}
|
||||||
c.queue = _Console
|
c.queue = _Console
|
||||||
@ -73,28 +80,41 @@ local function INIT(__GlobalLinda,__SleepingLinda)
|
|||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getThreads()
|
function THREAD.getThreads()
|
||||||
return GLOBAL.__THREADS__
|
return GLOBAL.__THREADS__
|
||||||
end
|
end
|
||||||
|
|
||||||
if os.getOS() == "windows" then
|
if os.getOS() == "windows" then
|
||||||
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||||
else
|
else
|
||||||
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.kill() -- trigger the lane destruction
|
function THREAD.kill() -- trigger the lane destruction
|
||||||
error("Thread was killed!\1")
|
error("Thread was killed!\1")
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getName()
|
function THREAD.getName()
|
||||||
return THREAD_NAME
|
return THREAD_NAME
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getID()
|
function THREAD.getID()
|
||||||
return THREAD_ID
|
return THREAD_ID
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function THREAD.pushStatus(...)
|
||||||
|
local args = {...}
|
||||||
|
__StatusLinda:send(nil,THREAD_ID, args)
|
||||||
|
end
|
||||||
|
|
||||||
_G.THREAD_ID = 0
|
_G.THREAD_ID = 0
|
||||||
|
|
||||||
function THREAD.sleep(n)
|
function THREAD.sleep(n)
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
__SleepingLinda:receive(n, "__non_existing_variable")
|
__SleepingLinda:receive(n, "__non_existing_variable")
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.hold(n)
|
function THREAD.hold(n)
|
||||||
local function wait()
|
local function wait()
|
||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
@ -104,6 +124,7 @@ local function INIT(__GlobalLinda,__SleepingLinda)
|
|||||||
wait()
|
wait()
|
||||||
until n()
|
until n()
|
||||||
end
|
end
|
||||||
|
|
||||||
local GLOBAL = {}
|
local GLOBAL = {}
|
||||||
setmetatable(GLOBAL, {
|
setmetatable(GLOBAL, {
|
||||||
__index = function(t, k)
|
__index = function(t, k)
|
||||||
@ -115,6 +136,7 @@ local function INIT(__GlobalLinda,__SleepingLinda)
|
|||||||
})
|
})
|
||||||
return GLOBAL, THREAD
|
return GLOBAL, THREAD
|
||||||
end
|
end
|
||||||
return {init = function(g,s)
|
|
||||||
return INIT(g,s)
|
return {init = function(g,s,st)
|
||||||
|
return INIT(g,s,st)
|
||||||
end}
|
end}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -131,7 +131,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end)
|
end)
|
||||||
end,holup),name
|
end,holup),name
|
||||||
end
|
end
|
||||||
multi:newThread("jobManager",function()
|
thread:newThread("jobManager",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
local dat = c.queueReturn:pop()
|
local dat = c.queueReturn:pop()
|
||||||
@ -155,7 +155,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
local queueAll = love.thread.getChannel("__JobQueue_"..jqc.."_queueAll")
|
local queueAll = love.thread.getChannel("__JobQueue_"..jqc.."_queueAll")
|
||||||
local registry = {}
|
local registry = {}
|
||||||
setmetatable(_G,{__index = funcs})
|
setmetatable(_G,{__index = funcs})
|
||||||
multi:newThread("startUp",function()
|
thread:newThread("startUp",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
local all = queueAll:peek()
|
local all = queueAll:peek()
|
||||||
@ -165,7 +165,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
multi:newThread("runner",function()
|
thread:newThread("runner",function()
|
||||||
thread.sleep(.1)
|
thread.sleep(.1)
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
@ -187,7 +187,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end):OnError(function(...)
|
end):OnError(function(...)
|
||||||
error(...)
|
error(...)
|
||||||
end)
|
end)
|
||||||
multi:newThread("Idler",function()
|
thread:newThread("Idler",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
if clock()-lastProc> 2 then
|
if clock()-lastProc> 2 then
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -37,7 +37,7 @@ GLOBAL = THREAD.getGlobal()
|
|||||||
multi, thread = require("multi").init()
|
multi, thread = require("multi").init()
|
||||||
stab["returns"] = {THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))}
|
stab["returns"] = {THREAD.loadDump(__FUNC__)(unpack(__IMPORTS))}
|
||||||
]]
|
]]
|
||||||
local multi, thread = require("multi.compat.love2d"):init()
|
local multi, thread = require("multi"):init()
|
||||||
local THREAD = {}
|
local THREAD = {}
|
||||||
__THREADID__ = 0
|
__THREADID__ = 0
|
||||||
__THREADNAME__ = "MainThread"
|
__THREADNAME__ = "MainThread"
|
||||||
@ -48,70 +48,7 @@ local GLOBAL = THREAD.getGlobal()
|
|||||||
local THREAD_ID = 1
|
local THREAD_ID = 1
|
||||||
local OBJECT_ID = 0
|
local OBJECT_ID = 0
|
||||||
local stf = 0
|
local stf = 0
|
||||||
function THREAD:newFunction(func,holup)
|
|
||||||
local tfunc = {}
|
|
||||||
tfunc.Active = true
|
|
||||||
function tfunc:Pause()
|
|
||||||
self.Active = false
|
|
||||||
end
|
|
||||||
function tfunc:Resume()
|
|
||||||
self.Active = true
|
|
||||||
end
|
|
||||||
function tfunc:holdMe(b)
|
|
||||||
holdme = b
|
|
||||||
end
|
|
||||||
local function noWait()
|
|
||||||
return nil, "Function is paused"
|
|
||||||
end
|
|
||||||
local rets, err
|
|
||||||
local function wait(no)
|
|
||||||
if thread.isThread() and not (no) then
|
|
||||||
-- In a thread
|
|
||||||
else
|
|
||||||
-- Not in a thread
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tfunc.__call = function(t,...)
|
|
||||||
if not t.Active then
|
|
||||||
if holdme then
|
|
||||||
return nil, "Function is paused"
|
|
||||||
end
|
|
||||||
return {
|
|
||||||
isTFunc = true,
|
|
||||||
wait = noWait,
|
|
||||||
connect = function(f)
|
|
||||||
f(nil,"Function is paused")
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
local t = multi:newSystemThread("SystemThreadedFunction",func,...)
|
|
||||||
t.OnDeath(function(self,...) rets = {...} end)
|
|
||||||
t.OnError(function(self,e) err = e end)
|
|
||||||
if holdme then
|
|
||||||
return wait()
|
|
||||||
end
|
|
||||||
local temp = {
|
|
||||||
OnStatus = multi:newConnection(),
|
|
||||||
OnError = multi:newConnection(),
|
|
||||||
OnReturn = multi:newConnection(),
|
|
||||||
isTFunc = true,
|
|
||||||
wait = wait,
|
|
||||||
connect = function(f)
|
|
||||||
local tempConn = multi:newConnection()
|
|
||||||
t.OnDeath(function(self,...) if f then f(...) else tempConn:Fire(...) end end)
|
|
||||||
t.OnError(function(self,err) if f then f(nil,err) else tempConn:Fire(nil,err) end end)
|
|
||||||
return tempConn
|
|
||||||
end
|
|
||||||
}
|
|
||||||
t.OnDeath(function(self,...) temp.OnReturn:Fire(...) end)
|
|
||||||
t.OnError(function(self,err) temp.OnError:Fire(err) end)
|
|
||||||
t.linkedFunction = temp
|
|
||||||
t.statusconnector = temp.OnStatus
|
|
||||||
return temp
|
|
||||||
end
|
|
||||||
setmetatable(tfunc,tfunc)
|
|
||||||
return tfunc
|
|
||||||
end
|
|
||||||
function multi:newSystemThread(name,func,...)
|
function multi:newSystemThread(name,func,...)
|
||||||
local c = {}
|
local c = {}
|
||||||
c.name = name
|
c.name = name
|
||||||
@ -119,38 +56,60 @@ function multi:newSystemThread(name,func,...)
|
|||||||
c.thread=love.thread.newThread(ThreadFileData)
|
c.thread=love.thread.newThread(ThreadFileData)
|
||||||
c.thread:start(THREAD.dump(func),c.ID,c.name,...)
|
c.thread:start(THREAD.dump(func),c.ID,c.name,...)
|
||||||
c.stab = THREAD.createStaticTable(name)
|
c.stab = THREAD.createStaticTable(name)
|
||||||
GLOBAL["__THREAD_"..c.ID] = {ID=c.ID,Name=c.name,Thread=c.thread}
|
c.OnDeath = multi:newConnection()
|
||||||
|
c.OnError = multi:newConnection()
|
||||||
|
GLOBAL["__THREAD_"..c.ID] = {ID=c.ID, Name=c.name, Thread=c.thread}
|
||||||
GLOBAL["__THREAD_COUNT"] = THREAD_ID
|
GLOBAL["__THREAD_COUNT"] = THREAD_ID
|
||||||
THREAD_ID=THREAD_ID+1
|
THREAD_ID=THREAD_ID + 1
|
||||||
multi:newThread(function()
|
function c:getName()
|
||||||
while true do
|
return c.name
|
||||||
thread.yield()
|
end
|
||||||
if c.stab["returns"] then
|
thread:newThread(function()
|
||||||
c.OnDeath:Fire(c,unpack(t.stab.returns))
|
if name:find("TempSystemThread") then
|
||||||
t.stab.returns = nil
|
local status_channel = love.thread.getChannel("__"..c.ID.."__MULTI__STATUS_CHANNEL__")
|
||||||
thread.kill()
|
thread.hold(function()
|
||||||
end
|
-- While the thread is running we might as well do something in the loop
|
||||||
local error = c.thread:getError()
|
local status = status_channel
|
||||||
if error then
|
if status:peek()~=nil then
|
||||||
if error:find("Thread Killed!\1") then
|
c.statusconnector:Fire(unpack(status:pop()))
|
||||||
c.OnDeath:Fire(c,"Thread Killed!")
|
|
||||||
thread.kill()
|
|
||||||
else
|
|
||||||
c.OnError:Fire(c,error)
|
|
||||||
thread.kill()
|
|
||||||
end
|
end
|
||||||
end
|
return not c.thread:isRunning()
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
thread.hold(function()
|
||||||
|
return not c.thread:isRunning()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- If the thread is not running let's handle that.
|
||||||
|
local thread_err = c.thread:getError()
|
||||||
|
if thread_err == "Thread Killed!\1" then
|
||||||
|
c.OnDeath:Fire("Thread Killed!")
|
||||||
|
elseif thread_err then
|
||||||
|
c.OnError:Fire(c,thread_err)
|
||||||
|
elseif c.stab.returns then
|
||||||
|
c.OnDeath:Fire(unpack(c.stab.returns))
|
||||||
|
c.stab.returns = nil
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
function love.threaderror(thread, errorstr)
|
|
||||||
print("Thread error!\n"..errorstr)
|
function THREAD:newFunction(func)
|
||||||
|
return thread:newFunctionBase(function(...)
|
||||||
|
return multi:newSystemThread("TempSystemThread"..THREAD_ID,func,...)
|
||||||
|
end)()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
THREAD.newSystemThread = multi.newSystemThread
|
||||||
|
|
||||||
|
function love.threaderror(thread, errorstr)
|
||||||
|
mulit.print("Thread error!\n"..errorstr)
|
||||||
|
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")
|
||||||
print("Integrated Love Threading!")
|
mulit.print("Integrated Love Threading!")
|
||||||
return {init=function()
|
return {init=function()
|
||||||
return GLOBAL,THREAD
|
return GLOBAL,THREAD
|
||||||
end}
|
end}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,15 +24,19 @@ SOFTWARE.
|
|||||||
require("love.timer")
|
require("love.timer")
|
||||||
require("love.system")
|
require("love.system")
|
||||||
require("love.data")
|
require("love.data")
|
||||||
|
require("love.thread")
|
||||||
local socket = require("socket")
|
local socket = require("socket")
|
||||||
local multi, thread = require("multi").init()
|
local multi, thread = require("multi").init()
|
||||||
local threads = {}
|
local threads = {}
|
||||||
|
|
||||||
function threads.loadDump(d)
|
function threads.loadDump(d)
|
||||||
return loadstring(d:getString())
|
return loadstring(d:getString())
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.dump(func)
|
function threads.dump(func)
|
||||||
return love.data.newByteData(string.dump(func))
|
return love.data.newByteData(string.dump(func))
|
||||||
end
|
end
|
||||||
|
|
||||||
local fRef = {"func",nil}
|
local fRef = {"func",nil}
|
||||||
local function manage(channel, value)
|
local function manage(channel, value)
|
||||||
channel:clear()
|
channel:clear()
|
||||||
@ -44,6 +48,7 @@ local function manage(channel, value)
|
|||||||
channel:push(value)
|
channel:push(value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function RandomVariable(length)
|
local function RandomVariable(length)
|
||||||
local res = {}
|
local res = {}
|
||||||
math.randomseed(socket.gettime()*10000)
|
math.randomseed(socket.gettime()*10000)
|
||||||
@ -52,12 +57,14 @@ local function RandomVariable(length)
|
|||||||
end
|
end
|
||||||
return table.concat(res)
|
return table.concat(res)
|
||||||
end
|
end
|
||||||
|
|
||||||
local GNAME = "__GLOBAL_"
|
local GNAME = "__GLOBAL_"
|
||||||
local proxy = {}
|
local proxy = {}
|
||||||
function threads.set(name,val)
|
function threads.set(name,val)
|
||||||
if not proxy[name] then proxy[name] = love.thread.getChannel(GNAME..name) end
|
if not proxy[name] then proxy[name] = love.thread.getChannel(GNAME..name) end
|
||||||
proxy[name]:performAtomic(manage, val)
|
proxy[name]:performAtomic(manage, val)
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.get(name)
|
function threads.get(name)
|
||||||
if not proxy[name] then proxy[name] = love.thread.getChannel(GNAME..name) end
|
if not proxy[name] then proxy[name] = love.thread.getChannel(GNAME..name) end
|
||||||
local dat = proxy[name]:peek()
|
local dat = proxy[name]:peek()
|
||||||
@ -67,6 +74,7 @@ function threads.get(name)
|
|||||||
return dat
|
return dat
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.waitFor(name)
|
function threads.waitFor(name)
|
||||||
if thread.isThread() then
|
if thread.isThread() then
|
||||||
return thread.hold(function()
|
return thread.hold(function()
|
||||||
@ -82,18 +90,28 @@ function threads.waitFor(name)
|
|||||||
end
|
end
|
||||||
return dat
|
return dat
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.package(name,val)
|
function threads.package(name,val)
|
||||||
local init = val.init
|
local init = val.init
|
||||||
val.init=threads.dump(val.init)
|
val.init=threads.dump(val.init)
|
||||||
GLOBAL[name]=val
|
GLOBAL[name]=val
|
||||||
val.init=init
|
val.init=init
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.getCores()
|
function threads.getCores()
|
||||||
return love.system.getProcessorCount()
|
return love.system.getProcessorCount()
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.kill()
|
function threads.kill()
|
||||||
error("Thread Killed!\1")
|
error("Thread Killed!\1")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function THREAD.pushStatus(...)
|
||||||
|
local status_channel = love.thread.getChannel("__"..__THREADID__.."__MULTI__STATUS_CHANNEL__")
|
||||||
|
local args = {...}
|
||||||
|
status_channel:push(__THREADID__, args)
|
||||||
|
end
|
||||||
|
|
||||||
function threads.getThreads()
|
function threads.getThreads()
|
||||||
local t = {}
|
local t = {}
|
||||||
for i=1,GLOBAL["__THREAD_COUNT"] do
|
for i=1,GLOBAL["__THREAD_COUNT"] do
|
||||||
@ -101,18 +119,23 @@ function threads.getThreads()
|
|||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.getThread(n)
|
function threads.getThread(n)
|
||||||
return GLOBAL["__THREAD_"..n]
|
return GLOBAL["__THREAD_"..n]
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.getName()
|
function threads.getName()
|
||||||
return __THREADNAME__
|
return __THREADNAME__
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.getID()
|
function threads.getID()
|
||||||
return __THREADID__
|
return __THREADID__
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.sleep(n)
|
function threads.sleep(n)
|
||||||
love.timer.sleep(n)
|
love.timer.sleep(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.getGlobal()
|
function threads.getGlobal()
|
||||||
return setmetatable({},
|
return setmetatable({},
|
||||||
{
|
{
|
||||||
@ -125,6 +148,7 @@ function threads.getGlobal()
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.createTable(n)
|
function threads.createTable(n)
|
||||||
local _proxy = {}
|
local _proxy = {}
|
||||||
local function set(name,val)
|
local function set(name,val)
|
||||||
@ -151,6 +175,7 @@ function threads.createTable(n)
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.getConsole()
|
function threads.getConsole()
|
||||||
local c = {}
|
local c = {}
|
||||||
c.queue = love.thread.getChannel("__CONSOLE__")
|
c.queue = love.thread.getChannel("__CONSOLE__")
|
||||||
@ -163,11 +188,12 @@ function threads.getConsole()
|
|||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
if not ISTHREAD then
|
if not ISTHREAD then
|
||||||
local clock = os.clock
|
local clock = os.clock
|
||||||
local lastproc = clock()
|
local lastproc = clock()
|
||||||
local queue = love.thread.getChannel("__CONSOLE__")
|
local queue = love.thread.getChannel("__CONSOLE__")
|
||||||
multi:newThread("consoleManager",function()
|
thread:newThread("consoleManager",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
dat = queue:pop()
|
dat = queue:pop()
|
||||||
@ -181,6 +207,7 @@ if not ISTHREAD then
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.createStaticTable(n)
|
function threads.createStaticTable(n)
|
||||||
local __proxy = {}
|
local __proxy = {}
|
||||||
local function set(name,val)
|
local function set(name,val)
|
||||||
@ -212,10 +239,12 @@ function threads.createStaticTable(n)
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function threads.hold(n)
|
function threads.hold(n)
|
||||||
local dat
|
local dat
|
||||||
while not(dat) do
|
while not(dat) do
|
||||||
dat = n()
|
dat = n()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return threads
|
return threads
|
||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -129,7 +129,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end)
|
end)
|
||||||
end,holup),name
|
end,holup),name
|
||||||
end
|
end
|
||||||
multi:newThread("jobManager",function()
|
thread:newThread("jobManager",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
local dat = c.queueReturn:pop()
|
local dat = c.queueReturn:pop()
|
||||||
@ -153,7 +153,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
local queueAll = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueAll")
|
local queueAll = lovr.thread.getChannel("__JobQueue_"..jqc.."_queueAll")
|
||||||
local registry = {}
|
local registry = {}
|
||||||
setmetatable(_G,{__index = funcs})
|
setmetatable(_G,{__index = funcs})
|
||||||
multi:newThread("startUp",function()
|
thread:newThread("startUp",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
local all = queueAll:peek()
|
local all = queueAll:peek()
|
||||||
@ -163,7 +163,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
multi:newThread("runner",function()
|
thread:newThread("runner",function()
|
||||||
thread.sleep(.1)
|
thread.sleep(.1)
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
@ -185,7 +185,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end):OnError(function(...)
|
end):OnError(function(...)
|
||||||
error(...)
|
error(...)
|
||||||
end)
|
end)
|
||||||
multi:newThread("Idler",function()
|
thread:newThread("Idler",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
if clock()-lastProc> 2 then
|
if clock()-lastProc> 2 then
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -76,6 +76,7 @@ function multi:newSystemThread(name,func,...)
|
|||||||
THREAD_ID=THREAD_ID+1
|
THREAD_ID=THREAD_ID+1
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
THREAD.newSystemThread = multi.newSystemThread
|
||||||
function lovr.threaderror(thread, errorstr)
|
function lovr.threaderror(thread, errorstr)
|
||||||
print("Thread error!\n"..errorstr)
|
print("Thread error!\n"..errorstr)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -168,7 +168,7 @@ if not ISTHREAD then
|
|||||||
local clock = os.clock
|
local clock = os.clock
|
||||||
local lastproc = clock()
|
local lastproc = clock()
|
||||||
local queue = lovr.thread.getChannel("__CONSOLE__")
|
local queue = lovr.thread.getChannel("__CONSOLE__")
|
||||||
multi:newThread("consoleManager",function()
|
thread:newThread("consoleManager",function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
dat = queue:pop()
|
dat = queue:pop()
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -116,6 +116,7 @@ local function _INIT(luvitThread, timer)
|
|||||||
luvitThread.start(entry, package.path, name, c.func, ...)
|
luvitThread.start(entry, package.path, name, c.func, ...)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
THREAD.newSystemThread = multi.newSystemThread
|
||||||
multi.print("Integrated Luvit!")
|
multi.print("Integrated Luvit!")
|
||||||
multi.integration = {} -- for module creators
|
multi.integration = {} -- for module creators
|
||||||
multi.integration.GLOBAL = GLOBAL
|
multi.integration.GLOBAL = GLOBAL
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -72,7 +72,7 @@ function master:newNetworkThread(nodeName,func,...)
|
|||||||
local ret
|
local ret
|
||||||
local nID = netID
|
local nID = netID
|
||||||
local conn = multi:newConnection()
|
local conn = multi:newConnection()
|
||||||
multi:newThread(function()
|
thread:newthread(function()
|
||||||
dat:addBlock{
|
dat:addBlock{
|
||||||
args = args,
|
args = args,
|
||||||
func = func,
|
func = func,
|
||||||
@ -143,7 +143,7 @@ function multi:newMasterNode(cd)
|
|||||||
else
|
else
|
||||||
c:getNodesFromBroadcast()
|
c:getNodesFromBroadcast()
|
||||||
end
|
end
|
||||||
multi:newThread("CMDQueueProcessor",function()
|
thread:newthread("CMDQueueProcessor",function()
|
||||||
while true do
|
while true do
|
||||||
thread.skip(128)
|
thread.skip(128)
|
||||||
local data = table.remove(c._queue,1)
|
local data = table.remove(c._queue,1)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -125,7 +125,7 @@ function multi:newSystemThreadedJobQueue(n)
|
|||||||
end,holup),name
|
end,holup),name
|
||||||
end
|
end
|
||||||
for i=1,c.cores do
|
for i=1,c.cores do
|
||||||
multi:newThread("PesudoThreadedJobQueue_"..i,function()
|
thread:newthread("PesudoThreadedJobQueue_"..i,function()
|
||||||
while true do
|
while true do
|
||||||
thread.yield()
|
thread.yield()
|
||||||
if #jobs>0 then
|
if #jobs>0 then
|
||||||
|
|||||||
@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
package.path = "?/init.lua;?.lua;" .. package.path
|
package.path = "?/init.lua;?.lua;" .. package.path
|
||||||
local multi, thread = require("multi").init()
|
local multi, thread = require("multi"):init()
|
||||||
|
|
||||||
if multi.integration then
|
if multi.integration then
|
||||||
return {
|
return {
|
||||||
@ -32,7 +32,7 @@ if multi.integration then
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local GLOBAL, THREAD = require("multi.integration.pesudoManager.threads"):init()
|
local GLOBAL, THREAD = require("multi.integration.pesudoManager.threads").init(thread)
|
||||||
|
|
||||||
function multi:canSystemThread() -- We are emulating system threading
|
function multi:canSystemThread() -- We are emulating system threading
|
||||||
return true
|
return true
|
||||||
@ -41,6 +41,7 @@ end
|
|||||||
function multi:getPlatform()
|
function multi:getPlatform()
|
||||||
return "pesudo"
|
return "pesudo"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function split(str)
|
local function split(str)
|
||||||
local tab = {}
|
local tab = {}
|
||||||
for word in string.gmatch(str, '([^,]+)') do
|
for word in string.gmatch(str, '([^,]+)') do
|
||||||
@ -48,13 +49,16 @@ local function split(str)
|
|||||||
end
|
end
|
||||||
return tab
|
return tab
|
||||||
end
|
end
|
||||||
THREAD.newFunction=thread.newFunction
|
|
||||||
|
local tab = [[_VERSION,io,os,require,load,debug,assert,collectgarbage,error,getfenv,getmetatable,ipairs,loadstring,module,next,pairs,pcall,print,rawequal,rawget,rawset,select,setfenv,setmetatable,tonumber,tostring,type,unpack,xpcall,math,coroutine,string,table]]
|
||||||
|
tab = split(tab)
|
||||||
|
|
||||||
local id = 0
|
local id = 0
|
||||||
function multi:newSystemThread(name,func,...)
|
function multi:newSystemThread(name,func,...)
|
||||||
GLOBAL["$THREAD_NAME"] = name
|
GLOBAL["$THREAD_NAME"] = name
|
||||||
GLOBAL["$__THREADNAME__"] = name
|
GLOBAL["$__THREADNAME__"] = name
|
||||||
GLOBAL["$THREAD_ID"] = id
|
GLOBAL["$THREAD_ID"] = id
|
||||||
--GLOBAL["$thread"] = thread
|
GLOBAL["$thread"] = thread
|
||||||
local env = {
|
local env = {
|
||||||
GLOBAL = GLOBAL,
|
GLOBAL = GLOBAL,
|
||||||
THREAD = THREAD,
|
THREAD = THREAD,
|
||||||
@ -64,21 +68,28 @@ function multi:newSystemThread(name,func,...)
|
|||||||
thread = thread
|
thread = thread
|
||||||
}
|
}
|
||||||
|
|
||||||
local tab = [[_VERSION,io,os,require,load,debug,assert,collectgarbage,error,getfenv,getmetatable,ipairs,loadstring,module,next,pairs,pcall,print,rawequal,rawget,rawset,select,setfenv,setmetatable,tonumber,tostring,type,unpack,xpcall,math,coroutine,string,table]]
|
|
||||||
tab = split(tab)
|
|
||||||
for i = 1,#tab do
|
for i = 1,#tab do
|
||||||
env[tab[i]] = _G[tab[i]]
|
env[tab[i]] = _G[tab[i]]
|
||||||
end
|
end
|
||||||
--setmetatable(env,{__index=env})
|
|
||||||
multi:newISOThread(name,func,env,...).OnError(function(self,msg)
|
local th = thread:newISOThread(name,func,env,...)
|
||||||
print("ERROR:",msg)
|
|
||||||
end)
|
|
||||||
id = id + 1
|
id = id + 1
|
||||||
|
|
||||||
|
return th
|
||||||
end
|
end
|
||||||
|
|
||||||
|
THREAD.newSystemThread = multi.newSystemThread
|
||||||
-- System threads as implemented here cannot share memory, but use a message passing system.
|
-- System threads as implemented here cannot share memory, but use a message passing system.
|
||||||
-- An isolated thread allows us to mimic that behavior so if access data from the "main" thread happens things will not work. This behavior is in line with how the system threading works
|
-- An isolated thread allows us to mimic that behavior so if access data from the "main" thread happens things will not work. This behavior is in line with how the system threading works
|
||||||
|
|
||||||
print("Integrated Pesudo Threading!")
|
function THREAD:newFunction(func,holdme)
|
||||||
|
return thread:newFunctionBase(function(...)
|
||||||
|
return multi:newSystemThread("TempSystemThread",func,...)
|
||||||
|
end,holdme)()
|
||||||
|
end
|
||||||
|
|
||||||
|
multi.print("Integrated Pesudo Threading!")
|
||||||
multi.integration = {} -- for module creators
|
multi.integration = {} -- for module creators
|
||||||
multi.integration.GLOBAL = GLOBAL
|
multi.integration.GLOBAL = GLOBAL
|
||||||
multi.integration.THREAD = THREAD
|
multi.integration.THREAD = THREAD
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
--[[
|
--[[
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Ryan Ward
|
Copyright (c) 2022 Ryan Ward
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -21,6 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local function getOS()
|
local function getOS()
|
||||||
if package.config:sub(1, 1) == "\\" then
|
if package.config:sub(1, 1) == "\\" then
|
||||||
return "windows"
|
return "windows"
|
||||||
@ -28,7 +29,8 @@ local function getOS()
|
|||||||
return "unix"
|
return "unix"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function INIT(env)
|
|
||||||
|
local function INIT(thread)
|
||||||
local THREAD = {}
|
local THREAD = {}
|
||||||
local GLOBAL = {}
|
local GLOBAL = {}
|
||||||
THREAD.Priority_Core = 3
|
THREAD.Priority_Core = 3
|
||||||
@ -38,24 +40,29 @@ local function INIT(env)
|
|||||||
THREAD.Priority_Below_Normal = -1
|
THREAD.Priority_Below_Normal = -1
|
||||||
THREAD.Priority_Low = -2
|
THREAD.Priority_Low = -2
|
||||||
THREAD.Priority_Idle = -3
|
THREAD.Priority_Idle = -3
|
||||||
|
|
||||||
function THREAD.set(name, val)
|
function THREAD.set(name, val)
|
||||||
GLOBAL[name] = val
|
GLOBAL[name] = val
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.get(name)
|
function THREAD.get(name)
|
||||||
return GLOBAL[name]
|
return GLOBAL[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.waitFor(name)
|
function THREAD.waitFor(name)
|
||||||
print("Waiting",thread)
|
|
||||||
return thread.hold(function() return GLOBAL[name] end)
|
return thread.hold(function() return GLOBAL[name] end)
|
||||||
end
|
end
|
||||||
|
|
||||||
if getOS() == "windows" then
|
if getOS() == "windows" then
|
||||||
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||||
else
|
else
|
||||||
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getCores()
|
function THREAD.getCores()
|
||||||
return THREAD.__CORES
|
return THREAD.__CORES
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getConsole()
|
function THREAD.getConsole()
|
||||||
local c = {}
|
local c = {}
|
||||||
function c.print(...)
|
function c.print(...)
|
||||||
@ -66,31 +73,38 @@ local function INIT(env)
|
|||||||
end
|
end
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getThreads()
|
function THREAD.getThreads()
|
||||||
return {}--GLOBAL.__THREADS__
|
return {}--GLOBAL.__THREADS__
|
||||||
end
|
end
|
||||||
|
|
||||||
|
THREAD.pushStatus = thread.pushStatus
|
||||||
|
|
||||||
if os.getOS() == "windows" then
|
if os.getOS() == "windows" then
|
||||||
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
THREAD.__CORES = tonumber(os.getenv("NUMBER_OF_PROCESSORS"))
|
||||||
else
|
else
|
||||||
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
THREAD.__CORES = tonumber(io.popen("nproc --all"):read("*n"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.kill()
|
function THREAD.kill()
|
||||||
error("Thread was killed!")
|
error("Thread was killed!")
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getName()
|
function THREAD.getName()
|
||||||
return GLOBAL["$THREAD_NAME"]
|
return GLOBAL["$THREAD_NAME"]
|
||||||
end
|
end
|
||||||
|
|
||||||
function THREAD.getID()
|
function THREAD.getID()
|
||||||
return GLOBAL["$THREAD_ID"]
|
return GLOBAL["$THREAD_ID"]
|
||||||
end
|
end
|
||||||
function THREAD.sleep(n)
|
|
||||||
thread.sleep(n)
|
THREAD.sleep = thread.sleep
|
||||||
end
|
|
||||||
function THREAD.hold(n)
|
THREAD.hold = thread.hold
|
||||||
return thread.hold(n)
|
|
||||||
end
|
|
||||||
return GLOBAL, THREAD
|
return GLOBAL, THREAD
|
||||||
end
|
end
|
||||||
return {init = function()
|
|
||||||
return INIT()
|
return {init = function(thread)
|
||||||
|
return INIT(thread)
|
||||||
end}
|
end}
|
||||||
39
rockspecs/multi-15.2-0.rockspec
Normal file
39
rockspecs/multi-15.2-0.rockspec
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package = "multi"
|
||||||
|
version = "15.2-0"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/rayaman/multi.git",
|
||||||
|
tag = "v15.2.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"] = "multi/init.lua",
|
||||||
|
["multi.integration.lanesManager"] = "multi/integration/lanesManager/init.lua",
|
||||||
|
["multi.integration.lanesManager.extensions"] = "multi/integration/lanesManager/extensions.lua",
|
||||||
|
["multi.integration.lanesManager.threads"] = "multi/integration/lanesManager/threads.lua",
|
||||||
|
["multi.integration.loveManager"] = "multi/integration/loveManager/init.lua",
|
||||||
|
["multi.integration.loveManager.extensions"] = "multi/integration/loveManager/extensions.lua",
|
||||||
|
["multi.integration.loveManager.threads"] = "multi/integration/loveManager/threads.lua",
|
||||||
|
--["multi.integration.lovrManager"] = "multi/integration/lovrManager/init.lua",
|
||||||
|
--["multi.integration.lovrManager.extensions"] = "multi/integration/lovrManager/extensions.lua",
|
||||||
|
--["multi.integration.lovrManager.threads"] = "multi/integration/lovrManager/threads.lua",
|
||||||
|
["multi.integration.pesudoManager"] = "multi/integration/pesudoManager/init.lua",
|
||||||
|
["multi.integration.pesudoManager.extensions"] = "multi/integration/pesudoManager/extensions.lua",
|
||||||
|
["multi.integration.pesudoManager.threads"] = "multi/integration/pesudoManager/threads.lua",
|
||||||
|
["multi.integration.luvitManager"] = "multi/integration/luvitManager.lua",
|
||||||
|
["multi.integration.threading"] = "multi/integration/threading.lua",
|
||||||
|
--["multi.integration.networkManager"] = "multi/integration/networkManager.lua",
|
||||||
|
}
|
||||||
|
}
|
||||||
200
test.lua
200
test.lua
@ -1,113 +1,111 @@
|
|||||||
--package.path = "./?/init.lua;"..package.path
|
package.path = "./?/init.lua;"..package.path
|
||||||
multi,thread = require("multi"):init()
|
multi, thread = require("multi"):init{print=true}
|
||||||
|
GLOBAL, THREAD = require("multi.integration.threading"):init()
|
||||||
|
|
||||||
func = thread:newFunction(function(count)
|
-- Using a system thread, but both system and local threads support this!
|
||||||
local a = 0
|
-- Don't worry if you don't have lanes or love2d. PesudoThreading will kick in to emulate the threading features if you do not have access to system threading.
|
||||||
while true do
|
func = THREAD:newFunction(function(count)
|
||||||
a = a + 1
|
print("Starting Status test: ",count)
|
||||||
thread.sleep(.5)
|
local a = 0
|
||||||
thread.pushStatus(a,count)
|
while true do
|
||||||
if a == count then break end
|
a = a + 1
|
||||||
end
|
THREAD.sleep(.1)
|
||||||
return "Done"
|
-- Push the status from the currently running threaded function to the main thread
|
||||||
|
THREAD.pushStatus(a,count)
|
||||||
|
if a == count then break end
|
||||||
|
end
|
||||||
|
return "Done"
|
||||||
end)
|
end)
|
||||||
|
|
||||||
multi:newThread("test",function()
|
thread:newThread("test",function()
|
||||||
local ret = func(10)
|
local ret = func(10)
|
||||||
local ret2 = func(15)
|
ret.OnStatus(function(part,whole)
|
||||||
local ret3 = func(20)
|
print("Ret1: ",math.ceil((part/whole)*1000)/10 .."%")
|
||||||
ret.OnStatus(function(part,whole)
|
end)
|
||||||
print("Ret1: ",math.ceil((part/whole)*1000)/10 .."%")
|
print("TEST",func(5).wait())
|
||||||
end)
|
-- The results from the OnReturn connection is passed by thread.hold
|
||||||
ret2.OnStatus(function(part,whole)
|
print("Status:",thread.hold(ret.OnReturn))
|
||||||
print("Ret2: ",math.ceil((part/whole)*1000)/10 .."%")
|
print("Function Done!")
|
||||||
end)
|
|
||||||
ret3.OnStatus(function(part,whole)
|
|
||||||
print("Ret3: ",math.ceil((part/whole)*1000)/10 .."%")
|
|
||||||
end)
|
|
||||||
thread.hold(ret2.OnReturn + ret.OnReturn + ret3.OnReturn)
|
|
||||||
print("Function Done!")
|
|
||||||
os.exit()
|
|
||||||
end)
|
|
||||||
|
|
||||||
--GLOBAL,THREAD = require("multi.integration.threading"):init() -- Auto detects your environment and uses what's available
|
|
||||||
|
|
||||||
func2 = thread:newFunction(function()
|
|
||||||
thread.sleep(3)
|
|
||||||
print("Hello World!")
|
|
||||||
return true
|
|
||||||
end,true) -- set holdme to true
|
|
||||||
|
|
||||||
func2:holdMe(false) -- reset holdme to false
|
|
||||||
print("Calling func...")
|
|
||||||
print(func2())
|
|
||||||
|
|
||||||
test = thread:newFunction(function(a,b)
|
|
||||||
thread.sleep(1)
|
|
||||||
return a,b
|
|
||||||
end)
|
|
||||||
print(test(1,2).connect(function(...)
|
|
||||||
print(...)
|
|
||||||
end))
|
|
||||||
test:Pause()
|
|
||||||
print(test(1,2).connect(function(...)
|
|
||||||
print(...)
|
|
||||||
end))
|
|
||||||
test:Resume()
|
|
||||||
print(test(1,2).connect(function(...)
|
|
||||||
print(...)
|
|
||||||
end))
|
|
||||||
|
|
||||||
test = thread:newFunction(function()
|
|
||||||
return 1,2,nil,3,4,5,6,7,8,9
|
|
||||||
end,true)
|
|
||||||
print(test())
|
|
||||||
multi:newThread("testing",function()
|
|
||||||
print("#Test = ",test())
|
|
||||||
print(thread.hold(function()
|
|
||||||
print("Hello!")
|
|
||||||
return false
|
|
||||||
end,{
|
|
||||||
interval = 2,
|
|
||||||
cycles = 3
|
|
||||||
})) -- End result, 3 attempts within 6 seconds. If still false then timeout
|
|
||||||
print("held")
|
|
||||||
end).OnError(function(...)
|
end).OnError(function(...)
|
||||||
print(...)
|
print("Error:",...)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
sandbox = multi:newProcessor("Test Processor")
|
local ret = func(10)
|
||||||
sandbox:newTLoop(function()
|
local ret2 = func(15)
|
||||||
print("testing...")
|
local ret3 = func(20)
|
||||||
end,1)
|
local s1,s2,s3 = 0,0,0
|
||||||
|
ret.OnError(function(...)
|
||||||
test2 = multi:newTLoop(function()
|
print("Error:",...)
|
||||||
print("testing2...")
|
end)
|
||||||
end,1)
|
ret2.OnError(function(...)
|
||||||
|
print("Error:",...)
|
||||||
sandbox:newThread("Test Thread",function()
|
end)
|
||||||
local a = 0
|
ret3.OnError(function(...)
|
||||||
while true do
|
print("Error:",...)
|
||||||
thread.sleep(1)
|
end)
|
||||||
a = a + 1
|
ret.OnStatus(function(part,whole)
|
||||||
print("Thread Test: ".. multi.getCurrentProcess().Name)
|
s1 = math.ceil((part/whole)*1000)/10
|
||||||
if a == 10 then
|
print(s1)
|
||||||
sandbox.Stop()
|
end)
|
||||||
end
|
ret2.OnStatus(function(part,whole)
|
||||||
end
|
s2 = math.ceil((part/whole)*1000)/10
|
||||||
end).OnError(function(...)
|
print(s2)
|
||||||
print(...)
|
end)
|
||||||
|
ret3.OnStatus(function(part,whole)
|
||||||
|
s3 = math.ceil((part/whole)*1000)/10
|
||||||
|
print(s3)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
multi:newThread("Test Thread",function()
|
loop = multi:newTLoop()
|
||||||
while true do
|
|
||||||
thread.sleep(1)
|
function loop:testing()
|
||||||
print("Thread Test: ".. multi.getCurrentProcess().Name)
|
print("testing haha")
|
||||||
end
|
end
|
||||||
end).OnError(function(...)
|
|
||||||
print(...)
|
loop:Set(1)
|
||||||
|
t = loop:OnLoop(function()
|
||||||
|
print("Looping...")
|
||||||
|
end):testing()
|
||||||
|
|
||||||
|
local proc = multi:newProcessor("Test")
|
||||||
|
local proc2 = multi:newProcessor("Test2")
|
||||||
|
local proc3 = proc2:newProcessor("Test3")
|
||||||
|
proc.Start()
|
||||||
|
proc2.Start()
|
||||||
|
proc3.Start()
|
||||||
|
proc:newThread("TestThread_1",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
proc:newThread("TestThread_2",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
proc2:newThread("TestThread_3",function()
|
||||||
|
while true do
|
||||||
|
thread.sleep(1)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
sandbox.Start()
|
thread:newThread(function()
|
||||||
|
thread.sleep(1)
|
||||||
|
local tasks = multi:getStats()
|
||||||
|
|
||||||
|
for i,v in pairs(tasks) do
|
||||||
|
print("Process: " ..i.. "\n\tTasks:")
|
||||||
|
for ii,vv in pairs(v.tasks) do
|
||||||
|
print("\t\t"..vv:getName())
|
||||||
|
end
|
||||||
|
print("\tThreads:")
|
||||||
|
for ii,vv in pairs(v.threads) do
|
||||||
|
print("\t\t"..vv:getName())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
thread.sleep(10) -- Wait 10 seconds then kill the process!
|
||||||
|
os.exit()
|
||||||
|
end)
|
||||||
|
|
||||||
multi:mainloop()
|
multi:mainloop()
|
||||||
51
test3.lua
Normal file
51
test3.lua
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package.path = "./?.lua;?/init.lua;"..package.path
|
||||||
|
local multi,thread = require("multi"):init{print=true}
|
||||||
|
--local GLOBAL,THREAD = require("multi.integration.lanesManager"):init()
|
||||||
|
|
||||||
|
-- func = THREAD:newFunction(function(a,b,c)
|
||||||
|
-- print("Hello Thread!",a,b,c)
|
||||||
|
-- return 1,2,3
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
-- func2 = THREAD:newFunction(function(a,b,c)
|
||||||
|
-- print("Hello Thread2!",a,b,c)
|
||||||
|
-- THREAD.sleep(1)
|
||||||
|
-- return 10,11,12
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
-- multi:newThread("Test thread",function()
|
||||||
|
-- handler = func(4,5,6)
|
||||||
|
-- handler2 = func2(7,8,9)
|
||||||
|
-- thread.hold(handler.OnReturn + handler2.OnReturn)
|
||||||
|
-- print("Function Done",handler.getReturns())
|
||||||
|
-- print("Function Done",handler2.getReturns())
|
||||||
|
-- end)
|
||||||
|
|
||||||
|
|
||||||
|
-- multi:benchMark(1):OnBench(function(sec,steps)
|
||||||
|
-- print("Steps:",steps)
|
||||||
|
-- os.exit()
|
||||||
|
-- end)
|
||||||
|
print("Running benchmarks! ",_VERSION)
|
||||||
|
local sleep_for = 1
|
||||||
|
local a = 0
|
||||||
|
local c = 1
|
||||||
|
local function bench(t,step)
|
||||||
|
a = a + step
|
||||||
|
c = c + 1
|
||||||
|
os.exit()
|
||||||
|
end
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Idle,"Idle:"):OnBench(bench)
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Very_Low,"Very Low:"):OnBench(bench)
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Low,"Low:"):OnBench()
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Below_Normal,"Below Normal:"):OnBench(bench)
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Normal,"Normal:"):OnBench(bench)
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Above_Normal,"Above Normal:"):OnBench(bench)
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_High,"High:"):OnBench(bench)
|
||||||
|
--multi:benchMark(sleep_for,multi.Priority_Very_High,"Very High:"):OnBench(bench)
|
||||||
|
multi:benchMark(sleep_for,multi.Priority_Core,"Core:"):OnBench(bench)
|
||||||
|
multi.OnExit(function()
|
||||||
|
print("Total: ".. a)
|
||||||
|
end)
|
||||||
|
|
||||||
|
multi:mainloop()
|
||||||
@ -1,3 +0,0 @@
|
|||||||
return function objectTests(multi,thread)
|
|
||||||
print("Testing Alarms!")
|
|
||||||
end
|
|
||||||
@ -1,4 +1,9 @@
|
|||||||
package.path="../?.lua;../?/init.lua;../?.lua;../?/?/init.lua;"..package.path
|
if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
|
||||||
|
package.path="multi/?.lua;multi/?/init.lua;multi/?.lua;multi/?/?/init.lua;"..package.path
|
||||||
|
require("lldebugger").start()
|
||||||
|
else
|
||||||
|
package.path="./?.lua;../?/init.lua;../?.lua;../?/?/init.lua;"..package.path
|
||||||
|
end
|
||||||
--[[
|
--[[
|
||||||
This file runs all tests.
|
This file runs all tests.
|
||||||
Format:
|
Format:
|
||||||
@ -15,7 +20,157 @@ package.path="../?.lua;../?/init.lua;../?.lua;../?/?/init.lua;"..package.path
|
|||||||
The expected and actual should "match" (Might be impossible when playing with threads)
|
The expected and actual should "match" (Might be impossible when playing with threads)
|
||||||
This will be pushed directly to the master as tests start existing.
|
This will be pushed directly to the master as tests start existing.
|
||||||
]]
|
]]
|
||||||
local multi, thread = require("multi"):init()
|
local multi, thread = require("multi"):init{print=true}--{priority=true}
|
||||||
function runTest(path)
|
local good = false
|
||||||
|
local proc = multi:newProcessor("Test",true)
|
||||||
|
proc:newAlarm(3):OnRing(function()
|
||||||
|
good = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
runTest = thread:newFunction(function()
|
||||||
|
local alarms,tsteps,steps,loops,tloops,updaters,events=false,0,0,0,0,0,false
|
||||||
|
print("Testing Basic Features. If this fails most other features will probably not work!")
|
||||||
|
proc:newAlarm(2):OnRing(function(a)
|
||||||
|
alarms = true
|
||||||
|
a:Destroy()
|
||||||
|
end)
|
||||||
|
proc:newTStep(1,10,1,.1):OnStep(function(t)
|
||||||
|
tsteps = tsteps + 1
|
||||||
|
end).OnEnd(function(step)
|
||||||
|
step:Destroy()
|
||||||
|
end)
|
||||||
|
proc:newStep(1,10):OnStep(function(s)
|
||||||
|
steps = steps + 1
|
||||||
|
end).OnEnd(function(step)
|
||||||
|
step:Destroy()
|
||||||
|
end)
|
||||||
|
local loop = proc:newLoop(function(l)
|
||||||
|
loops = loops + 1
|
||||||
|
end)
|
||||||
|
proc:newTLoop(function(t)
|
||||||
|
tloops = tloops + 1
|
||||||
|
end,.1)
|
||||||
|
local updater = proc:newUpdater(1):OnUpdate(function()
|
||||||
|
updaters = updaters + 1
|
||||||
|
end)
|
||||||
|
local event = proc:newEvent(function()
|
||||||
|
return alarms
|
||||||
|
end)
|
||||||
|
event.OnEvent(function(evnt)
|
||||||
|
evnt:Destroy()
|
||||||
|
events = true
|
||||||
|
print("Alarms: Ok")
|
||||||
|
print("Events: Ok")
|
||||||
|
if tsteps == 10 then print("TSteps: Ok") else print("TSteps: Bad!") end
|
||||||
|
if steps == 10 then print("Steps: Ok") else print("Steps: Bad!") end
|
||||||
|
if loops > 100 then print("Loops: Ok") else print("Loops: Bad!") end
|
||||||
|
if tloops > 10 then print("TLoops: Ok") else print("TLoops: Bad!") end
|
||||||
|
if updaters > 100 then print("Updaters: Ok") else print("Updaters: Bad!") end
|
||||||
|
end)
|
||||||
|
thread.hold(event.OnEvent)
|
||||||
|
print("Starting Connection and Thread tests!")
|
||||||
|
func = thread:newFunction(function(count)
|
||||||
|
print("Starting Status test: ",count)
|
||||||
|
local a = 0
|
||||||
|
while true do
|
||||||
|
a = a + 1
|
||||||
|
thread.sleep(.1)
|
||||||
|
thread.pushStatus(a,count)
|
||||||
|
if a == count then break end
|
||||||
|
end
|
||||||
|
return "Done"
|
||||||
|
end)
|
||||||
|
local ret = func(10)
|
||||||
|
local ret2 = func(15)
|
||||||
|
local ret3 = func(20)
|
||||||
|
local s1,s2,s3 = 0,0,0
|
||||||
|
ret.OnError(function(...)
|
||||||
|
print("Func 1:",...)
|
||||||
|
end)
|
||||||
|
ret2.OnError(function(...)
|
||||||
|
print("Func 2:",...)
|
||||||
|
end)
|
||||||
|
ret3.OnError(function(...)
|
||||||
|
print("Func 3:",...)
|
||||||
|
end)
|
||||||
|
ret.OnStatus(function(part,whole)
|
||||||
|
s1 = math.ceil((part/whole)*1000)/10
|
||||||
|
end)
|
||||||
|
ret2.OnStatus(function(part,whole)
|
||||||
|
s2 = math.ceil((part/whole)*1000)/10
|
||||||
|
end)
|
||||||
|
ret3.OnStatus(function(part,whole)
|
||||||
|
s3 = math.ceil((part/whole)*1000)/10
|
||||||
|
end)
|
||||||
|
ret.OnReturn(function()
|
||||||
|
print("Done 1")
|
||||||
|
end)
|
||||||
|
ret2.OnReturn(function()
|
||||||
|
print("Done 2")
|
||||||
|
end)
|
||||||
|
ret3.OnReturn(function()
|
||||||
|
print("Done 3")
|
||||||
|
end)
|
||||||
|
local err, timeout = thread.hold(ret.OnReturn + ret2.OnReturn + ret3.OnReturn)
|
||||||
|
if s1 == 100 and s2 == 100 and s3 == 100 then
|
||||||
|
print("Threads: Ok")
|
||||||
|
else
|
||||||
|
print("Threads OnStatus or thread.hold(conn) Error!")
|
||||||
|
end
|
||||||
|
if timeout then
|
||||||
|
print("Threads or Connection Error!")
|
||||||
|
else
|
||||||
|
print("Connection Test 1: Ok")
|
||||||
|
end
|
||||||
|
conn1 = proc:newConnection()
|
||||||
|
conn2 = proc:newConnection()
|
||||||
|
conn3 = proc:newConnection()
|
||||||
|
local c1,c2,c3,c4 = false,false,false,false
|
||||||
|
|
||||||
|
local a = conn1(function()
|
||||||
|
c1 = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
local b = conn2(function()
|
||||||
|
c2 = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
local c = conn3(function()
|
||||||
|
c3 = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
local d = conn3(function()
|
||||||
|
c4 = true
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn1:Fire()
|
||||||
|
conn2:Fire()
|
||||||
|
conn3:Fire()
|
||||||
|
|
||||||
|
if c1 and c2 and c3 and c4 then
|
||||||
|
print("Connection Test 2: Ok")
|
||||||
|
else
|
||||||
|
print("Connection Test 2: Error")
|
||||||
|
end
|
||||||
|
c3 = false
|
||||||
|
c4 = false
|
||||||
|
d:Destroy()
|
||||||
|
conn3:Fire()
|
||||||
|
if c3 and not(c4) then
|
||||||
|
print("Connection Test 3: Ok")
|
||||||
|
else
|
||||||
|
print("Connection Test 3: Error removing connection")
|
||||||
|
end
|
||||||
|
os.exit() -- End of tests
|
||||||
|
end)
|
||||||
|
|
||||||
|
runTest().OnError(function(...)
|
||||||
|
print("Error: Something went wrong with the test!")
|
||||||
|
print(...)
|
||||||
|
os.exit(1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
print("Pumping proc")
|
||||||
|
while true do
|
||||||
|
proc.run()
|
||||||
end
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user