Thread Tools Display Modes
09-13-19, 04:38 AM   #1
Odjur
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Feb 2014
Posts: 7
Is there any way to throttle an arbitrary function?

I am currently writing my functions to run for N iterations before calling them again, but it would be much more convenient and consistent to be able to pass my functions off to a handler/scheduler and have them take care of them for me. This is an example of what I am trying to do:

Code:
local thread
local delay
local count = 0

local queue = function()
	for a = 1, 10000000 do
		count = a
	end
end

C_Timer.NewTicker(0, function()
	if queue then
		if not thread then
			thread = coroutine.create(function()
				delay = C_Timer.NewTicker(0, function()
					print(count)
					
					if coroutine.status(thread) == "dead" then
						queue = nil
						thread = nil
						delay:Cancel()
					else
						coroutine.yield()
					end
				end)
				
				queue()
			end)
		end
		
		coroutine.resume(thread)
	end
end)
I was trying to pass my functions to the variable 'queue' and have them turned into coroutines that would be yielded every frame. However it seems that C_Timer.NewTicker doesn't run asynchronously, so it never gets to yield the coroutine.

Is there any way to do what I am trying to do? It seems strange to me that I can't come up with a clean way to throttle my functions. Thanks for your help.
  Reply With Quote
09-13-19, 05:05 AM   #2
MooreaTv
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: May 2019
Posts: 38
To yield every frame you have to call yield inside the loop not after the loop is finished

yield only yields the current coroutine not another one (which wouldn't be possible given the lua interpreter in wow is single threaded, which you can be thankful for otherwise we'd have locking issues)
  Reply With Quote
09-13-19, 06:22 AM   #3
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
I have a lib named Scorpio, it has a task schedule system works like:

Lua Code:
  1. Scorpio "TestAddon" "1.0.0"
  2.  
  3. -- __Async__ is used to wrap the target function, so when the
  4. -- function is called, it'd be processed in a coroutine, the coroutine
  5. -- will be recycled when the target function finished its job
  6. __Async__()
  7. function LoopJob()
  8.     while true do
  9.         NextEvent("PLAYER_REGEN_DISABLED")  -- wait the event
  10.  
  11.         print("Start combat")
  12.  
  13.        local cnt = 0
  14.  
  15.         repeat
  16.             Delay(1)    -- delay for 1 sec
  17.             cnt = cnt + 1
  18.             print("[Combat]", cnt)
  19.         until not InCombatLockdown()
  20.  
  21.         print("End combat")
  22.     end
  23. end
  24.  
  25. -- Start the loop
  26. LoopJob()

With the system, we can avoid the callback hell and keep any logic in one function. And the better part of the system is if we put all hard works to it, it really can smooth the function calls(delay the call if there is too much operations in one phase) and make the fps no dropping.

So, if you are interesting, you can find the lib at https://github.com/kurapica/Scorpio, it's also uploaded to the curseforge.

For your example, you may check the Next and Continue API provided by the Scoprio, the Next is used to delay the process to the next phase, the Continue is used to check if there is enough time in the current phase to continue the process, otherwise, it'd delay it to the next phase.

Last edited by kurapica.igas : 09-13-19 at 06:42 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Is there any way to throttle an arbitrary function?

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off