CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 33
  1. #1
    Join Date
    Dec 2006
    Posts
    60

    while loop w/ sleep(1) doesnt work

    I am writing a software that periodically checks for CAN messages through calls to the driver libraries. And I must perform actions depending on the CAN messages I see.

    At first I used a system timer and function call in response to the windows message WM_TIMER.
    (i.e. SetTimer(1,10,NULL) and OnTimer() function where the processing of the messages occur.)

    But that solution has proven to be too slow, and I need a faster loop. So I though to use a while loop with a sleep of 1ms so as not to lock up the cpu. However, I've read that the sleep interval can only be as low as 15ms, and anything below that will sleep for 15ms.

    How can I create a faster loop without using all cpu resources?

  2. #2
    Join Date
    Nov 2003
    Posts
    1,902

    Re: while loop w/ sleep(1) doesnt work

    The best option would be to not poll at all, but instead be notified when an event occurs. If that isn't an option, then you have to poll.

    Do you really need to poll the driver more than once every 15ms? Why?

    What "driver libraries" are you referring to?

    gg

  3. #3
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by acerunner316 View Post
    ...
    How can I create a faster loop without using all cpu resources?
    I don't know what you mean by "without using all cpu resources", however, you could try Multimedia Timer
    Victor Nijegorodov

  4. #4
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by Codeplug View Post
    The best option would be to not poll at all, but instead be notified when an event occurs. If that isn't an option, then you have to poll.

    Do you really need to poll the driver more than once every 15ms? Why?

    What "driver libraries" are you referring to?

    gg
    I am using Kvaser and vectorCAN, which requires polling.

    And yes I do need a loop thats faster than 15ms. I am implementing a communication algorithm with handshaking. So i send a command, get its response, and send next command, get another response. All of this must occure sequentially. The response is much much faster than the polling on the PC side, so the PC side is my weakest link in the speed of this procedure. At the speed that I am polling and sending commands now, I am only using 4% of the CAN bus load, and I have plenty of space to put more messages on the bus. I just don't know how to speed it up on the PC side.

  5. #5
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by VictorN View Post
    I don't know what you mean by "without using all cpu resources", however, you could try Multimedia Timer
    what I mean is that I can't use ONLY a while loop without a pause inside of it. It is my understanding that that will comsume all cpu time.

  6. #6
    Join Date
    Nov 2003
    Posts
    1,902

    Re: while loop w/ sleep(1) doesnt work

    So I see the Kvaser products can be used with their CANlib SDK. Is that what you're using?

    Are their blocking API's you can use - instead of polling?

    gg

  7. #7
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    yes I am using the CANlib SDK. That is the only solution kvaser provides to communicate with their devices. I am not sure what you mean by "blocking API".

    In CANlib, the function to get a message is canRead.
    Code:
    canStatus canRead(
        int handle, long* id, 
        void* msg, unsigned int* dlc, 
        unsigned int* flag, DWORD* time);
    This is the function I want to call every 1ms, which retreives messages in the device's receive buffer.

  8. #8
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: while loop w/ sleep(1) doesnt work

    The key to avoiding the "15ms" thing is to *not* make any call which would cause the OS to timeslice over to other running processes (or even check for them). In other words, you need a pause() function which remains strictly in user mode for the duration rather than entering kernel mode. Unfortunately, I'm not aware of a standard function which does this; the suggestion above to use blocking functions (possibly with timeouts if you need to detect failure) is probably the best.

    EDIT: A quick Google later, I found this:
    http://www.kvaser.com/index.htm

    Looks like canReadWait() is what you want.

  9. #9
    Join Date
    Nov 2003
    Posts
    1,902

    Re: while loop w/ sleep(1) doesnt work

    Looks like canReadWait() is the blocking version. This would be much better than polling.

    canReadSync() and canReadSyncSpecific() also look useful.

    gg

  10. #10
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    i know about the canReadWait() function for kvaser. However, my app must also work with a few other CAN adapters that are user selectable. The APIs for these other devices do not have an equivalent function, so i have to write something in my app to do it.

    If by blocking function, you mean something like this:
    Code:
    void pauseforcount(int count)
    {
    int i=0;
    while (i<count)
     i++;
    }
    does the cpu freeze up during this loop?
    my sequence of cmd and response can take several minutes, and I don't want the CPU to hang on my app.

  11. #11
    Join Date
    Nov 2003
    Posts
    1,902

    Re: while loop w/ sleep(1) doesnt work

    >> If by blocking function...
    In this context, "blocking" means that the current thread is "blocked" or waiting efficiently within the OS. Meaning, the call does not return from the OS until some condition is met. For example, Sleep() is a blocking call which blocks for at least the amount of time given. If your code is spinning in a loop, that's called a "busy wait". This will count against you in the "&#37; CPU Usage" column of task manager.

    >> my sequence of cmd and response can take several minutes
    Then why not just poll once a second? I see no need for polling the data any faster. And if you are willing to call Sleep(), then just call canReadWait() with a 1 second timeout. Then if data is available it will return immediately. If not, the call will block for up to 1 second.

    Is this code multi-threaded? Or are you handling the UI and device interaction all within one thread?

    gg

  12. #12
    Join Date
    Dec 2006
    Posts
    60

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by Codeplug View Post
    >> If by blocking function...
    In this context, "blocking" means that the current thread is "blocked" or waiting efficiently within the OS. Meaning, the call does not return from the OS until some condition is met. For example, Sleep() is a blocking call which blocks for at least the amount of time given. If your code is spinning in a loop, that's called a "busy wait". This will count against you in the "% CPU Usage" column of task manager.
    Thanks for providing the correct terminology. Yes, I want to avoid a busy wait at all costs.


    Quote Originally Posted by Codeplug View Post
    >> my sequence of cmd and response can take several minutes
    Then why not just poll once a second? I see no need for polling the data any faster. And if you are willing to call Sleep(), then just call canReadWait() with a 1 second timeout. Then if data is available it will return immediately. If not, the call will block for up to 1 second.
    what I mean is that there are so many cmd & response pairs of CAN messages that all of them in sequence can take several minutes. For example, I have 1000 cmds to send, each waiting for a response before sending the next command. Polling every 1 second will require at least 1000 seconds to complete the entire sequence of 1000 cmds. Polling every 1ms, however, dramatically reduces this time to 1 sec, which is what I'm trying to do.

    Quote Originally Posted by Codeplug View Post
    Is this code multi-threaded? Or are you handling the UI and device interaction all within one thread?

    gg
    it's single thread.

  13. #13
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: while loop w/ sleep(1) doesnt work

    Well, canReadWait() seems like exactly the right thing then. It will return immediately if a message is waiting, *or* wait up to the specified amount of time if one is not. You'd have to give us more details about these other APIs you're working with before we could get more specific.

  14. #14
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: while loop w/ sleep(1) doesnt work

    Quote Originally Posted by acerunner316 View Post
    Yes, I want to avoid a busy wait at all costs.
    ...
    Polling every 1ms, however, dramatically reduces this time to 1 sec, which is what I'm trying to do.
    Do you have more than one CPU/core? The strategy depends on that.
    Also, the “busy wait” is only wrong if you are counting crows in your loop. If you have something like that:
    Code:
    while(!canRead())
        ;
    it’s more like extreme readiness.
    In any case, you should NEVER have lengthy processing on the same thread as your UI.
    I would run that polling function (or the blocking canReadWait() function, if it exists) on the separate thread, and wait for it using MsgWaitForMultipleObjects() so that your UI is responsive.
    Now, what do you need a sleep timer for? Even a high-precision one? That high-precision timer works pretty much like a busy loop. No better but less performing than my loop above.
    If you want to achieve maximum throughput, I would suggest raising your thread’s priority.
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  15. #15
    Join Date
    Nov 2003
    Posts
    1,902

    Re: while loop w/ sleep(1) doesnt work

    >> Polling every 1 second will require at least 1000 seconds to complete
    Yes - if you only try to read something once a second. But if you use canReadWait() with a timeout, then the function will return as soon as there is data available or if a timeout occurs.

    Typically, when dealing with a message-response type protocol, there is a "time window" in which a response is expected. If a response isn't received within that window, then you assume "communications error". You will have to decide at what point does a lack of a response indicate an error.

    How long does it typically take to receive a response?
    At what point does a lack of response indicate "communication error"?

    >> it's single thread.
    If you're not familiar with it, making it multi-threaded may add more complications than you care to deal with right now. But without it, you'll need to find a way to keep the UI responsive while handling CAN communications.

    The single threaded approach wouldn't be too hard if, for example, you had a modal dialog with a cancel button and some sort of progress indicator. You would then use a special message loop just for this modal dialog. This special message loop would periodically pump messages while handling CAN message/response pairs.

    gg

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured