| 07-07-2008, 12:19 PM | #1 | |
Okay, I've been fiddling around with timers a lot the last day or so, and come up with what appears to be a safe, reliable and lightning fast method of attaching a struct to a timer. Basically, it involves adding a slight amount to the timeout. Obviously, this requires that you know the timeout at both ends to exploit it, but that's normally the case I find (if not always). Due to my method of type casting between int and real, the amount of increase is minimised while maxisiming safety. Attaching values between 0 and 9000 results in no higher than 0.095% increase in timeout according to my tests (see below). Attaching non-structs is not advisable. Timeout wise, it bugged out when I took it to 10 million, but one million seems to be fine (and if you need more than 11 days timeout to attach something to...well, I dunno). Pros: - Very fast (should get inlined by JASSHelper). - Easy-ish to use. Cons: - Slight inaccuracies in timing, which increases as the value attached increases. - Requires that you know the timeout value at both ends. JASS:library CGTimerLib function i2r takes integer i returns real return i return 0. endfunction function r2i takes real r returns integer return r return 0 endfunction function StartTimerStruct takes timer t, integer itime, integer value, boolean repeat, code func returns nothing call TimerStart(t, i2r(itime+value), repeat, func) endfunction function GetTimerStruct takes timer t, integer itime returns integer return r2i(TimerGetTimeout(t))-itime endfunction endlibrary Example usage: JASS:library Example initializer Init globals private real timeout = 5. private integer itimeout endglobals private function Example takes nothing returns nothing call BJDebugMsg("Random int was: " + I2S(GetTimerStruct(GetExpiredTimer(), itimeout))) endfunction private function Init takes nothing returns nothing set itimeout = r2i(timeout) call StartTimerStruct(CreateTimer(), itimeout, GetRandomInt(0, 8191), true, function Example) endfunction endlibrary The precalculating of r2i(timeout) speeds it up, but is also there because Blizzard fails at coding, so I had to avoid a random bug where JASS forgets how to do maths around some two type casts or something. If you want to take a look at my testing code, feel free (NB: I know this is ugly, but it does the job of testing it):
Anyway, feel free to try and break it (while staying within the struct range). And StartTimerStruct needs a new name, but I don't know what. |
| 07-07-2008, 01:21 PM | #2 |
AWESOME!!!!11!!! ![]() |
| 07-07-2008, 01:29 PM | #3 |
I am always amazed at the possibilities of human imagination. |
| 07-07-2008, 02:44 PM | #4 |
JASS://========================================================================================== // TimerUserData by DiscipleOfLife (works with timeouts ranging from 0 to 0.1) //========================================================================================== function TimerStartWithUserData takes timer t, real timeout, integer data, boolean periodic, code handlerFunc returns nothing call TimerStart(t, timeout+(data)/67108871., periodic, handlerFunc) endfunction function GetTimerUserData takes timer t, real timeout returns integer return R2I((TimerGetTimeout(t)-timeout)*67108871.) endfunction // (by changing the value 67108871 (2^26) you can change the timeout limit this TimerUserData sys has, for example 2^23 for a 1 sec limit, 2^22 for a 2 sec limit,...) This is almost a year old idea. First public appearance can be found here as far as I know. HINDY used the same idea in some version of SEE too. That typecast thing you do with this is actually new though. |
| 07-07-2008, 02:55 PM | #5 | |
Quote:
Older than a year old. I had the idea way back but never actually released or used it due to it not being safe enough outside specific usage. Typecasting allows for the best possible values for a very small cost. |
| 07-07-2008, 04:14 PM | #6 | |
Quote:
|
| 07-07-2008, 04:22 PM | #7 |
Vex, that code uses a very different method to TimerAttach. When I was investigating timers way back when I thought up the TimerAttach method (start, pause, start; inspired from the pause trick on units), I experimented with the editing values method, but I don't think I ever went public with it (since it didn't work well enough to be reliable without far too much requirement on sensible use). So they didn't copy it, probably just came up with it independantly (after me, but actually used it, but I'm fairly sure people had thought of it before me as well). TimerAttach doesn't break, unless you go to like 10 digits on the attached integer, and is perfectly accurate, but only works with non-periodics. The method used in TimerStartWithUserData is either unreliable or adjusts the timer by a significant amount. StartTimerStruct (needs a new name that isn't a blatant lie) improves significantly upon both methods. |
| 07-07-2008, 05:32 PM | #8 |
Well this is all pointless in the long run since attaching to timers is pointless per se. |
| 07-07-2008, 05:42 PM | #9 |
As much as people keep saying that, I always manage to find a few applications where attaching to timers is the preferred method. |
| 07-07-2008, 06:16 PM | #10 | |
Quote:
Please do enlighten us. |
| 07-07-2008, 08:23 PM | #11 | |
Quote:
now we know 100500 ways to attach something to timers awesome... // in fact it doesnt matter but gj. |
| 07-07-2008, 10:26 PM | #12 |
ABCT + TT = no attaching. (no code inside libraries does not count, only what user sees.) |
| 07-07-2008, 10:27 PM | #13 | |
Quote:
That makes no sense. Even if it is in a library, it's still attaching. |
| 07-08-2008, 12:49 AM | #14 | |
Quote:
That is the same reasoning Assembler programmers used when they were introduced with C and we know how that ended up... |
| 07-08-2008, 08:00 AM | #15 | |
Quote:
Except we're still coding both sides of it. |
