Thread Tools Display Modes
10-15-11, 01:58 PM   #1
wellbeing
A Cliff Giant
Join Date: Oct 2009
Posts: 71
Forced pause in loops. I think i figured out a way.

So, I've been working on more source for personal use.

I've seen many addons that somehow utilize a pause. I searched quite a bit to no avail. In particular, those addons that arrange bags seem to have a timed delay in activity during execution.

My thinking was.. if I can use the user defined wait() function to act as the fire for iteration, I can use and increment a table to define my iteration start pts each time wait() fires. (note that wait(), itself, does not increment the table values, the incrementing takes place in the deepest nested loop, as you can see in my code below.)

So, in essence, this is a triple nested loop that is broken (hard return) on the inner most level each time. (only after incrementing the table values from which the loops obtain their start point and then invoking the wait() function) .

This allows for less code than using if/then in place of the loops.

This can also be re-worked in a number of ways, and is versatile to many concepts.

I'm no pro, so I was hoping for feedback. Whatsup?

(also stickied for those of u who prefer it: http://www.wowace.com/paste/4089/)

Code:
local t={}
local startLoop
local printNext
local waitTable = {};
local waitFrame = nil;


SLASH_CPCMD1, SLASH_CPCMD2 = 'signpost', '/sp';
function SlashCmdList.CPCMD(msg, editbox)

	if msg == "test" then
	
		print ("pressed now")
		firePrism_wait(5, print, "printed 5 seconds later")
	
	end
	
	if msg =="test2" then

	       startLoop()
	
	end
	
	
	
end
SlashCmdList["cpcmd"] = SlashCmdList.CPCMD


function startLoop()
	
	t.gemType = t.gemType or 1
	t.bag = t.bag or 0
	t.slot = t.slot or 1
	
	for i=t.gemType, 6 do
		
		
		
		for j = t.bag+1, 5 do
			
			for k= t.slot,  14 do
				
				printNext("gem= "..t.gemType..", bag = "..t.bag..", slot = "..t.slot)
				
				if k == 14 then
					
					t.bag = t.bag+1
					t.slot = 0
									
				end
				
				if j == 5 and t.slot == 0 then

					t.gemType = t.gemType+1
					t.bag = 0
					print("Next gem") 

				end

				t.slot = t.slot+1

				return
			end
		
		end
	
	end
	
end


function printNext(myString)

	--print(myString)
	firePrism_wait(.2, print, myString)
	
end


function firePrism_wait(delay, func, ...)

  if(type(delay)~="number" or type(func)~="function") then
    return false;
  end
  if(waitFrame == nil) then
    waitFrame = CreateFrame("Frame","WaitFrame", UIParent);
    waitFrame:SetScript("onUpdate",function (self,elapse)
      local count = #waitTable;
      local i = 1;
      while(i<=count) do
        local waitRecord = tremove(waitTable,i);
        local d = tremove(waitRecord,1);
        local f = tremove(waitRecord,1);
        local p = tremove(waitRecord,1);
        if(d > elapse) then
          tinsert(waitTable,i,{d-elapse,f,p});
          i = i + 1;
        else
          count = count - 1;
         
		  f(unpack(p));
		 
		  startLoop()
		 
        end
      end
    end);
  end
  tinsert(waitTable,{delay,func,{...}});
  return true;
end
This can be used in a number of ways, but suits me for splitting and sorting items in bags without overlap in slot population causing errors. My area of interest for this code is gems(in this case, the 6 green cata gems). In use, table t{} contains location and quantity information about each gem, but like I said, this template could be useful to others in other ways.

Thanks for checking it out, I'd love any comments/advice.

Last edited by wellbeing : 10-15-11 at 02:30 PM. Reason: comment
  Reply With Quote
10-15-11, 02:26 PM   #2
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
waiting is no option in a wow-addon. the game is haltet until your addon is finished with its action even if its a wait-loop
__________________
The cataclysm broke the world ... and the pandas could not fix it!
  Reply With Quote
10-15-11, 02:29 PM   #3
wellbeing
A Cliff Giant
Join Date: Oct 2009
Posts: 71
Originally Posted by Rilgamon View Post
waiting is no option in a wow-addon. the game is haltet until your addon is finished with its action even if its a wait-loop
This circumvents it. its not a system pause, but a forced delay in your code and only your code. Look closer.
  Reply With Quote
10-15-11, 04:54 PM   #4
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,308
This is not a wait, it's known as a timeout. It's putting aside separate code to be run later. To show some light on the subject, here's the difference.



Wait
Code:
-- Some code
Wait(1000);-- Puts the processor in low-powered sleep mode
-- More code run 1000ms later


Timeout
Code:
-- Some code
Timeout(1000,func);-- Runs func() after 1000 seconds
-- More code runs immediately without delay

Note: Wait() and Timeout() do not exist and are used in pseudo-code to explain the difference in concept.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
10-15-11, 07:08 PM   #5
wellbeing
A Cliff Giant
Join Date: Oct 2009
Posts: 71
Thanks for the clarification, SDPhantom. However, I'm not attempting to shed light on this wait function's misnomer, as I did not write it. It's right out of the wiki.

This post was to illustrate it's use to hard itterate nested loops on a delay.

look closer.

Notice the tables used as iterator start points for the nested loops. In use, one would obviously call to GetContainerNumSlot for the termination index, rather than leaving it at 14.

The tables are updated anytime the wait is called, and the nested loops are exited. Then when wait fires its function, it calls for our original nested loops sequence to resume, using the tabled data as the start points for the iterators.

Last edited by wellbeing : 10-15-11 at 07:12 PM.
  Reply With Quote
10-16-11, 01:06 AM   #6
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
oops I did not scroll down the code because I'd expected functions to be declared before the use and thought you're looking for help how such functions should look ... sorry
__________________
The cataclysm broke the world ... and the pandas could not fix it!
  Reply With Quote
10-16-11, 08:48 AM   #7
wellbeing
A Cliff Giant
Join Date: Oct 2009
Posts: 71
Originally Posted by Rilgamon View Post
oops I did not scroll down the code because I'd expected functions to be declared before the use and thought you're looking for help how such functions should look ... sorry
No problem, thanks for looking either way. I'm pretty sure all my functions are declared except the wait function. It's use is dangerously global for reasons of testing.

  Reply With Quote
10-17-11, 06:55 AM   #8
sigg
Featured Artist
 
sigg's Avatar
Featured
Join Date: Aug 2008
Posts: 1,251
Hello

I am not sure, but I think you are looking for a timer library.

Check our timer library (RDX addon) in this file:
VFL\Timers\Schedulers.lua

(RDX code is full opensource and you can use it, copy it)

Our API:

Code:
--- Adaptive-schedule a recurring process.
-- @description The adaptive scheduler is a system designed to improve the performance impact
-- of frequently-recurring (subsecond precison) tasks.
-- It works by assigning tasks to "slots" within the 1-second interval, then sweeping
-- over those slots and running the tasks. Each task receives a random offset that ensures
-- it does not collide with other tasks. It also reduces overhead by not "thrashing" schedule entries.
-- Moreover, when FPS drops below a user definable number, the adaptive staggered scheduler
-- automatically "dilates" the schedule to slow everything down.
-- @param id An ID that can be later used to stop this schedule
-- @param interval The interval of time of recurring process (min 0.02)
-- @param func The function to call
-- @param ... arg to pass to func
VFLT.AdaptiveSchedule(id, interval, func, ...)
Code:
--- Unschedule by ID from the adaptive scheduler
-- @param id An ID used in VFLT.AdaptiveSchedule
VFLT.AdaptiveUnschedule(id)
Code:
--- Schedule func to be executed dt seconds from now.
-- @description The zero-memory scheduler is an alternative scheduling implementation
-- for "one-off" scheduling tasks.
-- It allocates zero tables and one table entry at schedule time, using
-- nearly no memory and performing very little work. However, its cycle
-- time is linear in the size of the schedule table. Moreover, entities
-- scheduled with ZMSchedule can only be directly unscheduled by handle,
-- creating the need for an API layer on top of ZMSchedule for more
-- complex cases.
-- @param dt The period of time
-- @param func The Function to be executed
-- @return a handle for later descheduling.
function VFLT.ZMSchedule(dt, func)
Code:
--- Unschedule a function scheduled by ZMSchedule. 
-- @param handle the return value from ZMSchedule as the handle.
function VFLT.ZMUnschedule(handle)
Code:
--- Schedule something to happen on the next frame.
-- @param id To identify this task, most of time this is a random number math.random(10000000)
-- @param func The Function to be executed
function VFLT.NextFrame(id, func)
Code:
--- Create a "periodic latch" around a function. The periodic latch guarantees that a function
-- won't be called more often than the period, and if the function should be spammed multiple
-- times, it'll be called again the end of the period
-- @param period The period of time
-- @param f The Function to be executed
-- @return a "go" function
-- @return a "terminate" function that can be used in the event of a shutdown to destroy the latch.
function VFLT.CreatePeriodicLatch(period, f)
__________________
RDX manager
Sigg
  Reply With Quote
10-17-11, 12:37 PM   #9
wellbeing
A Cliff Giant
Join Date: Oct 2009
Posts: 71
Originally Posted by sigg View Post
Hello

I am not sure, but I think you are looking for a timer library.

Check our timer library (RDX addon) in this file:

Thanks sigg! Neat stuff. I used RDX for a bit, created some pretty nasty environments for my gaming, but a wow patch completely raped RDX for me and after a few days I was forced to make some changes to my dependencies in game. I loved the concept, for sure.

I'm not sure the terminology of things, but the code I have above works very well. After invoking similar notions in many ways, I've determined that coders must've been using this sort of thing for many years. It's not that it's really all that complicated, it just hadn't occurred to me to do it until now.

Thanks for the reply, and also.. if there is a term for what I'm doing in my code, I'd love to know it.

Wb
  Reply With Quote
10-17-11, 01:33 PM   #10
Iriel
Super Moderator
WoWInterface Super Mod
Featured
Join Date: Jun 2005
Posts: 578
While the goal of your code is noble and the general idea is sound, it has some serious performance issues for code that runs every frame in an OnUpdate, which I would suggest you resolve if for no other reason than to learn why they are bad.

In no particular order:

1) Using tremove to read 3 values from a 3 value table that serves no other purpose is extremely inefficient, each call to tremove has to look up then invoke a function, the function has to move all of entries in the table, and then return the one you wanted. Stick to local a, b, c = tbl[1], tbl[2], tbl[3].

2) Removing each entry, checking if it's ready to fire, and re-building and putting it back if not, is also very wasteful, both in terms of cycles and garbage. You're much better off looking at each entry, then either remove-and-use, or modify-in place

3) It may be much faster to keep a "currentTime" value (incremented by the 2nd argument to OnUpdate) and express fire time in terms of that, so you dont have to modify the records AT ALL.

4) You may want to consider keeping the array sorted so that the soonest tasks are at the end, then you can scan it from the end each OnUpdate, stop when you find a task that's not ready, and removal will never have to move other entries, only nil out the last one. Alternatively use a heap data structure or linked list.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » Forced pause in loops. I think i figured out a way.

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