March 31, 2008
Ah the windows message pump – you just can’t get away from it regardless of the language you write in. I may be developing Windows programs on my Mac now (using Parallels) and I’m using C# for the current project, but necessity demands I write yet another version of the message pump. I’ve blogged about this before for various reasons.
I’m currently developing an application which will playout video on a live-to-air broadcast. Apart from the necessary robustness this demands, another crucial element is the timing and synchronising with a timebase. Generally as GUI developers we don’t have to deal with things this way around. It’s more likely we have to cope with displaying high volumes of data from a stream in a window somewhere. You’re then faced with the usual – do I throttle it, buffer it, lockless queue it type questions. As long as the painting of the screen doesn’t end up in white outs or frozen, partially painted windows the users are happy. I’ve written about this before and it’s all about keeping the message pump, pumping away.
The point here is you’re not particularly concerned that WM_PAINT and WM_TIMER messages, being the amoeba of the windows message world, get pushed to the back of the message queue, because eventually they will get processed.
However, if you have to provide screen updates with accurate, rock solid countdown timers that don’t stutter and can be absolutely relied upon, you need to tackle things slightly differently. You need accurate timers and timing which is not normally the forte of Win32.
For what I needed to achieve, working with video was a very accurate video frame counter and execute some code in the message pump every frame. Since it is PAL this means every 40mS and the code shouldn’t take more than 40mS to execute. If it does then it needs to take account of the overrun.
So the choices for accurate timing are:
Well you could use this, but you’d be mad. Although it is documented to return the current system time in milliseconds, the actual precision can range from a few up to 55mS depending on operating system.
Accuracy: 5 – 55 mS
Resolution : 1 mS
Execution time : 0.1 uS
As part of the multimedia system, this is accurate to 1 mS and can be relied upon, but it takes a long time to execute.
Accuracy: 1 mS
Resolution : 1mS
Execution time : 8.0 uS
The way to go if you want uS accuracy and resolution.
Accuracy: 1 uS or better
Resolution : 1uS
Execution time : 4.0 uS
Unfortunately, the performance counter is not available on all PCs. If you’re running on old hardware or an old version of Windows this API uses a programmable timer chip (part of the chipset) as the clock. This has a frequency of 1.19318MHz meaning an accuracy of around a uS. More recent chipsets will from Intel will give you a frequency of 3.579545MHz.
The frequency only affects the resolution and the API gives you a call to query it, so you can take it into account.
So how can we incorporate this into a message pump and get the accuracy required. A typical message pump looks like this:
while (GetMessage(&msg, NULL, 0, 0))
TranslateMessage( &msg );
DispatchMessage( &msg );
The well known problem with this is GetMessage. It won’t return until a message is available to be dealt with, so we’re always waiting for Windows to give us something – obviously no good because we need to do stuff every 40 mS. The classic way to solve this uses a PeekMessage in the message pump to see if there is a message available. If not then you can call what ever code you need to execute. So the alternative which incorporates a rock solid 40 mS with a resolution of about 1 uS is like this:
DWORD msPerFrame = 40;
BOOL okToDoWork = true;
::QueryPerformanceFrequency((LARGE_INTEGER *) &timerFrequency)
msPerFrame = timerFrequency / 25; // 25 frames per second i.e 40mS frame rate
::QueryPerformanceCounter((LARGE_INTEGER *) &nextTime);
::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE);
if (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
okToDoWork = false;
} ::QueryPerformanceCounter((LARGE_INTEGER *) &timeNow);
if (timeNow > nextTime)
nextTime += msPerFrame;
// Effectively drops a frame if we've taken too long
// to draw stuff.
if (nextTime < timeNow)
nextTime = timeNow + msPerFrame;
okToDoWork = true;
April 18, 2007
Having just had another article published on codeproject, I am reminded yet again how much I miss many of the features of C++ when I’m coding in C#. There’s no denying C# is a very productive language, but C++ techniques I have used and taken for granted just aren’t possible.Generics are a case in point. I constantly feel C# is wanting to hold my hand while crossing the programming road. Generics and C++ templates are not the same thing – the design goals are very different. C# generics are like classes that have a type parameter and everything (pretty much) happens at runtime and C++ templates are just macros that look like classes and it all comes together at compile (and maybe link) time.
If all you do with templates is type safe collections, this is probably not an issue and generics could be considered a safer approach, but it is very limiting. In the SyncInvoker article I use template metaprogramming to achieve code reusability. More accurately I guess this comes under the heading of generic programming so I avoid having the re-write sections of similar code that have minor variations. I guess I’m just lazy.
Template metaprogramming allows the programmer to concentrate on architecture and delegate to the compiler the generation of any implementation required by client code. With template metaprogramming you can create truly generic code – a smaller codebase and better maintainability. However, the syntax and idioms of template metaprogramming are esoteric compared to conventional C++ programming sometimes even the most trivial, template metaprogramming can be very difficult to understand.
March 26, 2007
I’m hardly a behemoth of jollity back in the world of C++ at the moment. Much as a think it is an excellent language, I am reminded that is so open to abuse. Take the following example I recently stumbled across.
throw "Floating point error"
catch(const char *e)
if (strError == "floating point error")
else if (strError == "some other error")
else if (strError == "some violation")
Clearly this is open to all sorts of problems. Probably the most obvious it breaks when the string content changes due to capitalization and the floating point error never being seen. However, for me the most significant problem here is a fundamental misunderstanding of what exceptions are really all about.
The author of this code is trying to catch an exception based on its value and not its type. A string literal contains practically no information about the type of exception being thrown. It’s no different to using a string to represent a float or complex number. You can do it but you’d be making hard work for yourself.
And this isn’t confined to string literals. Throwing ints, floats or any predefined type has all the same issues. Once caught, there is no real type information, so you can’t be sure what it represents and have to jump through hoops to fathom how to deal with it – the Temple of Doom!
I’m not going into a long technical treatise about C++ exceptions; there’s plenty of books and online material that cover it much better than I could. However here’s some bullet point reminders I tend to keep in my head for such occasions that are mostly obvious.
- exception types are abstract data types representing an exceptions.
- provide some standard method (what) that describes the exception and maybe a code.
- better still, derive from a standard exception type. You can then catch the specific type or the base class type.
- make sure you’ve got a non-throwing copy constructor and destructor in place.
- don’t throw exception pointers. The address of the exception pointer will be somewhere on the heap and isn’t protected for the duration of the catch. A temporary stack based exception is guaranteed to be safely persisted until the exception has been handled, regardless of platform and compiler.
- throw by value and catch by reference
- you prevent unnecessary copying of large exception objects
- you ensure that modifications applied to the exception within a catch clause are preserved in the exception object if it is re-thrown
- you avoid slicing of derived exception objects
- you’ve got less work to do!
As Short Round said – “I keep telling you, you listen to me more, you live longer!”
February 25, 2007
I’m currently porting a Linux C++ pricing library and agent to Win32 – the goal is to grid enable it and deploy it on a DataSynapse. Now this is a very large project with many hundreds of headers and libs. Understanding the make dependencies and seeing how it would be possible to decompose the code to be grid friendly is complex to say the least.
Simply trying to build the project on Visual Studio, MinGW or CygWin is not enough to see what is missing. The build only shows you what the next few headers and libs are missing and you need to look deep into the dependancy graph and not worry about what builds and what doesn’t.
IncludeManager from Profactor is a saviour when you need to do this. It’s targeted more at the ‘what will rebuild if I change this file’ use, but I find it very useful for gaining a clearer picture of complex dependancies. It’s easy to collapse the graph to reduce dependancy noise.
And it’s very cheap!