Versions of SLEEP

Started by MrBcx, April 25, 2025, 09:49:20 AM

Previous topic - Next topic

MrBcx

With the first version of BCX_SLEEP(), while playing Asteroids, my desktop clock widget flickers.

Not so with version two of BCX_SLEEP().

Quin

Very cool, thanks for sharing! I knew about timeBeginPeriod and timeEndPeriod, in fact I use them in my MicState application whenever the user presses the hotkey so the sleep is actually only about 50 MS. I don't bother using arguments for mine though, just call timeBeginPeriod(); and timeEndPeriod();.
What have you noticed this screwing up? I ask because in my app I do it only for as long as  needed, but an audiogame engine I work on does this at the start of its AngelScript registration and I wonder if it could actually screw something up?

MrBcx

On a good day, BCX's built in SLEEP() function is accurate to about 16 milliseconds.

Here is a version that I used in my Asteroids game that's accurate to about 1 millisecond:
It's good but it can sometimes affect other system timers resulting in stutters or flickers.


SUB BCX_SLEEP ( x AS INTEGER )
   '******************************************
   ' Gives precision to about 1 millisecond
   '******************************************
   DIM RAW tc AS TIMECAPS
   timeGetDevCaps(&tc, SIZEOF(TIMECAPS))
   timeBeginPeriod(tc.wPeriodMin)
   SLEEP(x)
   timeEndPeriod(tc.wPeriodMin)
END SUB


Here is my new favorite version that's good to about 100 nano-seconds
but I still have it setup to accept only milliseconds argument. It has lower
impacts on the system and could be extended to accept sub-millisecond
arguments but I will leave that to others, as I have no need for that.



SUB BCX_SLEEP (Milliseconds AS INTEGER)
    '***************************************************
    ' Intervals are precise to approx 100 nano-seconds
    ' BCX_SLEEP(0) resets this timer
    ' Only use this when you need short, high precision
    ' intervals (1 to  15 milliseconds) otherwise just
    ' use BCX's normal SLEEP() command
    '***************************************************
    STATIC hTimer AS HANDLE
    DIM liDueTime AS LARGE_INTEGER
    DIM success AS INT

    ' If called with 0, close and reset the timer handle
    IF Milliseconds = 0 THEN
        IF hTimer THEN
            CloseHandle(hTimer)
            hTimer = NULL
        END IF
        EXIT SUB
    END IF

    ' Initialize timer if not already created
    IF hTimer = NULL THEN
        hTimer = CreateWaitableTimer(NULL, TRUE, NULL)
        IF hTimer = NULL THEN EXIT SUB
    END IF

    ' Convert ms to 100ns intervals (negative = relative time)
    liDueTime.QuadPart = -1 * Milliseconds * 10000

    success = SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, FALSE)
    IF success THEN
        WaitForSingleObject(hTimer, INFINITE)
    END IF
END SUB