|
Joined: Aug 2006
Posts: 183
Vogon poet
|
OP
Vogon poet
Joined: Aug 2006
Posts: 183 |
Hello, The timer function doesn't seem to always keep track of what order timers were called. In this code... alias timet {
var %j -1
while %j < 3 {
.timer 1 %j echo -a %j
inc %j
}
} ...one would expect the output to be -1, 0, 1 then 2. However, it always gives the output in this order: 0, -1, 1, 2. Now, I understand that giving /timer a negative number might throw an exception, so I tested that as well using the following code. alias timet {
var %j -1
while %j < 3 {
if %j < 0 { var %k 0 }
else { var %k = %j }
.timer 1 %k echo -a %j -- %k
inc %j
}
} It still produces the same erroneous output. However, if one uses the -h switch the problem seems to vanish. I can't imagine this is intended behavior, though.
Yar
|
|
|
|
Joined: Oct 2003
Posts: 3,918
Hoopy frood
|
Hoopy frood
Joined: Oct 2003
Posts: 3,918 |
It is. Timers trigger in the order that the Windows API decides they do. The -h switch (highres) makes Windows API think more carefully about order, which matters when the timers are all triggered within the same millisecond (usually the case for a while loop).
In short, it's out of mIRC's hands (mIRC is likely even issuing the timer commands in the correct order). If you care about timer order, you want a highres timer.
- argv[0] on EFnet #mIRC - "Life is a pointer to an integer without a cast"
|
|
|
|
Joined: Dec 2002
Posts: 2,033
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 2,033 |
Try using the -d switch. From versions.txt28/07/2006 - mIRC v6.2
Changes: .. 25. Added /timer -d switch, ensures that a timer and any subsequent timers using the -d switch are triggered in that order.
Last edited by RoCk; 05/01/10 03:21 PM.
|
|
|
|
Joined: Nov 2006
Posts: 1,559
Hoopy frood
|
Hoopy frood
Joined: Nov 2006
Posts: 1,559 |
A negative delay put aside,I never got the d-switch working for that. E.g.: //.timer -d 1 0 echo -a 1 | .timer -d 1 0 echo -a 2 | .timer -d 1 0 echo -a 3 sometimes resulted in "1 2 3" but most times in "2 1 3" on my machine... I thus did: ; /timertest [h|d]
alias timertest {
var %a = 1, %b = 1, %s = $left($1,1)
echo -ag * starting 8 timers (4x 0s, 4x 1s) with $iif((%s isin hd),the $v1,no) switch...
while (%a <= 4) {
.timer $iif((%s isin hd),- $+ $v1) 1 0 echo -ag delay 0 : $ord(%a)
inc %a
}
while (%b <= 4) {
.timer $iif((%s isin hd),- $+ $v1) 1 $iif((%s == h),1000,1) echo -ag delay 1 : $ord(%b)
inc %b
}
} /timertest * starting 8 timers (4x 0s, 4x 1s) with no switch... delay 0 : 4th delay 0 : 3rd delay 0 : 2nd delay 0 : 1st delay 1 : 1st delay 1 : 2nd delay 1 : 3rd delay 1 : 4th /timertest d * starting 8 timers (4x 0s, 4x 1s) with the d switch... delay 0 : 4th delay 0 : 3rd delay 0 : 2nd delay 0 : 1st delay 1 : 1st delay 1 : 2nd delay 1 : 3rd delay 1 : 4th /timertest h * starting 8 timers (4x 0s, 4x 1s) with the h switch... delay 0 : 1st delay 0 : 2nd delay 0 : 3rd delay 0 : 4th delay 1 : 1st delay 1 : 2nd delay 1 : 3rd delay 1 : 4th Now I wonder what -d is made for... I tested as well with named timers and/or timers that will fire at a certain [time] value... alias timertest2 {
var %s = $iif(($1 == d),-d), %t = $asctime($calc($ctime +60),HH:nn)
echo -ag * starting 6 timers $iif(%s,with the $v1 switch) (3 fire at %t $+ :00, 3 fire at %t $+ :01)...
.timerB %s %t 1 0 echo -ag 1st
.timerA %s %t 1 0 echo -ag 2nd
.timerC %s %t 1 0 echo -ag 3rd
.timerZ %s %t 1 1 echo -ag 1st
.timerX %s %t 1 1 echo -ag 2nd
.timerY %s %t 1 1 echo -ag 3rd
} /timertest2 * starting 6 timers (3 fire at 17:10:00, 3 fire at 17:10:01)... 3rd 2nd 1st 2nd 3rd 1st /timertest2 d * starting 6 timers with the -d switch (3 fire at 17:11:00, 3 fire at 17:11:01)... 3rd 2nd 1st 2nd 3rd 1st Edit: the -d switch is taken into account in the list of timers (/timer). I don't see any effect beyond that though.
Last edited by Horstl; 05/01/10 04:22 PM.
|
|
|
|
Joined: Dec 2002
Posts: 2,033
Hoopy frood
|
Hoopy frood
Joined: Dec 2002
Posts: 2,033 |
I got 2 1 3 everytime as well, until I removed the silencers in your test and the outputs changed to 2 3 1 everytime. Strange.
|
|
|
|
Joined: Aug 2006
Posts: 183
Vogon poet
|
OP
Vogon poet
Joined: Aug 2006
Posts: 183 |
I had tried the -d switch as well, but it didn't work any better for me.
Yar
|
|
|
|
Joined: Jan 2010
Posts: 11
Pikka bird
|
Pikka bird
Joined: Jan 2010
Posts: 11 |
argv0 was on the right track about the API. Event driven multi-tasking environments give processes priorities. Addressing an API timer event as high priority will yield more expected results with the cost of processing speed.
On a side note Thrull, on my machine with Win 7, your code without the -h worked fine every time. All numbers in order.
|
|
|
|
Joined: Aug 2006
Posts: 183
Vogon poet
|
OP
Vogon poet
Joined: Aug 2006
Posts: 183 |
Well, I'm not going to get Win7 to solve the issue. Even if Argv0 is correct about the API issue (and I don't doubt he is), it'd be nice if the timers all functioned the same way on all version of Windows. Perhaps it really can't be done, I don't know enough about Windows API and the internals of Mirc.
Yar
|
|
|
|
Joined: Aug 2004
Posts: 7,252
Hoopy frood
|
Hoopy frood
Joined: Aug 2004
Posts: 7,252 |
Regretfully, timers are not 100% accurate. regular timers, which are set to the second can (and do) actually trigger with up to a 1 second variance.
This can be reduced by using a millisecond timer.
I seem to recall this situation being reported earlier, but I don't recall when... Sorry.
Thus an intermediate solution maybe to use the -m with or without the c switch, which will keep the timer even more accurate.
|
|
|
|
Joined: Jan 2010
Posts: 11
Pikka bird
|
Pikka bird
Joined: Jan 2010
Posts: 11 |
I choose to write recursive routines using timers instead. (Even though it is bad mIRC mojo). But that's just me.
alias testt {
var %i $1
if (%i > 3) { halt }
echo -a Timer iteration: %i
inc %i
.timer -m 1 1 testt %i
}
|
|
|
|
Joined: Aug 2004
Posts: 7,252
Hoopy frood
|
Hoopy frood
Joined: Aug 2004
Posts: 7,252 |
As someone said to me once : "If it ain't broke, don't fix it"
|
|
|
|
Joined: Jan 2010
Posts: 4
Self-satisified door
|
Self-satisified door
Joined: Jan 2010
Posts: 4 |
i know in some programming languages when you want to order numbers it will order them in a similar matter as to what you've shown here or for another example this sequence of numbers 0,1,2,3,10,11,22,23,34,35 would be ordered as 0,1,10,11,2,22,23,3,34,35 in mySQL this problem occurs when you are assigning the numbers as asc, or chr values instead of int's I know you cant really control how mIRC stores the data in this case but im thinking this could be what's causing this issue as the pattern you've displayed seems to be ordered in a similar fashion if you see what im getting at. I dont know if this will help you directly but perhaps if this is the same issue in mIRC in a future version they can through in a flag to indicate your timer name is an integer and not of type char. Hope this might shed some light.
|
|
|
|
Joined: Oct 2003
Posts: 3,918
Hoopy frood
|
Hoopy frood
Joined: Oct 2003
Posts: 3,918 |
@ Thrull: You don't have to "believe" me, you just need to read the Timers API: The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue. http://msdn.microsoft.com/en-us/library/ms644902%28VS.85%29.aspx This means things like keyboard events, mouse events and probably many others can all make a timer run slow. And yes, /timer *is* implemented via WM_TIMER. But more pertinent: timers do function the same on all versions of windows. The problem here is that your expectation is not reasonable. /timer is neither expected to trigger in order (-d triggers them in order on mIRC's end, not Windows') nor give you "exact" timings. It's well known that a "1 second" timer will never trigger in exactly 1000ms. In fact, the actual timing could be anywhere from 500ms to 1500ms, given "bug reports" of the past (they weren't actually bugs, of course). With this fact in mind, it's conceivable that 3 timers could easily trigger out of order (timer1 triggers in 1500ms but the others trigger in ~900ms). This is how the Windows API works, and pretty much how any sort of multi-threaded environment (or emulation thereof) will be expected to function. In fact, even the Windows API docs tell you that pretty much nothing is accurate to 1ms by default (it's more like 15ms). That means that if you need to do time-sensitive work, you need to tell the OS; this is what -h is for. Otherwise your timers are approximations and should not be time sensitive. The fact that on Win7 the numbers order up is irrelevant. You should not be expecting any order without -h.
- argv[0] on EFnet #mIRC - "Life is a pointer to an integer without a cast"
|
|
|
|
Joined: Aug 2006
Posts: 183
Vogon poet
|
OP
Vogon poet
Joined: Aug 2006
Posts: 183 |
Point taken. My only gripe is that the script had been working perfectly for months and all the sudden started to not work properly. I tracked down the source and found it to be this problem. If it was something that could be easily fixed, then a bug report was worth the time. If not, then I already have a solution and it isn't that big of a deal. The fact that on Win7 the numbers order up is irrelevant. You should not be expecting any order without -h. Well, given that it worked fine for months, and I saw no reason it shouldn't suddenly stop working probably, my expectations were fair. And given the amount of bug reports that have been posted on it (or similar things involving /timer) Khlaed may well want to add a bit more in the help file to explain away some of the misconceptions.
Yar
|
|
|
|
|