hmmmm,


QvasiModo, no thanks - hutch can take it elsewhere if he wants to


Perhaps you should learn not to attempt reverse attribution on an argument that you are trying to start. Try and keep your responses technical and forget starting arguments, you are not very good at it.


and that Sleep(1) certeinly WON'T return in 1ms because of the granularity.


This is incorrect, SleepEx() like any other periodic function is effected by the timeslice duration set by the OS so when it yields, the thread does not get another look until it gets another time slice. SetTimer is little better at small intervals and if you really need higher precision, you use a multimedia timer that is designed for fast frame rates and similar applications.


I would have opted for WM_TIMER style notification instead though, to avoid the overhead of an additional thread.


SetTimer() by necessity must be in a seperate thread to the calling app otherwise the app would lock up between intervals. Its the same old rule, you get nothing for nothing and any functionality you use has an overhead.

Regards,

hutch at movsd dot com
Posted on 2005-09-30 22:24:04 by hutch--

This is incorrect, SleepEx() like any other periodic function is effected by the timeslice duration set by the OS so when it yields, the thread does not get another look until it gets another time slice.

...and you won't get 1ms granularity, since the default timeslice duration is like 12ms or whatever. At any rate, Sleep can only really guarantee that you'll sleep for at least that duration, so it's not suited for "Sleep(1)  + inc " - which is what matters in this context.


SetTimer() by necessity must be in a seperate thread to the calling app otherwise the app would lock up between intervals. Its the same old rule, you get nothing for nothing and any functionality you use has an overhead.

Afaik, it is handled by the scheduler in an already-existing thread... so no, SetTimer isn't free, but it's somewhat less overhead than creating a new thread to do this work. Multimedia timers etc. is a bit silly in the context of what Lenin is trying to do.

I've attached a .zip that shows a decent way of doing all this. This one should be accurate (as accurate as timeGetTime anyway), no matter what time interval you use for updates.
Attachments:
Posted on 2005-09-30 23:03:40 by f0dder
I have no problem USING API's but actually using them for a timer that you want to be relatively accurate Meh anyways.

GetTickCount is great, but you have to call it and then IT has to return, it's craziness.
Those queryblahblah counter/freq or gettime blah blah apis (decompile kernel32 they have a ton of useless crap in them).

WhyIDontKnow:;;crazy thread proc ; = tickstart
  PUSH EBX
  PUSH ESI
  PUSH EDI
  MOV ECX,
  ADD ECX,1
  MOV EBX, ; get the sweet sweet magic memory address
.Counter:
  MOV EAX,
  MOV EDX,
  MUL EDX
  SHRD EAX,EDX,24 ;get the tick count
  XOR EDX,EDX
  SUB EAX,
  DIV 60000
  MOV ESI,EAX ;;;;;;;;;;;;;;;;;minutes
  MOV EAX,EDX
  XOR EDX,EDX
  DIV 1000
  MOV EDI,EAX ;;;;;;;;;;;;;;;;;seconds
  MOV EAX,EDX
  MOV EDX, 3435973837
  MUL EDX
  SHR EDX,3 ;;;;;;;;;;;;;;;;;;;;;;centi seconds
  ;;;;;;;;;;;;;ESI:EDI:EDX Min:Sec:Cen
  ;;;;;;;;;;;;;put them in dialogue box code or what not
  ;;;;;;;;;;;;;IF some out of thread global memory address says reset then reset
  MOV EAX, dword
  TEST EAX,EAX
  JZ .Counter
  MOV ,0
  MOV EAX,
  MOV EDX,
  MUL EDX
  SHRD EAX,EDX,24
  MOV ,EAX
  JMP .Counter
  POP EDI
  POP ESI
  POP EBX
  RET NeverMuhahahahahahahahahahaha

I have no clue if the above code works or not or what it does.
Just bored.
Posted on 2005-10-01 00:26:34 by r22
hehe, r22... the time to call+ret from GetTickCount amounts to, what, some nanoseconds? hardly an overhead problem there. And depending on how the implementation of GetTickCount looks is pretty bad.

But the code looks like fun.
Posted on 2005-10-01 00:37:45 by f0dder
hmmmm,


...and you won't get 1ms granularity, since the default timeslice duration is like 12ms or whatever. At any rate, Sleep can only really guarantee that you'll sleep for at least that duration, so it's not suited for "Sleep(1)  + inc " - which is what matters in this context.


Nothing gets 1 millisecond so its an inappropriate comment at best. The SleepEx() API will do just what it is documented to do, with a duration greater than 0 it yields to the OS until its duration has elapsed AND the next timeslice is available. Now what can effect it is two seperate things, if the duration is down close to the timeslice duration AND the procesor usage is high with other tasks of higher priority, it runs the risk of missing a timeslice which effects the next time the message is received when the next timeslice is available. It requires a reasonably high rate per second to do this, 50 per second is 20 ms duration and its rare that you need much finer unless you are doing multimedia work.

The advantages of putting SleepEx() in a seperate thread is it can be adjusted on the fly with PostThreadMessage() if you set up a message que in the thread so you can change the duration, the thread priority and remotely close it down and by using te SleepEx() API you can run the thread at a high priority as SleepEx() unconditionally yields anyway.

I have made the comment before, if you need genuine high precision with a timer you use a multimedia timer as it is designed for intervals smaller than can be delivered with a normal timer.

Regards,

hutch at movsd dot com
Posted on 2005-10-01 05:22:44 by hutch--

I'm looking forward to my place in the top 20 posters being boosted by 2 places soon :))

Hey Spook, look here!
Posted on 2005-10-01 06:08:27 by japheth
What hutch proposes here is "kludge programming"; using one inappropriate function leads to another, and soon there is a total mess. Why not just Do It Right? You want a timer - use a timer facility.
Posted on 2005-10-01 06:49:41 by death
hutch, he's designing a stopwatch timer, not a spaceshuttle control program :)

So, super-duper-save-the-world high precision isn't necessary. Other code than the original approach is necessary, though, since it increments a milisecond counter, which assumes that Sleep() can gives 1ms accuracy - which it can't.

Try looking at the context of the problem. Doing a polling loop with high-precision timers would certainly give very good precision, but it's entirely overkill and CPU wasting for a simple stockwatch.

I'll post the timer.zip again so it doesn't drown in all this nonsense :). The idea of it is to get the time duration from an external and reliable source, rather than trying to manage it yourself, which would require more work than a "inc miliseconds + Sleep(1)" loop.

Attachments:
Posted on 2005-10-01 06:52:06 by f0dder
Lets face it, anything pulled through ring3 is not going to be all that accurate, task switching, OS priority and the like will reduce the precision by at least some amount. Now if you could manage a ring3 application to upgrade a display every millisecond which of course it cannot, you would come close to locking up the machine because while it is 0.1% in terms of duration, bashing anything 1000 times a second on a computer is expensive. Now your logic of obtaining the source externally does make sense if the resolution is fine enough but I seriousl doubt that anything can work in a task switching OS at 1 millisecond resolution as the timeslice is considerably longer.

Now the following piece of wit deserves a comment.


What hutch proposes here is "kludge programming"; using one inappropriate function leads to another, and soon there is a total mess. Why not just Do It Right? You want a timer - use a timer facility.


So Death considers a multimedia timer "kludge programming" ? He should write a letter to Bill Gates telling him of this piece of wisdom and how Microsoft should be listening to such pearls of wisdom from IRC instead of just producing high resolution timers that do the job well. Its evident that such a talent is wasted on IRC when Microsoft need to hear such pearls of wisdom.

Death is the END of life.

Regards,

hutch at movsd dot com
Posted on 2005-10-01 08:17:46 by hutch--

I've attached a .zip that shows a decent way of doing all this. This one should be accurate (as accurate as timeGetTime anyway), no matter what time interval you use for updates.


Your solution might be beautifull and accurate, but it has a major (sp?) problem, try starting the timer, stoping it, and starting it again, see how the timer gets reseted. Not depending on an API to get you the time has its advantages after all  ;).

By the way I just realised that I was waiting/sleeping the wrong amount of time... It should be 10 instead of 1 since Im working with centisecond, not miliseconds.

I was looking into the multimedia timer API (timeBeginPeriod, timeEndPeriod, timeSetEvent, timeKillEvent) but got a little confused since there are no examples in that page, if anyone has some code that uses them please post.
Posted on 2005-10-01 09:47:38 by Lenin

try starting the timer, stoping it, and starting it again, see how the timer gets reseted

Do you want it to resume from where you stopped it instead? That will take some additional logic, but is still doable with this kind of logic. I'll try reworking it a bit later today.
Posted on 2005-10-01 11:28:12 by f0dder

So Death considers a multimedia timer "kludge programming" ?


I was actually referring to your SleepEx()/priority solution. I thought it was obvious (see my last sentence), but apparently it was not. The rest of your "comment" isn't worth addressing.
Posted on 2005-10-01 12:04:42 by death
Here's an updated version. I've changed the GUI update interval as well - the beauty of doing it this way is you can change the interval without doing any other modifications to the source...
Attachments:
Posted on 2005-10-01 12:21:04 by f0dder
My solution is seriously the best one :D

1 - If it weren't for cruddy Bin2Ascii code I think my solution could probably update to the screen every millisecond. (Bin2Ascii could be replaced with LUTs because of the scope of the numbers). There are a few divs in the code WELL at least every 2 to 3 milliseconds which is pretty good for Ring3.

2 - Only output API is needed, so no calls or polling of Sleep or GetTickCount or QueryPerformance blah or SetTimer.

3 - It's just plan sexy, did anyone besides f0d actually look at the code?

4 - It's compatibility with non WinXP is questionable but who cares :]

5 - Every list should be a Prime Number long.

Because No One likes buggy example code the following is a tested working ThreadProc
I used console output ala to test it, it was able to output serveral times per MILLISECOND!!!!!!!!!
So you may have to tweak the thread priority to a slower setting.
Tested on a 3.2ghz P4

;;;;;;;;;;;;;;;;;;;;;;;;;;ResetThis and TickStart are global data
TimerThreadTest:;;crazy thread proc
  PUSH EBX
  PUSH ESI
  PUSH EDI
  MOV ECX,
  ADD ECX,1
  MOV EBX, ; get the sweet sweet magic memory address
;;;;;;;set TickStart
  MOV EAX,
  MOV EDX,
  MUL EDX
  SHRD EAX,EDX,24
  MOV dword,EAX
.Counter: ;;;;;;;;;;;;;;;;;;;not really a counter but a never ending Loop of coolness
  MOV EAX,
  MOV EDX,
  MUL EDX
  SHRD EAX,EDX,24 ;get the tick count
  XOR EDX,EDX
  MOV ECX,60000
  SUB EAX,
  DIV ECX
  MOV ESI,EAX ;;;;;;;;;;;;;;;;;minutes
  MOV ECX,1000
  MOV EAX,EDX
  XOR EDX,EDX
  DIV ECX
  MOV EDI,EAX ;;;;;;;;;;;;;;;;;seconds
  MOV EAX,EDX
  MOV EDX, 3435973837
  MUL EDX
  SHR EDX,3 ;;;;;;;;;;;;;;;;;;;;;;centi seconds
  ;;;;;;;;;;;;;ESI:EDI:EDX Min:Sec:Cen
  ;;;;;;;;;;;;;PUT DIALOGUE OUTPUT CODE HERE
  ;;;;;;;;;;;;;IF some out of thread global memory address says reset then reset
  MOV EAX, dword
  TEST EAX,EAX
  JZ .Counter
  MOV dword,0
  MOV EAX,
  MOV EDX,
  MUL EDX
  SHRD EAX,EDX,24
  MOV ,EAX
  JMP .Counter
  POP EDI
  POP ESI
  POP EBX
  RET 0

Posted on 2005-10-01 17:42:44 by r22



What hutch proposes here is "kludge programming"; using one inappropriate function leads to another, and soon there is a total mess. Why not just Do It Right? You want a timer - use a timer facility.


For someone who has more to say than he can deliver in terms of code, te following statement is just a continuation of previous nonsense stated in this thread.


I was actually referring to your SleepEx()/priority solution.


There are two ranges being discussed with periodic timers, low resolution that is extremely efficient in terms of processor usage and this is with functions like SetTimer(), SleepEx() and similar and high resolution timers for much smaler intervals which is well addressed with a multimedia timer that is designed at the OS level for exactly this task.

When someone wants to say "Why not just Do It Right?" there is the necessity to actually learn what the right way is and with high resolution timing intervals, a multimedia timer IS the right way to perform the task.

Now f0dder had the right idea when you are not using a high resolution timer and that was to obtain the duration at each iteration of the timer from an independent source within the OS and while it will suffer some wander at ring3, it will remain consistent and sequential at the 100th of a second precision level that Lenin requires.

I have bothered to coment as I have heard some unmitigated nonsense in this thread when it came to using the SleepEx() API which is simply an NTDLL.DLL call utilising an int 2Eh service call.

Regards,

hutch at movsd dot com

Posted on 2005-10-01 20:32:14 by hutch--
Hutch-- is absolutely right.

we talk about a Timer precision. we'll deal with two discrepancies that are the total discrepancy and the interval discrepancy. we care about the total discrepancy while we use a timer to observe the result of something. we care about the interval discrepancy while we use a timer to see the process of something.

the total discrepancy == ? the interval discrepancy 

attention:
the interval discrepancy sometimes is positive, another timers is negative; sometimes is bigger discrepancy,another timers is smaller discrepancy. This is relating to the environment of your quartz.
;======================================
so, using a software to implement a timer of the 100th of a second precision level is impossible. if you don't believe that, Please try as follow:
using your the Timer drive the 2 pin of com1 which is changing low voltage from high voltage at every 0.01s. and take your oscillograph to see what's happen.
Posted on 2005-10-01 22:23:10 by dcskm4200
OK all you Top Gun Pilots, you overshot the runway. The orignial problem was solved, he took a solution that works. What is the purpose of splitting hairs any further?
Posted on 2005-10-01 23:06:52 by SpooK
SpooK, because he appearantly needs realtime code suitable for controlling a nuclear plant? :)
Posted on 2005-10-01 23:14:53 by f0dder
Here is a link to a simple demo that shows how to use the real precsion of the SleepEx() API in conjunction with multimedia APIs and a spinlock to get accurate 100th of a second resolution.

http://www.masmforum.com/simple/index.php?topic=2872.0

Regards,

hutch at movsd dot com
Posted on 2005-10-02 04:16:53 by hutch--
Here is a Timer which created by Hutch--'s method + F0dder's method.
i doubt the Timer has the 100th of a second precision level, because every instruction need time to run, and the time depends on the logic condition.

what we use a Timer to do is important. if we use this (Hey,what's time is it?), the above Timer is a pretty solution. but if we use the Timer to find oil and water under the ground, to evaluate the stress of a architecture in a earthquake and a storm, to calc the (x,y,z) of a earthquake, ... the above Timer isn't a significative solution. because we need high precision timer to calculate some parameter.

we often use reading the hardware timer + GPS verify to do something of needing the high precision timer.
Attachments:
Posted on 2005-10-02 11:18:46 by dcskm4200