mirror of
https://github.com/rayaman/multi.git
synced 2026-09-05 07:27:35 -04:00
Compare commits
120
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b0cb7a853 | ||
|
|
ffaab32d5e | ||
|
|
946217310f | ||
|
|
b4c3708f50 | ||
|
|
e3ac0951ab | ||
|
|
42b4e0fcf4 | ||
|
|
f07b1ebb57 | ||
|
|
ea6503d7b2 | ||
|
|
b7a7e5bf16 | ||
|
|
5ac17f8e59 | ||
|
|
2b9f732d88 | ||
|
|
726f55e5c6 | ||
|
|
91561f7f24 | ||
|
|
8d843a5958 | ||
|
|
30db370cc9 | ||
|
|
0af807a930 | ||
|
|
9ad2c45b8f | ||
|
|
e7ff234cef | ||
|
|
f540396932 | ||
|
|
46ace58ab8 | ||
|
|
ef7464f70d | ||
|
|
ad929da484 | ||
|
|
3d55704726 | ||
|
|
13221ca47e | ||
|
|
98198a4af2 | ||
|
|
5f5723e936 | ||
|
|
a660b63581 | ||
|
|
bab9b13cb8 | ||
|
|
8c2bde7ed8 | ||
|
|
d50c187710 | ||
|
|
5359be0772 | ||
|
|
59cbeb6597 | ||
|
|
bb0592f3eb | ||
|
|
bbaac2d779 | ||
|
|
9e6552d42e | ||
|
|
afdd98ab13 | ||
|
|
e43fe34a7c | ||
|
|
f4cdde6040 | ||
|
|
cec53f6f4e | ||
|
|
d57dc7dc22 | ||
|
|
6be948f068 | ||
|
|
c8abadd8d6 | ||
|
|
15bbec9379 | ||
|
|
befe863846 | ||
|
|
761e739e18 | ||
|
|
a9673385d9 | ||
|
|
0b0f971802 | ||
|
|
755f207554 | ||
|
|
49a1b944d0 | ||
|
|
883bdb9830 | ||
|
|
8a83c617fa | ||
|
|
06580e0bfa | ||
|
|
0a72f16e68 | ||
|
|
721571d1a4 | ||
|
|
7c95b2e8ca | ||
|
|
a6fac9d1d4 | ||
|
|
7ba642342d | ||
|
|
acc94ea17e | ||
|
|
81fc7b95c9 | ||
|
|
03a2f686a8 | ||
|
|
96cc41effb | ||
|
|
8c987b81ab | ||
|
|
1064d8a1cc | ||
|
|
cd4cc5fd2d | ||
|
|
614e032aa5 | ||
|
|
b2569118a2 | ||
|
|
d36204c87f | ||
|
|
660c10ec3b | ||
|
|
c39aa229f8 | ||
|
|
c80f44c68e | ||
|
|
1b3e3303e9 | ||
|
|
6fe10b22ab | ||
|
|
257ed03728 | ||
|
|
5e2ab9af3d | ||
|
|
d520e0a93a | ||
|
|
03ecb47f6f | ||
|
|
3effcb7384 | ||
|
|
06c31bee85 | ||
|
|
5c03b34290 | ||
|
|
af38ebbb81 | ||
|
|
de9b08fa2e | ||
|
|
ab9e949b68 | ||
|
|
ea4be86ae2 | ||
|
|
160c72d2f3 | ||
|
|
5caa90f6c7 | ||
|
|
a5add93747 | ||
|
|
ec9f7dec61 | ||
|
|
e616b51d6f | ||
|
|
cfa4c0f0b6 | ||
|
|
9f3b663fa2 | ||
|
|
4fe428e572 | ||
|
|
5cc18b04ae | ||
|
|
33202260e3 | ||
|
|
189552ac65 | ||
|
|
42149ffab2 | ||
|
|
03dbe1ee5b | ||
|
|
8cf047d713 | ||
|
|
9e1d31fc2a | ||
|
|
0e6c30b478 | ||
|
|
d8218f0bf7 | ||
|
|
45b51c15c7 | ||
|
|
61b5ea9d14 | ||
|
|
d2cfdfa8e8 | ||
|
|
8e6d174f20 | ||
|
|
c65b850529 | ||
|
|
a105d8a575 | ||
|
|
7da192e8dc | ||
|
|
ef9267d8fc | ||
|
|
0994ee2d2a | ||
|
|
22f1375380 | ||
|
|
6ed5555706 | ||
|
|
a7a902acd6 | ||
|
|
3776fdff9d | ||
|
|
7114b87bdd | ||
|
|
0bccc0dd87 | ||
|
|
cf980951a4 | ||
|
|
a81e55f41c | ||
|
|
5cf3947b15 | ||
|
|
298529edc2 | ||
|
|
5137bb9483 |
@@ -1,10 +1,11 @@
|
||||
# Multi Version: 16.1.0 - The Flow State
|
||||
# Multi Version: 16.0.0 - Connecting the dots
|
||||
**Key Changes**
|
||||
- Updated Processors to have more controlled over scheduled processes
|
||||
- Forwarding connections
|
||||
- New Timeout handling
|
||||
|
||||
Refer to the [Change Log](https://github.com/rayaman/multi/blob/master/docs/changes.md) for more infromation
|
||||
- Expanded connection logic
|
||||
- New integration priorityManager
|
||||
- Tests for threads
|
||||
- Consistent behavior between the threading integrations
|
||||
- Improved love2d threading
|
||||
- Bug fixes
|
||||
|
||||
Found an issue? Please [submit it](https://github.com/rayaman/multi/issues) and someone will look into it!
|
||||
|
||||
@@ -12,7 +13,7 @@ My multitasking library for lua. It is a pure lua binding, with exceptions of th
|
||||
|
||||
</br>
|
||||
|
||||
Progress is being made in [v16.1.0](https://github.com/rayaman/multi/tree/v16.1.0)
|
||||
Progress is being made in [v16.0.0](https://github.com/rayaman/multi/tree/v16.0.0)
|
||||
---
|
||||
|
||||
</br>
|
||||
@@ -51,7 +52,7 @@ Planned features/TODO
|
||||
- [x] ~~Create test suite (In progress, mostly done)~~
|
||||
- [ ] Network Parallelism rework
|
||||
|
||||
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/docs/Documentation.md)
|
||||
Usage: [Check out the documentation for more info](https://github.com/rayaman/multi/blob/master/Documentation.md)
|
||||
-----
|
||||
|
||||
You can run tests in 2 ways:
|
||||
|
||||
-154
@@ -1,8 +1,6 @@
|
||||
# Changelog
|
||||
Table of contents
|
||||
---
|
||||
[Update 16.1.0 - The Flow State](#update-1610---the-flow-state)</br>
|
||||
[Update 16.0.1 - Bug fix](#update-1601---bug-fix)</br>
|
||||
[Update 16.0.0 - Connecting the dots](#update-1600---getting-the-priorities-straight)</br>
|
||||
[Update 15.3.1 - Bug fix](#update-1531---bug-fix)</br>
|
||||
[Update 15.3.0 - A world of connections](#update-1530---a-world-of-connections)</br>
|
||||
@@ -60,158 +58,6 @@ Table of contents
|
||||
[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 16.1.0 - The Flow State
|
||||
Added
|
||||
---
|
||||
- `multi.UUID()` generates a uuid7, if chronos is installed that will be used as the initial time seed
|
||||
- `More control over processors`
|
||||
- `multi:newProcessor(name, opts, priority)` -- Now accepts a opts table. Old param still works
|
||||
|
||||
| Option | Description | Default |
|
||||
| --- | --- | --- |
|
||||
| Attach | If true a hook will be attached to the parent process and will run when Start is called or Start is set | false |
|
||||
| MaxObjects | Maximum number of objects that a processor can spawn | -1 (disabled) |
|
||||
| MaxThreads | Maximum number of threads that a processor can spawn | -1 (disabled) |
|
||||
| Start | If true the processor will start instantlly | false |
|
||||
| Priority | If true the processor will use the priority handler | false |
|
||||
| TaskDelay | Sets the task delay in seconds between each tasks execution | 0 |
|
||||
| TashHandler | If false will disable the task feature of a processor | true |
|
||||
- `proc:newThread()` returns nil, "errorstring" if it was unable to create a thread
|
||||
- `proc:new[Object]` now returns {unscheduled}, "errorstring", used to just return the {scheduledObject} and no errorstring
|
||||
- `proc:getMaxThreads()` -- returns the max thread limit
|
||||
- `proc:setMaxThreads(n)` -- sets the max thread limit
|
||||
- `proc:getMaxObjects()` -- gets the max object limit
|
||||
- `proc:setMaxObjects(n)` -- sets the max object limit
|
||||
- `proc.Status` -- A table that contains all status errors that occured in a process
|
||||
Example:
|
||||
```lua
|
||||
local multi, thread = require("multi"):init()
|
||||
|
||||
proc = multi:newProcessor("thread test",{
|
||||
Start = true,
|
||||
MaxThreads = 1,
|
||||
MaxObjects = 1,
|
||||
Attach = true,
|
||||
TaskDelay = .1,
|
||||
Priority = true,
|
||||
TaskHandler = false
|
||||
})
|
||||
|
||||
print(proc:newThread("testing",function()
|
||||
while true do
|
||||
print("STATUS:\n---")
|
||||
for i,v in ipairs(proc.Status) do
|
||||
print(i,v)
|
||||
end
|
||||
thread.sleep(1)
|
||||
end
|
||||
end))
|
||||
proc:newThread("testing 2",function()
|
||||
while true do
|
||||
print("testing 2...")
|
||||
thread.sleep(1)
|
||||
end
|
||||
end)
|
||||
proc:newThread("testing 3",function()
|
||||
while true do
|
||||
print("testing 3...")
|
||||
thread.sleep(1)
|
||||
end
|
||||
end)
|
||||
|
||||
proc:newLoop(function()
|
||||
--
|
||||
end)
|
||||
|
||||
print(proc:newLoop(function()
|
||||
--
|
||||
end))
|
||||
|
||||
multi:mainloop()
|
||||
```
|
||||
- `multi.hasType(typ)` returns true if a type has been registered
|
||||
- `multi.isMultiObj(obj)` returns true if the object is a multi object
|
||||
- `multi.forwardConnection(src, dest)` forwards events from one connection to another connection. Doesn't modify anything and both connections are triggered when src is Fired, but not when dest is fired.
|
||||
- `multi.isTimeout(res)` returns true if the response it gets is a timeout type or a string equal to `multi.TIMEOUT`'s value
|
||||
- `multi:newTimeout(seconds)` returns a connection that will trigger after a certain amount of time. See example below:
|
||||
```lua
|
||||
local multi, thread = require("multi"):init()
|
||||
|
||||
data = multi:newConnection()
|
||||
|
||||
-- This alarm takes too long... We will timeout
|
||||
multi:newAlarm(4):OnRing(function()
|
||||
data:Fire({Type="request"},"data is tasty")
|
||||
end)
|
||||
|
||||
multi:newThread(function()
|
||||
res, data = thread.hold(data + multi:newTimeout(3)) -- combined connections allow this to work
|
||||
if multi.isTimeout(res) then
|
||||
print("We timed out!")
|
||||
else
|
||||
print("We got the data:", data)
|
||||
end
|
||||
os.exit()
|
||||
end)
|
||||
|
||||
multi:mainloop()
|
||||
```
|
||||
- `connection % function` can now modify the arguments of a connection. See above example modified below
|
||||
```lua
|
||||
local multi, thread = require("multi"):init()
|
||||
|
||||
local data = multi:newAlarm(1).OnRing % function() return {Type="request"}, "data is tasty" end
|
||||
|
||||
multi:newThread(function()
|
||||
res, data = thread.hold(data + multi:newTimeout(3))
|
||||
if multi.isTimeout(res) then
|
||||
print("We timed out!")
|
||||
else
|
||||
print("We got the data:", data)
|
||||
end
|
||||
os.exit()
|
||||
end)
|
||||
|
||||
multi:mainloop()
|
||||
```
|
||||
|
||||
If the alarm takes longer the the timeout: `We timed out!` If the alarm is shorter: `We got the data: data is tasty`
|
||||
|
||||
Changed
|
||||
---
|
||||
- `multi:newBase(tp,ins,callback)` now accepts a tp param and a callback function. Callback is expected to return true/false, errorstring. If callback is false it will cancel scheduling of an object. If type is set the type of the object will be set.
|
||||
|
||||
**Note:** This is all internal functionality
|
||||
|
||||
# Update 16.0.1 - Bug fix
|
||||
Fixed
|
||||
---
|
||||
- thread.pushStatus() wasn't properly working when forwarding events from THREAD.pushStatus OnStatus connection. This bug also caused stack overflow errors with the following code
|
||||
```lua
|
||||
func = thread:newFunction(function()
|
||||
for i=1,10 do
|
||||
thread.sleep(1)
|
||||
thread.pushStatus(i)
|
||||
end
|
||||
end)
|
||||
|
||||
func2 = thread:newFunction(function()
|
||||
local ref = func()
|
||||
ref.OnStatus(function(num)
|
||||
-- do stuff with this data
|
||||
|
||||
thread.pushStatus(num*2) -- Technically this is not ran within a thread. This is ran outside of a thread inside the thread handler.
|
||||
end)
|
||||
end)
|
||||
|
||||
local handler = func2()
|
||||
handler.OnStatus(function(num)
|
||||
print(num)
|
||||
end)
|
||||
|
||||
multi:mainloop()
|
||||
```
|
||||
|
||||
# Update 16.0.0 - Getting the priorities straight
|
||||
|
||||
## Added New Integration: **priorityManager**
|
||||
|
||||
@@ -76,23 +76,17 @@ end
|
||||
|
||||
local types = {}
|
||||
function multi.registerType(typ, p)
|
||||
if multi["$"..typ:upper():gsub("_","")] then return typ end
|
||||
multi["$"..typ:upper():gsub("_","")] = typ
|
||||
if multi[typ:upper():gsub("_","")] then return typ end
|
||||
multi[typ:upper():gsub("_","")] = typ
|
||||
table.insert(types, {typ, p or typ})
|
||||
return typ
|
||||
end
|
||||
|
||||
function multi.hasType(typ)
|
||||
if multi["$"..typ:upper():gsub("_","")] then
|
||||
return multi["$"..typ:upper():gsub("_","")]
|
||||
end
|
||||
end
|
||||
|
||||
function multi.getTypes()
|
||||
return types
|
||||
end
|
||||
|
||||
multi.Version = "16.1.0"
|
||||
multi.Version = "16.0.0"
|
||||
multi.Name = "root"
|
||||
multi.NIL = {Type="NIL"}
|
||||
local NIL = multi.NIL
|
||||
@@ -101,7 +95,7 @@ multi.Children = {}
|
||||
multi.Active = true
|
||||
multi.Type = multi.registerType("rootprocess")
|
||||
multi.LinkedPath = multi
|
||||
multi.TIMEOUT = multi.registerType("TIMEOUT", "timeouts")
|
||||
multi.TIMEOUT = "TIMEOUT"
|
||||
multi.TID = 0
|
||||
multi.defaultSettings = {}
|
||||
|
||||
@@ -191,29 +185,9 @@ function multi.randomString(n)
|
||||
return str
|
||||
end
|
||||
|
||||
function multi.isMulitObj(obj)
|
||||
if type(obj)=="table" then
|
||||
if obj.Type ~= nil then
|
||||
return multi.hasType(obj.Type) ~= nil
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function multi.forwardConnection(src, dest)
|
||||
if multi.isMulitObj(src) and multi.isMulitObj(dest) then
|
||||
src(function(...)
|
||||
dest:Fire(...)
|
||||
end)
|
||||
else
|
||||
multi.error("Cannot forward non-connection objects")
|
||||
end
|
||||
end
|
||||
|
||||
local optimization_stats = {}
|
||||
local ignoreconn = true
|
||||
local empty_func = function() end
|
||||
|
||||
function multi:newConnection(protect,func,kill)
|
||||
local processor = self
|
||||
local c={}
|
||||
@@ -247,7 +221,6 @@ function multi:newConnection(protect,func,kill)
|
||||
for i = #conns, 1, -1 do
|
||||
obj.rawadd = true
|
||||
obj(conns[i])
|
||||
obj.rawadd = false
|
||||
end
|
||||
return obj
|
||||
end,
|
||||
@@ -257,22 +230,6 @@ function multi:newConnection(protect,func,kill)
|
||||
obj2(function(...)
|
||||
cn:Fire(obj1(...))
|
||||
end)
|
||||
elseif type(obj1) == "table" and type(obj2) == "function" then
|
||||
local conns = obj1:Bind({})
|
||||
for i = 1,#conns do
|
||||
obj1(function(...)
|
||||
conns[i](obj2(...))
|
||||
end)
|
||||
end
|
||||
obj1.__connectionAdded = function(conn, func)
|
||||
obj1:Unconnect(conn)
|
||||
obj1.rawadd = true
|
||||
obj1:Connect(function(...)
|
||||
func(obj2(...))
|
||||
end)
|
||||
obj1.rawadd = false
|
||||
end
|
||||
return obj1
|
||||
else
|
||||
error("Invalid mod!", type(obj1), type(obj2),"Expected function, connection(table)")
|
||||
end
|
||||
@@ -320,7 +277,6 @@ function multi:newConnection(protect,func,kill)
|
||||
end
|
||||
end)
|
||||
end
|
||||
return obj1
|
||||
elseif type(obj1) == "table" and type(obj2) == "table" then
|
||||
--
|
||||
else
|
||||
@@ -491,7 +447,6 @@ function multi:newConnection(protect,func,kill)
|
||||
func = function(...)
|
||||
__CurrentConnectionThread = th
|
||||
fref(...)
|
||||
__CurrentConnectionThread = nil
|
||||
end
|
||||
end
|
||||
table.insert(fast, func)
|
||||
@@ -536,10 +491,6 @@ function multi:newConnection(protect,func,kill)
|
||||
return temp
|
||||
end
|
||||
|
||||
function c:Get()
|
||||
return fast
|
||||
end
|
||||
|
||||
function c:Remove()
|
||||
local temp = fast
|
||||
fast={}
|
||||
@@ -602,7 +553,8 @@ end
|
||||
-- Advance Timer stuff
|
||||
function multi:SetTime(n)
|
||||
if not n then n=3 end
|
||||
local c,err=self:newBase(multi.registerType("timemaster"))
|
||||
local c=self:newBase()
|
||||
c.Type=multi.registerType("timemaster")
|
||||
c.timer=self:newTimer()
|
||||
c.timer:Start()
|
||||
c.set=n
|
||||
@@ -618,7 +570,7 @@ function multi:SetTime(n)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return self,err
|
||||
return self
|
||||
end
|
||||
|
||||
function multi:ResolveTimer(...)
|
||||
@@ -698,49 +650,8 @@ function multi:isDone()
|
||||
return self.Active~=true
|
||||
end
|
||||
|
||||
local time = os.time
|
||||
local ok, chronos = pcall(require, "chronos") -- hpc
|
||||
|
||||
if ok then
|
||||
math.randomseed(chronos.nanotime()*1000000000)
|
||||
else
|
||||
math.randomseed(time())
|
||||
end
|
||||
|
||||
function multi.UUID()
|
||||
|
||||
-- random bytes
|
||||
local value = {}
|
||||
for i = 1, 16 do
|
||||
value[i] = math.random(0, 255)
|
||||
end
|
||||
|
||||
-- current timestamp in ms
|
||||
local timestamp = time() * 1000
|
||||
|
||||
-- timestamp
|
||||
value[1] = (timestamp >> 40) & 0xFF
|
||||
value[2] = (timestamp >> 32) & 0xFF
|
||||
value[3] = (timestamp >> 24) & 0xFF
|
||||
value[4] = (timestamp >> 16) & 0xFF
|
||||
value[5] = (timestamp >> 8) & 0xFF
|
||||
value[6] = timestamp & 0xFF
|
||||
|
||||
-- version and variant
|
||||
value[7] = (value[7] & 0x0F) | 0x70
|
||||
value[9] = (value[9] & 0x3F) | 0x80
|
||||
res = ""
|
||||
for i = 1, #value do
|
||||
res = res .. string.format('%02x', value[i])
|
||||
if i == 4 or i == 6 or i == 8 or i == 10 then
|
||||
res = res .. "-"
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function multi:create(ref)
|
||||
ref.UID = self.UUID()
|
||||
ref.UID = "U"..multi.randomString(12)
|
||||
self.OnObjectCreated:Fire(ref, self)
|
||||
return self
|
||||
end
|
||||
@@ -752,7 +663,7 @@ end
|
||||
|
||||
--Constructors [CORE]
|
||||
local _tid = 0
|
||||
function multi:newBase(tp,ins,callback)
|
||||
function multi:newBase(ins)
|
||||
if not(self.Type==multi.registerType("rootprocess") or self.Type==multi.registerType("process", "processes")) then multi.error('Can only create an object on multi or an interface obj') return false end
|
||||
local c = {}
|
||||
if self.Type==multi.registerType("process", "processes") then
|
||||
@@ -770,7 +681,6 @@ function multi:newBase(tp,ins,callback)
|
||||
c.Act=function() end
|
||||
c.Parent=self
|
||||
c.creationTime = clock()
|
||||
c.Type = tp
|
||||
|
||||
function c:Pause()
|
||||
c.Parent.Pause(self)
|
||||
@@ -781,30 +691,16 @@ function multi:newBase(tp,ins,callback)
|
||||
c.Parent.Resume(self)
|
||||
return self
|
||||
end
|
||||
|
||||
_tid = _tid + 1 -- Even if the task isn't scheduled, we want to increment this
|
||||
|
||||
if type(callback) == "function" then
|
||||
local res, err = callback(tp)
|
||||
if not res then
|
||||
return c, err
|
||||
end
|
||||
end
|
||||
|
||||
if ins then
|
||||
table.insert(self.Mainloop,ins,c)
|
||||
else
|
||||
table.insert(self.Mainloop,c)
|
||||
end
|
||||
_tid = _tid + 1
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:newTimeout(timeout)
|
||||
local c={}
|
||||
c.Type = multi.registerType(multi.TIMEOUT, "timeouts")
|
||||
return function(self) self:Destroy() return c end % self:newAlarm(timeout).OnRing
|
||||
end
|
||||
|
||||
function multi:newTimer()
|
||||
local c={}
|
||||
c.Type=multi.registerType("timer", "timers")
|
||||
@@ -839,7 +735,8 @@ end
|
||||
|
||||
--Core Actors
|
||||
function multi:newEvent(task, func)
|
||||
local c,err=self:newBase(multi.registerType("event", "events"))
|
||||
local c=self:newBase()
|
||||
c.Type=multi.registerType("event", "events")
|
||||
local task = task or function() end
|
||||
function c:Act()
|
||||
local t = task(self)
|
||||
@@ -861,11 +758,12 @@ function multi:newEvent(task, func)
|
||||
self:setPriority("core")
|
||||
c:setName(c.Type)
|
||||
self:create(c)
|
||||
return c,err
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:newUpdater(skip, func)
|
||||
local c,err=self:newBase(multi.registerType("updater", "updaters"))
|
||||
local c=self:newBase()
|
||||
c.Type=multi.registerType("updater", "updaters")
|
||||
local pos = 1
|
||||
local skip = skip or 1
|
||||
function c:Act()
|
||||
@@ -886,11 +784,12 @@ function multi:newUpdater(skip, func)
|
||||
c.OnUpdate(func)
|
||||
end
|
||||
self:create(c)
|
||||
return c,err
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:newAlarm(set, func)
|
||||
local c,err=self:newBase(multi.registerType("alarm", "alarms"))
|
||||
local c=self:newBase()
|
||||
c.Type=multi.registerType("alarm", "alarms")
|
||||
c:setPriority("Low")
|
||||
c.set=set or 0
|
||||
local count = 0
|
||||
@@ -926,11 +825,12 @@ function multi:newAlarm(set, func)
|
||||
end
|
||||
c:setName(c.Type)
|
||||
self:create(c)
|
||||
return c,err
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:newLoop(func, notime)
|
||||
local c,err=self:newBase(multi.registerType("loop", "loops"))
|
||||
local c=self:newBase()
|
||||
c.Type = multi.registerType("loop", "loops")
|
||||
local start=clock()
|
||||
if notime then
|
||||
function c:Act()
|
||||
@@ -952,12 +852,13 @@ function multi:newLoop(func, notime)
|
||||
|
||||
self:create(c)
|
||||
c:setName(c.Type)
|
||||
return c,err
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:newStep(start,reset,count,skip)
|
||||
local c,err=self:newBase(multi.registerType("step", "steps"))
|
||||
local c=self:newBase()
|
||||
think=1
|
||||
c.Type=multi.registerType("step", "steps")
|
||||
c.pos=start or 1
|
||||
c.endAt=reset or math.huge
|
||||
c.skip=skip or 0
|
||||
@@ -1011,11 +912,12 @@ function multi:newStep(start,reset,count,skip)
|
||||
end
|
||||
c:setName(c.Type)
|
||||
self:create(c)
|
||||
return c,err
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:newTLoop(func, set)
|
||||
local c,err=self:newBase(multi.registerType("tloop", "tloops"))
|
||||
local c=self:newBase()
|
||||
c.Type=multi.registerType("tloop", "tloops")
|
||||
c.set=set or 0
|
||||
c.timer=self:newTimer()
|
||||
c.life=0
|
||||
@@ -1056,7 +958,7 @@ function multi:newTLoop(func, set)
|
||||
|
||||
self:create(c)
|
||||
|
||||
return c,err
|
||||
return c
|
||||
end
|
||||
|
||||
function multi:setTimeout(func, t)
|
||||
@@ -1176,38 +1078,10 @@ end
|
||||
|
||||
local sandcount = 1
|
||||
|
||||
function multi:newProcessor(name, opts, priority)
|
||||
local nothread, attach
|
||||
if type(opts) ~= "table" then
|
||||
attach = not opts
|
||||
nothread = opts -- support old params
|
||||
end
|
||||
function multi:newProcessor(name, nothread, priority)
|
||||
local c = {}
|
||||
c.Status = {}
|
||||
setmetatable(c,{__index = multi})
|
||||
local name = name or "Processor_" .. sandcount
|
||||
local maxThreads = -1
|
||||
local maxObjects = -1
|
||||
local taskhandler = true
|
||||
|
||||
rootBase = multi.newBase
|
||||
|
||||
local function setStatus(status)
|
||||
table.insert(c.Status,status)
|
||||
return status
|
||||
end
|
||||
|
||||
local callback = function(tp)
|
||||
if maxObjects <0 or #c.Mainloop < maxObjects then
|
||||
return true
|
||||
end
|
||||
return false, setStatus(string.format("Unable to create [%s]: MAX_OBJECTS: '%d' current scheduled objects: '%d'", tp, maxObjects, #c.Mainloop))
|
||||
end
|
||||
|
||||
function c:newBase(tp,ins)
|
||||
return rootBase(self,tp,ins,callback)
|
||||
end
|
||||
|
||||
sandcount = sandcount + 1
|
||||
c.Mainloop = {}
|
||||
c.Type = multi.registerType("process", "processes")
|
||||
@@ -1223,25 +1097,13 @@ function multi:newProcessor(name, opts, priority)
|
||||
local boost = 1
|
||||
local handler
|
||||
|
||||
if type(opts) == "table" then
|
||||
priority = opts.Priority or false
|
||||
Active = opts.Start or false
|
||||
maxThreads = opts.MaxThreads or -1
|
||||
maxObjects = opts.MaxObjects or -1
|
||||
task_delay = opts.TaskDelay or 0
|
||||
attach = opts.Attach or false
|
||||
if opts.TaskHandler == false then -- The default was true
|
||||
taskhandler = false
|
||||
end
|
||||
end
|
||||
|
||||
if priority then
|
||||
handler = c:createPriorityHandler(c)
|
||||
else
|
||||
handler = c:createHandler(c)
|
||||
end
|
||||
|
||||
if attach then -- Don't create a loop if we are triggering this manually
|
||||
if not nothread then -- Don't create a loop if we are triggering this manually
|
||||
c.process = self:newLoop(function()
|
||||
if Active then
|
||||
c:uManager(true)
|
||||
@@ -1275,10 +1137,7 @@ function multi:newProcessor(name, opts, priority)
|
||||
end
|
||||
|
||||
function c:newThread(name, func,...)
|
||||
if maxThreads < 0 or (#c.threads+#c.startme < maxThreads) then
|
||||
return thread.newThread(c, name, func, ...)
|
||||
end
|
||||
return nil, setStatus(string.format("Unable to create [thread]: '%s' MAX_THREADS: '%d' current scheduled threads: '%d'",name,maxThreads,#c.threads+#c.startme))
|
||||
return thread.newThread(c, name, func, ...)
|
||||
end
|
||||
|
||||
function c:newFunction(func, holdme)
|
||||
@@ -1287,24 +1146,6 @@ function multi:newProcessor(name, opts, priority)
|
||||
end, holdme)()
|
||||
end
|
||||
|
||||
function c:getMaxThreads()
|
||||
return maxThreads
|
||||
end
|
||||
|
||||
function c:setMaxThreads(n)
|
||||
maxThreads = n
|
||||
return c
|
||||
end
|
||||
|
||||
function c:getMaxObjects()
|
||||
return maxObjects
|
||||
end
|
||||
|
||||
function c:setMaxObjects(n)
|
||||
maxObjects = n
|
||||
return c
|
||||
end
|
||||
|
||||
function c:boost(count)
|
||||
boost = count or 1
|
||||
if boost > 1 then
|
||||
@@ -1360,24 +1201,22 @@ function multi:newProcessor(name, opts, priority)
|
||||
end
|
||||
end
|
||||
|
||||
if taskhandler then
|
||||
c:newThread("Task Handler", function()
|
||||
local self = multi:getCurrentProcess()
|
||||
local function task_holder()
|
||||
return #self.tasks > 0
|
||||
c:newThread("Task Handler", function()
|
||||
local self = multi:getCurrentProcess()
|
||||
local function task_holder()
|
||||
return #self.tasks > 0
|
||||
end
|
||||
while true do
|
||||
if #self.tasks > 0 then
|
||||
table.remove(self.tasks,1)()
|
||||
else
|
||||
thread.hold(task_holder)
|
||||
end
|
||||
while true do
|
||||
if #self.tasks > 0 then
|
||||
table.remove(self.tasks,1)()
|
||||
else
|
||||
thread.hold(task_holder)
|
||||
end
|
||||
if task_delay~=0 then
|
||||
thread.hold(task_delay)
|
||||
end
|
||||
if task_delay~=0 then
|
||||
thread.hold(task_delay)
|
||||
end
|
||||
end).OnError(multi.error)
|
||||
end
|
||||
end
|
||||
end).OnError(multi.error)
|
||||
|
||||
table.insert(processes,c)
|
||||
self:create(c)
|
||||
@@ -1596,7 +1435,7 @@ local function cleanReturns(...)
|
||||
end
|
||||
|
||||
function thread.pushStatus(...)
|
||||
local t = __CurrentConnectionThread or thread.getRunningThread()
|
||||
local t = thread.getRunningThread() or __CurrentConnectionThread
|
||||
t.statusconnector:Fire(...)
|
||||
end
|
||||
|
||||
@@ -2388,13 +2227,6 @@ end
|
||||
-- UTILS
|
||||
--------
|
||||
|
||||
function multi.isTimeout(res)
|
||||
if type(res) == "table" then
|
||||
return res.Type == multi.TIMEOUT
|
||||
end
|
||||
return res == multi.TIMEOUT
|
||||
end
|
||||
|
||||
function table.merge(t1, t2)
|
||||
for k,v in pairs(t2) do
|
||||
if type(v) == 'table' then
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
-- Allows the creation of states
|
||||
@@ -1,42 +0,0 @@
|
||||
package = "multi"
|
||||
version = "16.0-1"
|
||||
source = {
|
||||
url = "git://github.com/rayaman/multi.git",
|
||||
tag = "v16.0.1",
|
||||
}
|
||||
description = {
|
||||
summary = "Lua Multi tasking library",
|
||||
detailed = [[
|
||||
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
|
||||
Check github for documentation.
|
||||
]],
|
||||
homepage = "https://github.com/rayaman/multi",
|
||||
license = "MIT"
|
||||
}
|
||||
dependencies = {
|
||||
"lua >= 5.1"
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["multi"] = "init.lua",
|
||||
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
|
||||
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
|
||||
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
|
||||
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
|
||||
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
|
||||
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
|
||||
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
|
||||
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
|
||||
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
|
||||
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
|
||||
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
|
||||
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
|
||||
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
|
||||
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
|
||||
["multi.integration.threading"] = "integration/threading.lua",
|
||||
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
|
||||
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
|
||||
--["multi.integration.networkManager"] = "integration/networkManager.lua",
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package = "multi"
|
||||
version = "16.1-0"
|
||||
source = {
|
||||
url = "git://github.com/rayaman/multi.git",
|
||||
tag = "v16.1.0",
|
||||
}
|
||||
description = {
|
||||
summary = "Lua Multi tasking library",
|
||||
detailed = [[
|
||||
This library contains many methods for multi tasking. Features non coroutine based multi-tasking, coroutine based multi-tasking, and system threading (Requires use of an integration).
|
||||
Check github for documentation.
|
||||
]],
|
||||
homepage = "https://github.com/rayaman/multi",
|
||||
license = "MIT"
|
||||
}
|
||||
dependencies = {
|
||||
"lua >= 5.1"
|
||||
}
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
["multi"] = "init.lua",
|
||||
["multi.integration.lanesManager"] = "integration/lanesManager/init.lua",
|
||||
["multi.integration.lanesManager.extensions"] = "integration/lanesManager/extensions.lua",
|
||||
["multi.integration.lanesManager.threads"] = "integration/lanesManager/threads.lua",
|
||||
["multi.integration.loveManager"] = "integration/loveManager/init.lua",
|
||||
["multi.integration.loveManager.extensions"] = "integration/loveManager/extensions.lua",
|
||||
["multi.integration.loveManager.threads"] = "integration/loveManager/threads.lua",
|
||||
["multi.integration.loveManager.utils"] = "integration/loveManager/threads.lua",
|
||||
--["multi.integration.lovrManager"] = "integration/lovrManager/init.lua",
|
||||
--["multi.integration.lovrManager.extensions"] = "integration/lovrManager/extensions.lua",
|
||||
--["multi.integration.lovrManager.threads"] = "integration/lovrManager/threads.lua",
|
||||
["multi.integration.pseudoManager"] = "integration/pseudoManager/init.lua",
|
||||
["multi.integration.pseudoManager.extensions"] = "integration/pseudoManager/extensions.lua",
|
||||
["multi.integration.pseudoManager.threads"] = "integration/pseudoManager/threads.lua",
|
||||
["multi.integration.luvitManager"] = "integration/luvitManager.lua",
|
||||
["multi.integration.threading"] = "integration/threading.lua",
|
||||
["multi.integration.sharedExtensions"] = "integration/sharedExtensions/init.lua",
|
||||
["multi.integration.priorityManager"] = "integration/priorityManager/init.lua",
|
||||
--["multi.integration.networkManager"] = "integration/networkManager.lua",
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,6 @@ local multi, thread = require("multi"):init{print=true,warn=true,error=true}--{p
|
||||
local good = false
|
||||
local proc = multi:newProcessor("Test")
|
||||
|
||||
print("Version: "..multi.Version)
|
||||
|
||||
proc.Start()
|
||||
|
||||
proc:newAlarm(3):OnRing(function()
|
||||
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
package.path = "../?/init.lua;../?.lua;"..package.path
|
||||
multi, thread = require("multi"):init{print=true,warn=true,debugging=true}
|
||||
-- for i,v in pairs(thread) do
|
||||
-- print(i,v)
|
||||
-- end
|
||||
|
||||
-- require("multi.integration.priorityManager")
|
||||
|
||||
-- multi.debugging.OnObjectCreated(function(obj, process)
|
||||
-- multi.print("Created:", obj.Type, "in", process.Type, process:getFullName())
|
||||
-- end)
|
||||
|
||||
-- multi.debugging.OnObjectDestroyed(function(obj, process)
|
||||
-- multi.print("Destroyed:", obj.Type, "in", process.Type, process:getFullName())
|
||||
-- end)
|
||||
|
||||
|
||||
-- test = multi:newProcessor("Test")
|
||||
-- test:setPriorityScheme(multi.priorityScheme.TimeBased)
|
||||
|
||||
-- test:newUpdater(10000000):OnUpdate(function()
|
||||
-- print("Print is slowish")
|
||||
-- end)
|
||||
|
||||
-- print("Running...")
|
||||
|
||||
-- local conn1, conn2 = multi:newConnection(), multi:newConnection()
|
||||
-- conn3 = conn1 + conn2
|
||||
|
||||
-- conn1(function()
|
||||
-- print("Hi 1")
|
||||
-- end)
|
||||
|
||||
-- conn2(function()
|
||||
-- print("Hi 2")
|
||||
-- end)
|
||||
|
||||
-- conn3(function()
|
||||
-- print("Hi 3")
|
||||
-- end)
|
||||
|
||||
-- function test(a,b,c)
|
||||
-- print("I run before all and control if execution should continue!")
|
||||
-- return a>b
|
||||
-- end
|
||||
|
||||
-- conn4 = test .. conn1
|
||||
|
||||
-- conn5 = conn2 .. function() print("I run after it all!") end
|
||||
|
||||
-- conn4:Fire(3,2,3)
|
||||
-- -- This second one won't trigger the Hi's
|
||||
-- conn4:Fire(1,2,3)
|
||||
|
||||
-- conn5(function()
|
||||
-- print("Test 1")
|
||||
-- end)
|
||||
|
||||
-- conn5(function()
|
||||
-- print("Test 2")
|
||||
-- end)
|
||||
|
||||
-- conn5(function()
|
||||
-- print("Test 3")
|
||||
-- end)
|
||||
|
||||
-- conn5:Fire()
|
||||
|
||||
|
||||
|
||||
|
||||
-- multi.print("Testing thread:newProcessor()")
|
||||
|
||||
-- proc = thread:newProcessor("Test")
|
||||
|
||||
-- proc:newLoop(function()
|
||||
-- multi.print("Running...")
|
||||
-- thread.sleep(1)
|
||||
-- end)
|
||||
|
||||
-- proc:newThread(function()
|
||||
-- while true do
|
||||
-- multi.warn("Everything is a thread in this proc!")
|
||||
-- thread.sleep(1)
|
||||
-- end
|
||||
-- end)
|
||||
|
||||
-- proc:newAlarm(5):OnRing(function(a)
|
||||
-- multi.print(";) Goodbye")
|
||||
-- a:Destroy()
|
||||
-- end)
|
||||
|
||||
-- local func = thread:newFunction(function()
|
||||
-- thread.sleep(4)
|
||||
-- print("Hello!")
|
||||
-- end)
|
||||
|
||||
-- multi:newTLoop(func, 1)
|
||||
|
||||
-- multi:mainloop()
|
||||
|
||||
-- multi:setTaskDelay(.05)
|
||||
-- multi:newTask(function()
|
||||
-- for i = 1, 10 do
|
||||
-- multi:newTask(function()
|
||||
-- print("Task "..i)
|
||||
-- end)
|
||||
-- end
|
||||
-- end)
|
||||
|
||||
-- local conn = multi:newConnection()
|
||||
-- conn(function() print("Test 1") end)
|
||||
-- conn(function() print("Test 2") end)
|
||||
-- conn(function() print("Test 3") end)
|
||||
-- conn(function() print("Test 4") end)
|
||||
|
||||
-- print("Fire 1")
|
||||
-- conn:Fire()
|
||||
-- conn = -conn
|
||||
-- print("Fire 2")
|
||||
-- conn:Fire()
|
||||
|
||||
-- print(#conn)
|
||||
|
||||
-- thread:newThread("Test thread", function()
|
||||
-- print("Starting thread!")
|
||||
-- thread.defer(function() -- Runs when the thread finishes execution
|
||||
-- print("Clean up time!")
|
||||
-- end)
|
||||
-- --[[
|
||||
-- Do lot's of stuff
|
||||
-- ]]
|
||||
-- thread.sleep(3)
|
||||
-- end)
|
||||
|
||||
multi:mainloop()
|
||||
|
||||
-- local conn1, conn2, conn3 = multi:newConnection(nil,nil,true), multi:newConnection(), multi:newConnection()
|
||||
|
||||
-- local link = conn1(function()
|
||||
-- print("Conn1, first")
|
||||
-- end)
|
||||
|
||||
-- local link2 = conn1(function()
|
||||
-- print("Conn1, second")
|
||||
-- end)
|
||||
|
||||
-- local link3 = conn1(function()
|
||||
-- print("Conn1, third")
|
||||
-- end)
|
||||
|
||||
-- local link4 = conn2(function()
|
||||
-- print("Conn2, first")
|
||||
-- end)
|
||||
|
||||
-- local link5 = conn2(function()
|
||||
-- print("Conn2, second")
|
||||
-- end)
|
||||
|
||||
-- local link6 = conn2(function()
|
||||
-- print("Conn2, third")
|
||||
-- end)
|
||||
|
||||
-- print("Links 1-6",link,link2,link3,link4,link5,link6)
|
||||
-- conn1:Lock(link)
|
||||
-- print("All conns\n-------------")
|
||||
-- conn1:Fire()
|
||||
-- conn2:Fire()
|
||||
|
||||
-- conn1:Unlock(link)
|
||||
|
||||
-- conn1:Unconnect(link3)
|
||||
-- conn2:Unconnect(link6)
|
||||
-- print("All conns Edit\n---------------------")
|
||||
-- conn1:Fire()
|
||||
-- conn2:Fire()
|
||||
|
||||
-- thread:newThread(function()
|
||||
-- print("Awaiting status")
|
||||
-- thread.hold(conn1 + (conn2 * conn3))
|
||||
-- print("Conn or Conn2 and Conn3")
|
||||
-- end)
|
||||
|
||||
-- multi:newAlarm(1):OnRing(function()
|
||||
-- print("Conn")
|
||||
-- conn1:Fire()
|
||||
-- end)
|
||||
-- multi:newAlarm(2):OnRing(function()
|
||||
-- print("Conn2")
|
||||
-- conn2:Fire()
|
||||
-- end)
|
||||
-- multi:newAlarm(3):OnRing(function()
|
||||
-- print("Conn3")
|
||||
-- conn3:Fire()
|
||||
-- os.exit()
|
||||
-- end)
|
||||
|
||||
|
||||
-- local conn = multi:newSystemThreadedConnection("conn"):init()
|
||||
|
||||
-- multi:newSystemThread("Thread_Test_1", function()
|
||||
-- local multi, thread = require("multi"):init()
|
||||
-- local conn = GLOBAL["conn"]:init()
|
||||
-- local console = THREAD.getConsole()
|
||||
-- conn(function(a,b,c)
|
||||
-- console.print(THREAD:getName().." was triggered!",a,b,c)
|
||||
-- end)
|
||||
-- multi:mainloop()
|
||||
-- end)
|
||||
|
||||
-- multi:newSystemThread("Thread_Test_2", function()
|
||||
-- local multi, thread = require("multi"):init()
|
||||
-- local conn = GLOBAL["conn"]:init()
|
||||
-- local console = THREAD.getConsole()
|
||||
-- conn(function(a,b,c)
|
||||
-- console.print(THREAD:getName().." was triggered!",a,b,c)
|
||||
-- end)
|
||||
-- multi:newAlarm(2):OnRing(function()
|
||||
-- console.print("Fire 2!!!")
|
||||
-- conn:Fire(4,5,6)
|
||||
-- THREAD.kill()
|
||||
-- end)
|
||||
|
||||
-- multi:mainloop()
|
||||
-- end)
|
||||
-- local console = THREAD.getConsole()
|
||||
-- conn(function(a,b,c)
|
||||
-- console.print("Mainloop conn got triggered!",a,b,c)
|
||||
-- end)
|
||||
|
||||
-- alarm = multi:newAlarm(1)
|
||||
-- alarm:OnRing(function()
|
||||
-- console.print("Fire 1!!!")
|
||||
-- conn:Fire(1,2,3)
|
||||
-- end)
|
||||
|
||||
-- alarm = multi:newAlarm(3):OnRing(function()
|
||||
-- multi:newSystemThread("Thread_Test_3",function()
|
||||
-- local multi, thread = require("multi"):init()
|
||||
-- local conn = GLOBAL["conn"]:init()
|
||||
-- local console = THREAD.getConsole()
|
||||
-- conn(function(a,b,c)
|
||||
-- console.print(THREAD:getName().." was triggered!",a,b,c)
|
||||
-- end)
|
||||
-- multi:newAlarm(4):OnRing(function()
|
||||
-- console.print("Fire 3!!!")
|
||||
-- conn:Fire(7,8,9)
|
||||
-- end)
|
||||
-- multi:mainloop()
|
||||
-- end)
|
||||
-- end)
|
||||
|
||||
-- multi:newSystemThread("Thread_Test_4",function()
|
||||
-- local multi, thread = require("multi"):init()
|
||||
-- local conn = GLOBAL["conn"]:init()
|
||||
-- local conn2 = multi:newConnection()
|
||||
-- local console = THREAD.getConsole()
|
||||
-- multi:newAlarm(2):OnRing(function()
|
||||
-- conn2:Fire()
|
||||
-- end)
|
||||
-- multi:newThread(function()
|
||||
-- console.print("Conn Test!")
|
||||
-- thread.hold(conn + conn2)
|
||||
-- console.print("It held!")
|
||||
-- end)
|
||||
-- multi:mainloop()
|
||||
-- end)
|
||||
|
||||
-- multi:mainloop()
|
||||
--[[
|
||||
newFunction function: 0x00fad170
|
||||
waitFor function: 0x00fad0c8
|
||||
request function: 0x00fa4f10
|
||||
newThread function: 0x00fad1b8
|
||||
--__threads table: 0x00fa4dc8
|
||||
defer function: 0x00fa4f98
|
||||
isThread function: 0x00facd40
|
||||
holdFor function: 0x00fa5058
|
||||
yield function: 0x00faccf8
|
||||
hold function: 0x00fa51a0
|
||||
chain function: 0x00fa5180
|
||||
__CORES 32
|
||||
newISOThread function: 0x00fad250
|
||||
newFunctionBase function: 0x00fad128
|
||||
requests table: 0x00fa4e68
|
||||
newProcessor function: 0x00fad190
|
||||
exec function: 0x00fa50e8
|
||||
pushStatus function: 0x00fad108
|
||||
kill function: 0x00faccd8
|
||||
get function: 0x00fad0a8
|
||||
set function: 0x00fad088
|
||||
getCores function: 0x00facd60
|
||||
skip function: 0x00faccb0
|
||||
--_Requests function: 0x00fa50a0
|
||||
getRunningThread function: 0x00fa4fb8
|
||||
holdWithin function: 0x00facc80
|
||||
sleep function: 0x00fa4df0
|
||||
]]
|
||||
Reference in New Issue
Block a user