Writing fancy code on a plain compiler
This is a story of porting C++ code using all the latest features to a machine whose compiler was (ahem) definitely not supportive of advanced features :-/
Back
in about 1997 and 1998 I was a software consultant and got hired by an old
coworker at Avid to help them port their shiny new high-performance
file-copying software to the Irix. IIRC, they had written it in “portable” C++
which I discovered was anything but ☹
Writing code with no strings attached
Amongst
the other delights of 1997 era SGI workstations: SGI was a leader in creating
the C++ STL. But the SGI people really, really didn’t like the proposed STL
string types, so they just … didn’t. One of the many, many steps on my journey
to porting this code was to create enough of a string class to compile.
Other
issues were that vector<> wasn’t compatible either, so I had some lovely
#ifdef’s in the code.
What's in a namespace? Nothing.
The
compiler also didn’t handle namespaces; they were read in an ignored. For most
code this was a minor inconvenience, but the people writing this “portable” C++
code were a different breed. They had many, many classes with the same name and
similar but different functionality. My solution was to create enough of a C++ “parser”
to re-write the code. Turns out that if you ignore enough of the rules, you can
make a C++ parser with just Lex 😊
Exceptionally fine threading
But
the absolute worst part was that the “portable” C++ code used both multiple
threads (typical for networking code) and exceptions (still a new thing). The
SGI compiler (which was the only compiler – I did a thorough look to find
anybody else with a compiler) could handle threads, and could handle
exceptions, but created incorrect binaries when dealing with both. And it didn’t
matter if you threw any exceptions; the generated code was wrong regardless.
My
simple solution was to note that every single exception was uniformly caught
exactly one level higher, and that none of their code ever returned a value. So
I just made the exception-throwing methods return a value, instead. Simple, quick
to implement and IMHO made the code a little nicer looking. This solution was
rejected.
The alternative solution was to use processes instead of threads. A “thread spawn” became a “process
spawn”. And not just a process spawn: a process spawn all of the processes sharing
their C++ memory so the data structures should be shared (and mutually updated,
meaning using cross-process mutexes).
This was an unglodly heavyweight project. But the pay was
very nice.
TL/DR
Moral of the story: never outrun your compiler?
No comments:
Post a Comment