-
January 5th, 2009, 03:30 PM
#1
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?
-
January 5th, 2009, 03:37 PM
#2
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
-
January 5th, 2009, 03:41 PM
#3
Re: while loop w/ sleep(1) doesnt work
Originally Posted by acerunner316
...
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
-
January 5th, 2009, 03:50 PM
#4
Re: while loop w/ sleep(1) doesnt work
Originally Posted by Codeplug
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.
-
January 5th, 2009, 03:52 PM
#5
Re: while loop w/ sleep(1) doesnt work
Originally Posted by VictorN
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.
-
January 5th, 2009, 04:14 PM
#6
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
-
January 5th, 2009, 04:27 PM
#7
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.
-
January 5th, 2009, 04:30 PM
#8
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.
-
January 5th, 2009, 04:43 PM
#9
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
-
January 5th, 2009, 04:55 PM
#10
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.
-
January 5th, 2009, 05:09 PM
#11
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 "% 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
-
January 5th, 2009, 05:24 PM
#12
Re: while loop w/ sleep(1) doesnt work
Originally Posted by Codeplug
>> 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.
Originally Posted by Codeplug
>> 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.
Originally Posted by Codeplug
Is this code multi-threaded? Or are you handling the UI and device interaction all within one thread?
gg
it's single thread.
-
January 5th, 2009, 05:32 PM
#13
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.
-
January 5th, 2009, 10:27 PM
#14
Re: while loop w/ sleep(1) doesnt work
Originally Posted by acerunner316
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...
-
January 6th, 2009, 09:03 AM
#15
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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|