25 April 2007

Compile-Time use of assert

Why do at runtime what you can do at compile time? A lot of times, code depends on the values of certain enums not changing, or if they do, the code must be updated. If not handled properly, this can become a maintenance nightmare.

Use of the assert keyword comes in handy here. You can assert in debug builds that the value is what you expect it to be and whoever is maintaining your code will know what they need to do to make their new value work (because, let's face it, you comment your code great).

There's one little problem though. The assert line only happens if it's executed, therefore it might not catch all situations of misuse (at least not right away).

Here's a neat little trick:
#define compiletime_assert(argument) \
{ int unused[ argument ? 1 : -1 ]; }

compiletime_assert(MY_SPECIAL_VALUE == 4);
This gets evaluated at compile time. If anyone changes MY_SPECIAL_VAL to a value other than 4, the compiler will stop there with an error. The only downside is that the error is pretty cryptic, but good commenting will help out there. Obviously this will only work for things the compiler is able to evaluate at compile time, but that includes some very useful things like sizeof and value checking.

Software bugs, but not what you think

I'm posting this because of the people who didn't believe me. You know who you are.

According to an article that happened to find its way into my email, scientists have found and modified a particular bug protein so as to use it for data storage. Apparently, a LOT of storage.

The article estimates commercially available USB drives available a year from when it was written, but it's been almost a year and doesn't seem to be mainstream yet.

I'll keep my fingers crossed.

16 April 2007

Gun Control and the VA Tech Shootings

So it didn't take any time at all for the Gun Control lobby to come out and preach about the necessities of Gun Control.

First and foremost, my condolences and prayers are with the parents, family and friends of the victims of this tragedy. I'm sorry for your loss.

Now, Gun Control is not the answer. Why? Bad people have always been able to do Bad Things, and they don't obey the laws, so why would Gun Control apply to them anyways? The only thing Gun Control would do is cause law-abiding citizens to not be able to get guns that the Second Amendment to the Constitution affords them:
A well regulated militia being necessary to the security of a free State, the right of the People to keep and bear arms shall not be infringed.

Virginia has a concealed carry law, but the VA Tech campus doesn't allow concealed carry and furthermore an official praised the defeat of the concealed carry law on campus! With concealed carry, you don't know who around you has a gun, but if someone does, they've gone through extensive background checks and training. This is almost like a type of militia.

School shootings have really increased dramatically. In the 70's they were almost non-existent, and now there are multiple every year. Kids these days have loose morals, but that wasn't always the case. In the 50's you could find a school parking lot with rifles in trucks, but almost no school shootings. There was another thing present in schools in those days, and that was God. Since God was removed from the public schools in 1962, every major social problem has been on the rise: violent crime, divorce, teenage pregnancy, sexually transmitted disease, etc. Take away children's moral base and tell them that they are the product of nothing other than time, chance and random processes and what do you think will happen? Honestly, where is the outrage?

It's time for America to turn back to the moral base it had. There's nothing progressive about this society.

14 April 2007

Placement new is your friend

It doesn't happen often in game programming when you want to be specific about how (or where) an object is constructed, but it does come up. Consider a simple block allocator:

struct FreeBlock {
FreeBlock* pNext;
FreeBlock( FreeBlock* pNextFree = 0 ) :
pNext( pNextFree ) {}
};

T* BlockAlloc<T>::alloc() {
if ( m_freeList ) {
FreeBlock* pBlock = m_freeList;
m_freeList = pBlock->pNext;
pBlock->~FreeBlock(); // Destruct FreeBlock
// Use placement new to construct T
return new ( pBlock ) T();
} else {
// Get raw memory and set up free list
...
}
}

void BlockAlloc<T>::free( T* pt ) {
if ( pt ) {
pt->~T(); // Destruct T
m_freeList = new ( pt ) FreeBlock( m_freeList );
}
}


This is a very simple example, used only for illustration. The use of placement new allows us to construct only the T objects that are currently in use, but allows us to allocate enough memory for a large number of them.

Calling the FreeBlock destructor is seemingly unnecessary since FreeBlock only has an implicit destructor. However, it's maintainable to do so. What if someone later adds a destructor to FreeBlock to, say, decrement a count of FreeBlock objects?

This is a simple example; placement new is great for many things: containers, singleton objects that you don't want on the heap (but want to control when they are constructed), memory management structures, game resource management and so on.

09 April 2007

Five things you [probably] don't know about me

... or care to.

Anyways, this was going around for a while. Even though no one tagged me I'm going to go ahead and dump this on you. Here goes:
  • I'm a Christian
  • At a young age I turned my life over to Christ. Christian apologetics are very interesting to me. Most people don't understand that it's possible to be an intellectual Christian, but there is amazing historical evidence of Christ, his life, death and resurrection. Christianity has given me pure joy and I attribute any success I have in life to Christ.

  • I'm a Creationist
  • This plays into the first point. Again, it's possible to be an intellectual Creationist. No matter what view of origins you hold, it's not observable, measurable or repeatable. It's a matter of faith. None the less, there are plenty of books and videos that support my point of view on the topic.

  • I've been lost
  • When I was in High School, a friend and I went hiking in the Gila Wilderness. After losing the trail due to snow melt and becoming hopelessly lost, we figured our position on the map as best we could and headed for the Gila River, ignoring those close topographical lines. We had to climb down huge cliffs and eventually had to abandon our equipment. My friend lost one of his boots as he was swept away in the Gila River. When we finally made it to a highway, we hitchhiked the 14 miles back to my car, which had a flat tire. This also plays into the first point as it strengthened my faith.

  • I prefer Country
  • Why? 'Cause it's songs about me. It's music I can listen to in the car with my kids around. It's old-fashioned values and unselfish people still helping each other. Now, if only Guitar Hero would actually come in a country version...

  • I have better-than-perfect vision
  • I have permission from my optometrist to brag on this. He was dismayed at not being able to sell me any glasses or contacts with my 20/15 vision in both eyes. This is amazing to me since my dad has always worn glasses, my younger brother is starting to wear them, and my mom has been wearing them for a few years now.

02 April 2007

Maintainable code [for the win]

Books can (and have) been written on this topic, but I'd like to share one of my favorite little constructs. Often times I'll need to change a variable just for the scope of my function (a locking bool or a depth count for instance). It is ALWAYS better to use a temporary class on the stack to do this.

If I set bRecursionLock = true then I have to remember to always set bRecursionLock = false before I return from the function. What if someone other than me (or even me in a few months) has to change that code? What if someone adds a new return and forgets to set bRecursionLock = false? You get a hard-to-track-down bug. Why bother? The simplist C++ construct can take care of this:

class TempLock
{
    bool& m_lock;
public:
    TempLock( bool& lock ) : m_lock( lock ) { m_lock = true; }
    ~TempLock() { m_lock = false; }
};
TempLock lock( bRecursionLock );


We actually had this situation last week. A function needed a temporary class to change a variable on a class instance just in the scope of a function, so I used this construct even though there were no return statements. At the same time, an intern refactored the same function to return all over the place. When both of our changes were merged, the code worked perfectly.