Friday, January 26, 2007
Blogspot does feel a lot better, but there are still quirks. Specifically, it seems to cramp the content of my "pre" tags onto single lines, leaving no spacing between e.g. the interfaces shown in the previous post.
If anyone who happens to stumble by this blog has any hot tips for utilities, websites or anything which can easen the burden of posting source code; do tell me! That'd be much appreciated.
Update, Janauary 29th: I wrote a small application which takes a piece of C / C++ / C# / Java / ASM source code as input. The code is syntax highlighted using an online service, and then HTML formatted for BlogSpot. I'll be testing it on my next post, so stay tuned (exciting, isn't it ;-)
The __interface keyword, as horrific as it seems (I may be too much of a code poet (disregard my old hexdump post)), it can be useful in some situations. While classes in C++ can be implemented with the same "features" as those implied by an __interface structure, the latter will force you to use them. This means that with a __interface, there's no chance for you to
class Foo : public IFoo
// do the foo
- include implementation in the interface
- inherit anything other than interfaces
- include anything but public pure virtual functions
- include data members
- ... and so forth
So the point, as I see it, of the __interface structures, is to enforce some rules which have previously been restricted to comments, coding conventions and syntax verifiers. As such, it's a good thing. Whether or not you should use it, that's an entirely different story (and covered later).
In a scenario where you've got a class which inherits two or more interfaces, you may wish to change the behavior of a derived implementation, based on which interface the function is being called through. So along with the introduction of __interface, came the ability to override functions in specific interfaces.
Now the usefulefulness of this construct is questionable. Not to mention that it enables you to write structures that are less than intuitive to an end-of-the-line user. To elaborate: in the example above, doFoo will never be callable on an instance of Foo, unless you cast to a specific interface. doBar, on the other hand, is callable in any case. I'm not saying there aren't cases where this could come in handy, but if you wish to use it, give a second thought to how it'll to your next of kin.__interface IFoo
class Foo : public IFoo, public IFoo2
// doFoo called on IFoo ptr/ref
// doFoo called on IFoo2 ptr/ref
f.doFoo(); // C2668: ambiguous call to overloaded function
f.doBar(); // Ok, calls Foo::doBar
IFoo2& if2 = f;
if2.doFoo(); // Ok: calls Foo::IFoo2::doFoo
The "for each in" principle is something many other languages have had for quite some time. C# has it, Java has it (though not with the "each" suffix), and so do most script languages you can come up with. If applied properly, it simplifies iteration, and contributes to not only better looking -- but also generally more intuitive -- code. With VC8 this feature was introduced to native C++, and there's really no voodoo to it.
While you'd normally iterate a vector in a way such as
The "for each" keyword enables you to do the same thing:vector<int> v;
for(vector<int>::iterator i = v.begin(); i != v.end(); ++i)
// do whatever with *i
That sure looks better to me.for each(int i in v)
// do whatever with i
By now, I'm sure all die-hard C++ enthusiasts are strangling the bejesus out of anything in near vicinity. Rest assured, though, I'm not pitching these constructs as something you should carelessly embrace. While they can all be handy, there's the inevitable conformance and portability matters to consider. If you were to embed this deep within a project, you can kiss any cross platform code reuse good-bye. We obviously wouldn't want that.
Use them as you see fit, I say. And even more importantly: now you know that they exist, and you won't loose face by loudly proclaiming that "That code couldn't possibly compile!!!11".
Friday, January 19, 2007
The order in which you place your source lines will dictate how your application runs, and generally how well it works. Would you agree?
While it's correct per se, reality isn't quite as simple as one could mistakenly assume.
The basis for this claim is the complexity that is the computer you are sitting by. CPU, memory, pipelines and cache. It's an intricate collection intricate components. What this means for you, the programmer, is that you place your faith in those who've put it all together. And let's get just one thing into the open: they are doing a good job. Making this complex machinery work as you'd expect it to, even given code of (to say the least) varying quality, is truly an accomplishment. Obviously it's not just the merit of the hardware designers. Compiler programmers (among others) also deserve their moment of glory. You can do just about anything, in just about any order and fashion you see fit, and the compiler will find a way to optimize it. Sure; it breaks down occasionally, and there are bugs, but you produce your fair share of those as well.
One specific area of programming isn't quite that trivial. This may very well be where the most responsibility is placed upon the programmer, but it is also an area where compiler-, OS- and hardware designers spend much of their time "Making Your Crap Just Work". What field? Multi-threading, of course.
Usually, you just slap a few mutexes here and there, and it just works. Brillant. That's often the one and only advice you'll get when you move into threading; mutexes. With lower level languages, like C++ , it's not always enough, though. There are many perils you need to acquaint yourself with. Shared memory access. The order of said access. Instruction reorderings. Cache coherency. There's a lot of material to cover, and I suggest you take the time to familiarize yourself with it by reading through the articles listed below.
Wednesday, January 10, 2007
The last couple of months I've been spending just about all my working hours (and obviously most of the wee hours) on a project for a customer of ours. I'm the only one in the company with the required competency (or pain treshold), so I've been calling most of the shots -- a fact that often contributes to the mentioned wee hours. Anyway, it's a fairly straight forward job, though involving a specific piece of horribly unpredictable technology. By horribly unpredictable, I mean that risk analysis voodoo gets you little further than a donkey on a steep hill. Short of coloring the project name red, it doesn't reveal much. I'm at the mercy of the API, plain and simple, and there's no way to get around that. It's all about acceptance. And breathing.
However unpredictable, I've been on several similar projects before, using the same technology. You could say I've worked my way up to fair expectations. I've learnt that any sudden movement may cause the technology to completely break down, and give my proverbial mouth a good punch. The sad fact, though: there's absolutely no way to get around the use of neither the API nor the technology as a whole. The project, and the $'s, depend on it. Can I complete the job? Given the necessary amount of coffee, and more repeats of Danko Jones' tune than I believe would be proper without marrying the guy; sure.
So why am I sharing this with whomever stumbles by the blog? It's an excuse, obviously. I've had several updates in the pipeline the last couple of months, but only managed to complete the ThreadSynch ramblings. I haven't even found time to update the Thunk32 library yet, which I believe I promised would "only take a couple of days" to someone back in December. That's it for the excuse, though. The point is that if you're here, and you've actually checked by the blog more than this one time during these past few weeks; don't stop doing so. I'll be sharing all kinds of nonsense with you lot in due time, I'll just have to power through this project first.
Thursday, January 4, 2007
In anticipation of technical material, I suggest you get the new year started with a hot cup of coffe, and the unofficial coder anthem; Danko Jones' "We Sweat Blood".
I'm into never stopping
I'm making no sense
But I can never sit still I keep on riding
When you're fast asleep I'm working all night
I never sleep either I'll take a break when I die