|
Hello !
Windows is not the best platform for time-critical applications. If you must use it, though, you could try increasing the priority of your application to maximum level. This ensures that the 40 ms (I assume milliseconds, here)timer is fired as close to 40 ms intervals as possible.
Increasing the priority of your application will cause other applications to lose theirs: increasing the accuracy of your application might/will cause inaccuracy/stiff response/high latency in other applications concurrently executing in the system. Pushing one application to real-time priority will most likely cause the operating system to appear 'locked up' while this single application is executing. The timer will reach as close to 40 ms intervals as possible, though. That's the price you'll have to pay.
When designing the real-time thread, you must make it as low-resource hog as possible.
For an example, create a thread, increase it's priority and call SetTimer Win32 API routine with a pointer to the function that should run at 40 ms intervals. Then put this thread into a forever loop that can be interrupted, if necessary. When interrupted, the timer should be killed and the thread terminated. Note that this will not cause the system to lock up, because the priority of the process itself has not been raised. You could use SetPriorityClass to pump up the process priority as well. Before doing this, familiarize yourself with Scheduling Priorities[^] in the MSDN or in Visual Studio documentation. Misusing thread or process priorities is a sure way to get your computer locked up easily.
To set max priority for your MFC application's main thread, use AfxGetApp() to get the CWinApp object pointer, and call CWinThread::SetThreadPriority() with a parameter THREAD_PRIORITY_TIME_CRITICAL through this pointer. CWinApp derives from CWinThread . MFC does not have a direct routine to pump up process priority. You'd need to use a mixed-mode call (CWinThread::operator HANDLE and SetPriorityClass ) to accomplish this.
A precisely 40 ms timer with not a single micro-second delay or advance is impossible in a modern operating system. For such a purpose, you'd need to design and implement a micro-controller or similar solution.
Named events are used to schedule interprocess actions, or interthread actions. For example, you could create an event object in a remote thread to mark when this thread has ran a single loop. When the event object is signaled, a loop is complete and the next loop is starting, if it's a continous system. Event objects can be global or local, determining how they are created. Global of interprocess, local for interthread should be your general rule.
Even if you used named events, you would need some method to set the event to a signaled state whenever 40 ms has passed. This will again lead you back to the timing issue and the timers. Named events is the easiest way to signal other threads or processes that your 40 ms interval has passed, though.
Hope this helps.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Timer (WM_TIMER) messages have the very lowest priority in Windows. Even paint messages have a higher priority than timer messages. You shouldn't expect reliable behaviour from these timers.
Windows offers two other timer facilities: multimedia timers and waitable timers. For the first see Using Multimedia Timers[^]. For the second see the CreateWaitableTimer[^] function.
Another alternative is to decide whether you really need that resolution. If you're simply trying to update a timer display, measure the actual elapsed time using GetTickCount .
It sounds like you're trying to write a real-time system. Windows 2000 is not a real-time OS - the interrupt latencies are simply not predictable. If this is what you're trying to do, either obtain a real-time kernel which runs Windows as a subtask, or use Windows CE.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
I would like to be able to capture a right click on a button. CButton doesn't seem to allow me do so, it only has click and double click messages. I tried creating my own button which was derived from CButton. The header file definition:
<br />
class CMyButton : public CButton<br />
{<br />
public:<br />
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);<br />
DECLARE_MESSAGE_MAP()<br />
};<br />
And then in my implementation file I have:
<br />
BEGIN_MESSAGE_MAP(CMyButton, CButton)<br />
ON_WM_RBUTTONUP()<br />
END_MESSAGE_MAP()<br />
<br />
void CMyButton::OnRButtonUp(UINT nFlags, CPoint point)<br />
{<br />
}<br />
With this, I capture all right clicks on the dialog, not exactly what I wanted. Is there a way for a button to capture right clicks? I would also like to capture left clicks, but that should be simple once I know how to capure right clicks.
Greba,
My lack of content on my home page should be entertaining.
|
|
|
|
|
Now that I've answered my own question
All I needed to do (it seems) was to add Default() in the OnRButtonUp(...) function. Like this:
<br />
BEGIN_MESSAGE_MAP(CMyButton, CButton)<br />
ON_WM_RBUTTONUP()<br />
END_MESSAGE_MAP()<br />
<br />
void CMyButton::OnRButtonUp(UINT nFlags, CPoint point)<br />
{<br />
Default();<br />
}<br />
Greba,
My lack of content on my home page should be entertaining.
|
|
|
|
|
Hi,
The problem is, prior of catching the button up message the button DOWN message must be handled!.
What you do, is catching all down messages, because when the mouse button is released your button provides the only handler for UP messages.
I know it's weird. But best is to react on the down message, setting a flag and in the UP handler do any action only if the flag is set. And always rest the flag.
GSte
|
|
|
|
|
Is there a regular repression class in VC++?
I would like to convert following VB code to VC++ code. Thank you.
<br />
Dim regexp As New Regex("<(B|b)(L|l)(O|o)(C|c)(k|K)(q|Q)(u|U)(O|o)(t|T)(e|E)")<br />
Dim matches As MatchCollection<br />
Dim m As Match<br />
<br />
'matches = regexp.Matches(body, "<\/(B|b)(L|l)(O|o)(C|c)(k|K)(q|Q)(u|U)(O|o)(t|T)(e|E)>")<br />
'If matches.Count > 2 Then <br />
'End If<br />
'm.index position is in the right position where <blockquote was found<br />
' therefore, substracting compund length of deleting <blockquote... > string from original match index <br />
'finding all the blockquote string and store in the array<br />
matches = regexp.Matches(body)<br />
If matches.Count > 2 Then<br />
Dim bquotes(matches.Count) As String<br />
Dim bquote As String<br />
Dim index As Integer = 0<br />
Dim count As Integer = 0<br />
<br />
For Each m In matches<br />
close1 = body.IndexOf(">", m.Index)<br />
Dim temp As String<br />
Dim found As Boolean<br />
temp = body.Substring(m.Index, close1 + 1 - m.Index)<br />
If index <> 0 Then<br />
For Each bquote In bquotes<br />
If bquote = Nothing Then<br />
Exit For<br />
End If<br />
If (bquote = temp) Then<br />
found = True<br />
Exit For<br />
Else<br />
found = False<br />
End If<br />
Next<br />
End If<br />
If Not found Then<br />
bquotes(index) = temp<br />
index += 1<br />
End If<br />
Next<br />
Dim i As Integer = 0<br />
For Each bquote In bquotes<br />
If (bquote = Nothing Or i = index) Then Exit For<br />
body = regexp.Replace(body, bquote, "")<br />
i += 1<br />
Next<br />
body = regexp.Replace(body, "<\/(B|b)(L|l)(O|o)(C|c)(k|K)(q|Q)(u|U)(O|o)(t|T)(e|E)>", "")<br />
body = regexp.Replace(body, "(M|m)(A|a)(R|r)(G|g)(I|i)(N|n)-(L|l)(E|e)(F|f)(T|t):", "")<br />
End If<br />
regexp = Nothing
|
|
|
|
|
Not in the language itself but there is a lot of free source code that will do what you want. Search this site...
John
|
|
|
|
|
|
There are a few articles at CP about REs but that is not what you appear to be looking for. It is my understanding that the boost regex++ by Dr John Maddock has recently been accepted as part of the standard. Whether it will meat you requirements I do not know, but it is very good.
Search for regex++ online, the version I have tested came from the authors sight.
Good Luck!
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
Hi all,
I'm trying to fix some efficiency issues with some graph-drawing code in my application. This is an MFC application, so I'm using CDCs. Different parts of the graph display are rendered to seperate in-memory CDCs, and then they are combined into a final in-memory CDC via BitBlt() calls. This final CDC is then BitBlt()ed to the window's CClientDC during OnPaint().
I've added some QueryPerformanceCounter() calls into my rendering code to try and figure out what calls are eating up the most cycles, and I'm seeing some wierd behaviour. Here's an example:
<------------SNIP------------------>
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 827, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 0.017600 milliseconds
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 839, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 0.017600 milliseconds
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 837, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 876.786575 milliseconds
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 814, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 0.017879 milliseconds
<------------SNIP------------------>
As you can see, normally this BitBlt() operation takes very little time, but every now and then it jumps up to around 800ms. I can't figure out why!
Any one have any suggestions?
TIA,
Pete
|
|
|
|
|
Hi,
OS? probably not really multitasking and hanging in another process.
Sytem clean up?
Kind of magic numbers?
Swapfile operations?
GSte
|
|
|
|
|
Thanks for the reply.
Sorry, you're right, I should have included more information.
I'm running on Windows 2000, and probably working this machine a little too hard with quite a few processes.
As to the rest of you reply, I'm not really sure what information you're asking for? If you could, it'd be great if you could go into a little more detail as to exactly what information is relevent. It would be even GREATER if you could give me a little advice on how to collect it.
Jeez, I don't ask for much, do I?!
Thanks again,
Pete
|
|
|
|
|
Hi,
Sorry that I didn't make it clear. Those were not questions but hints, what you should ask.
Like, are there page misses, so the system as to relad memory from the swapfile.
Is any process eating up CPU-time by atomic instructions (anti virus software/ multimedia player).
If your using W2000 try to shut down most processes you can, to get the time measurement more reliable.
See if there is a pattern in the time frame, like every third or fourth call is aout of order.
I can't give you a solution, but just a few hints how to track the problem.
And if anything fails, use your imagination.
I once had a similiar problem and a wrongly installed outlook proofed to be the trouble maker.
Regards
GSte
-- Even dwarves were born small --
|
|
|
|
|
Hi GSte,
Thanks again for your input on this, I really appreciate it!
Would you be able to point me in the right direction on how I can look into the page-misses stuff? Is this something I can investigate with in-code profiling, or with the Task Manager, or do I need some more specialized profiling tools?
Also, after some more experimentation (including turning off my internet radio - doh!), I've found the following:
- Minimizing the number of other processes seems to have negligable effect.
- The slow calls only happen when the window size is being /increased/, never when it is being /decreased/.
- If I resize the window slowly, then every other BitBlt() call is slow, e.g.:
<-----------------SNIP-------------------->
...
...
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 752, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 0.011454 milliseconds
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 755, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 630.962036 milliseconds
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 758, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 0.015086 milliseconds
C2DTrajWindow::UpdateVirt(): m_memDC.BitBlt( 0, 0, 1280, 762, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 636.752995 milliseconds
...
...
etc.
<-----------------SNIP-------------------->
I don't suppose you have any insights after seeing this information?
Thanks again,
Pete
|
|
|
|
|
hi again,
Looks like we found the nasty guy. Page misses.
Everytime you make the picture larger a new block of memory must be allocated. If the RAM is low, than a part of the memory must be swapped to the memory file on disk (aka swap file). And that's what takes so long. Only solution so far ( And I mean this serene) lots of RAM, RAM, RAM.
How can I tell?
You see, the first allocation gets swift. When you increase the picture size, the system will allocate a block of memory a liitle bit larger than needed. That makes the second enlargement pretty fast. The third enlargement must be reallocated again (slow). And so forth.
Probably (I don't know for sure) you can preallocate a reasonable (lets say 1600*1200) amount of memory prior BitBlitting the immage the first time. That way by enlargening a smaller picture needn't to be reallocated until it exceeds the size of 1600*1200. But I don't know how this could be done.
Maybe a code like this will work.
Avoid flickering
-- Disable Output
BitBlitt(1600*1200)
Enable Output
BitBlitt(1280*600)
BitBlitt(1280*610)
and so on.
How to en/disable painting the image depends. There are several functions for this purpose.
Regards. Please referr to you most likely base class reference.
Regards
GSte
GSte
|
|
|
|
|
I follow your reasoning, and it does seem completely reasonable.
The only thing is, I don't see why BitBlt() is /allocating/ memory. As far as I was aware, BitBlt only copies blocks of memory.
I /am/ allocating larger bitmaps as the window size increases, but that's done outside of the code I'm profiling. Here's how I'm profiling the code:
<------------------SNIP---------------------->
#ifdef _DEBUG
LARGE_INTEGER time4;
VERIFY( ::QueryPerformanceCounter( &time4 ) );
#endif
m_memDC.BitBlt( 0, 0, m_iScreenWidth, clientRect.Height(), &m_decorationsMemDC, 0, 0, SRCAND );
#ifdef _DEBUG
LARGE_INTEGER time5;
VERIFY( ::QueryPerformanceCounter( &time5 ) );
#endif
...
...
...
TRACE( " m_memDC.BitBlt( 0, 0, %i, %i, &m_decorationsMemDC, 0, 0, SRCAND ) ] took %f\tmilliseconds\n"
, m_iScreenWidth, clientRect.Height(), ((time5.QuadPart - time4.QuadPart)/(double)freq.QuadPart)*1000 );
<------------------SNIP---------------------->
As you can see, the only thing I'm timing is that one call to BitBlt(...), so it's definitely something within that method that's slowing down.
One thought I had was that maybe BitBlt() is doing some behind-the-scenes allocation for some reason? Or perhaps there's some lazy-initialization going on where the CBitmaps attached to my CDCs only allocate memory when needed, in this case somewhere within BitBlt(). That doesn't really make sense though - I'm drawing into the source CDC before the guilty BitBlt() call (and presumably the memory would have to be allocated then), and I call
m_memDC.BitBlt( 0, 0, m_iScreenWidth,
clientRect.Height(), NULL, 0, 0, WHITENESS );
earlier as well, so as far as I can tell both the source and destination DCs' CBitmaps should already be allocated when that slow call BitBlt() happens.
Strange, no? Anyways, thanks once again for your help. If you have any further thoughts, obviously I'd love to hear them!
Cheers,
Pete
|
|
|
|
|
What is the value for rcClipBox if you call
CRect rcClipBox;
m_memDC.GetClipBox(rcClipBox);
TRACE("l: %d, t: %d, r: %d, b: %d",
rcClipBox.left, rcClipBox.top,
rcClipBox.right, rcClipBox.bottom);
just prior to each BitBlt call?
Pssst. You see that little light on your monitor? That's actually a government installed spy camera. Smile and wave to big brother!
|
|
|
|
|
C2DTrajWindow::UpdateVirt:
ClipBox - l: 0, t: 0, r: 1280, b: 740
m_memDC.BitBlt( 0, 0, 1280, 740, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 617.089323 milliseconds
C2DTrajWindow::UpdateVirt:
ClipBox - l: 0, t: 0, r: 1280, b: 748
m_memDC.BitBlt( 0, 0, 1280, 748, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 1.938794 milliseconds
C2DTrajWindow::UpdateVirt:
ClipBox - l: 0, t: 0, r: 1280, b: 750
m_memDC.BitBlt( 0, 0, 1280, 750, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 628.530162 milliseconds
C2DTrajWindow::UpdateVirt:
ClipBox - l: 0, t: 0, r: 1280, b: 760
m_memDC.BitBlt( 0, 0, 1280, 760, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 1.418616 milliseconds
|
|
|
|
|
OK, how about the clipbox values for m_decorationsMemDC?
Pssst. You see that little light on your monitor? That's actually a government installed spy camera. Smile and wave to big brother!
|
|
|
|
|
Hi Jack,
Pretty much the same story:
<---------------------SNIP----------------------->
C2DTrajWindow::UpdateVirt:
m_memDC's ClipBox - l: 0, t: 0, r: 1280, b: 807
m_decorationsMemDC's ClipBox - l: 0, t: 0, r: 1280, b: 807
m_memDC.BitBlt( 0, 0, 1280, 807, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 684.505154 milliseconds
C2DTrajWindow::UpdateVirt:
m_memDC's ClipBox - l: 0, t: 0, r: 1280, b: 809
m_decorationsMemDC's ClipBox - l: 0, t: 0, r: 1280, b: 809
m_memDC.BitBlt( 0, 0, 1280, 809, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 2.769346 milliseconds
C2DTrajWindow::UpdateVirt:
m_memDC's ClipBox - l: 0, t: 0, r: 1280, b: 812
m_decorationsMemDC's ClipBox - l: 0, t: 0, r: 1280, b: 812
m_memDC.BitBlt( 0, 0, 1280, 812, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 683.831325 milliseconds
C2DTrajWindow::UpdateVirt:
m_memDC's ClipBox - l: 0, t: 0, r: 1280, b: 815
m_decorationsMemDC's ClipBox - l: 0, t: 0, r: 1280, b: 815
m_memDC.BitBlt( 0, 0, 1280, 815, &m_decorationsMemDC, 0, 0, SRCAND ) ] took 2.098870 milliseconds
<---------------------SNIP----------------------->
Cheers,
Pete
|
|
|
|
|
<ctrl><alt> Have you ever look at how many processes might be running on you machine at one time. BitBlt() is like every other piece of code running on youre machine, it is a matter of priority (every body gets a slice of the processors time [at least they are supposed to]). I discover a virus once, becuase I notice that processor time was being eatin (slow down in resonse time).
May be someone can give you an idea for improving the speed if you explained why the graph is rendered in pieces, instead of as a whole.
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
hai..
I'm working on win32 vc++..I want to know waht is the window message that is processed when the window is maximized and minimized..
thanks.
|
|
|
|
|
Look at WM_SIZE.
wParam = SIZE_MAXIMIZED, SIZE_MINIMIZED, SIZE_RESTORED, etc.
lParam = cx -> lo word cy -> hi word
Hope this helps.
|
|
|
|
|
Is thera any way for
int a = 5;
int b;
b's memory address point to a's?
so &b would equal to &a.
Or the only way is create a pointer to do it
int a = 5;
int *b;
b = &a;
|
|
|
|
|
Or the only way is create a pointer to do it
me think yes.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
|