Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Reliability of Sleep() in C++

Status
Not open for further replies.

Klen

Member level 1
Joined
Nov 15, 2010
Messages
36
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Location
Germany
Activity points
1,602
Hi,

I recently encountered some problem with the Sleep () in C++ ( from the windows.h header file). As per as my knowledge, Sleep ( x ) halts the program for "atleast" x miliseconds, but it could be more. As such, I know its not a good idea to use Sleep() for timing problems.

Now, I have generated a signal from a FTDI module, which has a period of 1 second, with 20ms high time, and 980ms fall time. Using some FTDI driver functions, I seemingly am able to do so. However, I wanted to check if my program actually works as expected or no, and thus I substitued the part of the code responsible for causing a 20ms delay, with Sleep(20). If my program is correct, Sleep(20) should not change anything in the program. But it did. Using GetTickCount (), I tried to see how much delay is the Sleep(20) causing, and surprisingly, it always causes a 16ms delay :shock: . This is quite interesting for me, as I always thought that
1. Sleep(20) means a delay of 20ms or more...but not less than 20
2. Sleep(x) never causes a delay of x+c such that c = constant.

Could anyone please shed some light on this behaviour of Sleep()! :?:

Thanks

PS: Sorry for the huge question, when it could have easily been put in 2 lines. I just wanted to be as detailed as possible :smile:
 

Yes, Sleep(n) cannot be used to produce exact pauses. Sleep() just tells task scheduler that it can suspend thread calling Sleep() (i.e. do not give it CPU time) for (approximately!) specified amount of time. If you need more or less strict time management (considering Windows is not a real-time OS), I'd suggest using WaitableTimer (see WaitableTimer API in MSDN). An outline of a thread with (more or less) strict timing can be the following:


Code C++ - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
DWORD WaitableTimerThread(LPVOID lParam)
{
    HANDLE hTimer;
    LARGE_INTEGER timerPeriod;
        // increase timer resolution
    timeBeginPeriod(1); // This increases standard Windows timer resolution (which is used for task scheduling) from approx. 10ms to approx. 1ms (depending on Windows version and hardware)
    // create WaitableTimer object...
    hTimer = CreateWaitableTimer(NULL, FALSE, _T("MyWaitableTimer"));
    if (!hTimer)
    {
        // report some error...
        // _tprintf(_T("Cannot create waitable timer: error code 0x%X\n"),GetLastError());
        return;
    }
        // we want to create a WaitableTimer, that will be called every timer tick (i.e. ~1ms) (it is almost guaranteed if this thread priority is THREAD_PRIORITY_TIME_CRITICAL)
        // for this we set up a timer with a period at least twice less than required.
    timerPeriod.QuadPart=-4000; // 0.4 ms = 4000 * 100ns, relative ("-") (see WinAPI)
    if (!SetWaitableTimer(hTimer, &timerPeriod, 1, NULL, NULL, FALSE))
    {
        UINT _err=GetLastError();
        // report an error
        // _tprintf(_T("SetWaitableTimer failed: 0x%X\n"),_err);
        // CloseHandle(hTimer); // I don't know if hTimer should be closed here
        return;
    }
    while (!StopThisThread) // some external variable to tell this thread to exit. Otherwise we can use hEvent and WaitForMultipleObjects
    {
        if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0) // Wait for WaitableTimer 
        {
            // report error and, maybe, perform exit (or use Sleep() instead)
            // _tprintf(_T("WaitForSingleObject failed (%d)\n"), GetLastError());
            // Sleep(1);
        }
        // Report to other (working) thread that it can do something (check hardware, etc.)
        // SetEvent(SomeExtEvent); // Other (processing) thread can use WaitForSingleObject(SomeExtEvent, INFINITE) != WAIT_OBJECT_0)
        // OR we can perform some actions right here, if we are sure that these actions will not last too long
        // QuicklyCheckHardware();
        // ...
        // restarting timer (it is not auto-restartable)
        if (!SetWaitableTimer(hTimer, &timerPeriod, 0, NULL, NULL, FALSE))
        {
            // report error, if necessary
        }
    }
        // preparing to exit from here...
    CancelWaitableTimer(hTimer);
    CloseHandle(hTimer);
    hTimer=NULL;    // it is not necessary actually
    timeEndPeriod(1);   // return to usual timer resolution.
}
 
// somewhere this thread can be created by something like
// AfxBeginThread((AFX_THREADPROC)WaitableTimerThread, NULL, THREAD_PRIORITY_TIME_CRITICAL);



I used such a procedure in some projects which work with hardware (in polling mode), and found that (in case of such a thread is created with a THREAD_PRIORITY_TIME_CRITICAL priority) actual period was 970us (approx. 1024Hz) on Windows XP (on different CPUs, including signle-core and dual-core/hyperthreaded), and 1000us (1000Hz) on Windows 7 (on Intel Core i3).
Note: beware of setting THREAD_PRIORITY_TIME_CRITICAL priority to a thread that does some processing or other 'long' things - this can cause to system instability!

PS There're also HPETs (High-Precision Event Timers), Windows has support for starting from Vista, but I've never used them.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top