Anyone who’s ever needed to write cross-platform code in C or C++ knows that TRWTF is endianness. Your options are either to use a lot of platform specific preprocessor macros, or to coerce all of your data into your own specific format, for portability.
Adam H’s company took the latter approach, implementing a ByteWriter
class. It was relatively easy to use, with code that looked something like this:
byte* tempData = new byte[128];
ByteWriter* writer = ByteWriter::Instance();
writer->Initialize(tempData);
writer->PutInt32(someIntValue);
writer->PutInt32(someOtherIntValue);
writer->PutByte(someByteArray);
At this point, tempData
will hold your integers with the correct endianness, regardless of platform. But gee, that call to ByteWriter::Instance
sure looks odd. Is that some kind of factory method? If so, that call to Initialize
is weird. Let’s go to the implementation of the class…
class ByteWriter
{
private:
int _index;
byte* _data;
static ByteWriter *_instance = 0;
ByteWriter() {}
public:
void Initialize(byte* data)
{
_index = 0;
_data = data;
}
void PutInt32(int32_t w)
{
PutInt16((int32_t)(w & 0x0000FFFF));
PutInt16((int32_t)((w & 0xFFFF0000) >> 16));
}
void PutInt16(int16_t w)
{
PutByte((byte)(w & 0x00FF));
PutByte((byte)((w & 0xFF00) >> 8));
}
void PutByte(byte b)
{
_data[_index] = b;
_index++;
}
static ByteWriter *Instance()
{
if (!_instance)
_instance = new ByteWriter();
return _instance;
}
}
And this is what drew Adam into this code in the first place- it was breaking any time it was touched by multiple threads, and of course it was. This is a classic example of the “Unnecessary Singleton” design pattern, commonly implemented by people who have skimmed the “Gang of Four” book, and needed to prove they knew what a design pattern was during an interview.
Unfortunately for Adam, this bit code highlights the problem, but:
This isn’t the source verbatim, as TRWTF here is hard to nail down to one snippet, but it should be clear with a few pieces. (It also means that I may have messed up C++ syntax)
It’s going to be much more complicated for him to actually fix.