Sunday, September 09, 2007

hash_map band aid

Until TR1 is widely available, I'm using this wrapper to construct hash maps using the hash_maps distributed with Visual C++ and GCC. I thought it might be useful for someone else, so here goes.
#if defined(_MSC_VER)
#include <hash_map>
#elif defined(__GNUC__)
#include <ext/hash_map>
#endif

template <typename K> struct default_hash {};

template <> struct default_hash<int> {
 size_t operator()(int v) const
    { return size_t(v); }
};

template <> struct default_hash<unsigned int> {
 size_t operator()(unsigned int v) const
    { return size_t(v); }
};

#if defined(_MSC_VER)

template <
 typename KeyType,
 typename ValueType,
 class HashFun = default_hash<KeyType>
 >
struct HashMapOf
{
 struct Traits
 {
  static const size_t bucket_size = 4;
  static const size_t min_buckets = 8;

  HashFun hasher;

  inline size_t operator()
    (const KeyType& key) const
  {
   return hasher(key);
  }

  inline bool operator()
     (const KeyType& lhs,
      const KeyType& rhs) const
  {
   return lhs < rhs;
  }
 };


 typedef stdext::hash_map<
    KeyType,
    ValueType,
    Traits> Type;
};

#elif defined(__GNUC__)

template <
 typename KeyType,
 typename ValueType,
 class HashFun = default_hash<KeyType>
 >
struct HashMapOf
{
 typedef __gnu_cxx::hash_map<
    KeyType,
    ValueType,
    HashFun> Type;
};

#else
# error Unsupported toolchain.
#endif

Sunday, February 18, 2007

Vista and Visual Studio, Oil and Water

So I've installed Vista (Ultimate, in fact), but Visual Studio 2005 seems like a terrible Vista citizen. In order to run it you need to apply the service pack, but also a beta version of a hotfix package. Even then, Microsoft recommends you run Visual Studio as Administrator. Now, I ask myself: Does compiling source code demand complete access to the entire box? On Vista, that's apparently the case. It seemed to work fine on XP. Now to the most juicy bug of the day. Once you've started a debugging session from within Visual Studio, the target EXE file becomes locked. Closing Visual Studio removes the lock, but the devenv process doesn't hold any handles to the file. What gives? I'm starting to suspect that the SUA services might have something to do with this, so they're uninstalling right now. It's pretty annoying to restart the IDE after each debugging session to be able to recompile. Update I've identified SUA to be the problem. After uninstalling the SDK and removing the windows services it installs, I can recompile and debug again.. For now.

Wednesday, February 14, 2007

The pleasures of a stable ABI

As broken as the Win32 API might appear, the thing I really like about it is its stable ABI. That, and the fact that Microsoft spend thousands of hours making sure that old programs work when they release a new version of Windows is worth a lot to me. Solaris has a decent ABI, and I assume most other unices have too. What would it take for Linux to achieve the same level of stability? The Linux kernel does have a fairly stable ABI as long as you say away from the proc file system and device nodes (devfs and whatnot come and go). The C library is also well designed. Most issues with Linux binary (in)compatibility have been in the C++ libraries. The C++ libraries have changed ABIs with each and every version of the compiler, sometimes even breaking with point releases. Breaking the C++ ABI isn't a problem in itself, it happens with the Visual Studio compilers all the time. The real problem is that when deployed, Linux binaries depend on the distribution to include a suitable C++ runtime library to which they can dynamically link, whereas on Windows, programs either carry their C++ runtime with them (pre-VC8) or rely on a separate distributable that can be installed side-by-side in the DLL cache so that a compatible version is always available. For the Battlefield Linux server builds I had this exact problem. I had to use at least GCC 3.x as GCC 2.x was (and still is) a severely outdated compiler without proper namespace support. However, using GCC 3.x meant that people with rented servers that ran older versions of Red Hat were left out in the cold, unless they could find a standard C++ library that would somehow let them run the binary! This was seen as a Bad Thing. The only solution I could think of at the time was to provide a statically linked executable in addition to the regular executable, so that older systems had a hope in hell to run it. That required me to tweak and override certain symbols of the standard library to avoid them from referencing versioned symbols from glibc that weren't present on the target systems, and the whole things was just a terrible mess that took too much time. In the end, linking statically turned out to be somewhat illegal (as we couldn't satisfy the LGPL on that binary) so that option had to be removed. I considered it fair use because there was indeed a dynamically linked executable available as well that did satisfy the LGPL, but it was thought safer to drop it. It would have been so much nicer to ship a C++ library redistributable for x86 and amd64 and let users install it if needed..