Create one decode thread for each CPU

We can start creating more decoding threads now that we handle
rect ordering properly. No point in creating more threads than
there are CPUs though.
diff --git a/common/os/Thread.cxx b/common/os/Thread.cxx
index 7150a7f..f38a10b 100644
--- a/common/os/Thread.cxx
+++ b/common/os/Thread.cxx
@@ -20,6 +20,7 @@
 #include <windows.h>
 #else
 #include <pthread.h>
+#include <unistd.h>
 #endif
 
 #include <rdr/Exception.h>
@@ -99,6 +100,36 @@
   return running;
 }
 
+size_t Thread::getSystemCPUCount()
+{
+#ifdef WIN32
+  SYSTEM_INFO si;
+  size_t count;
+  DWORD mask;
+
+  GetSystemInfo(&si);
+
+  count = 0;
+  for (mask = si.dwActiveProcessorMask;mask != 0;mask >>= 1) {
+    if (mask & 0x1)
+      count++;
+  }
+
+  if (count > si.dwNumberOfProcessors)
+    count = si.dwNumberOfProcessors;
+
+  return count;
+#else
+  long ret;
+
+  ret = sysconf(_SC_NPROCESSORS_ONLN);
+  if (ret == -1)
+    return 0;
+
+  return ret;
+#endif
+}
+
 #ifdef WIN32
 long unsigned __stdcall Thread::startRoutine(void* data)
 #else
diff --git a/common/os/Thread.h b/common/os/Thread.h
index 41d9486..1a9aa54 100644
--- a/common/os/Thread.h
+++ b/common/os/Thread.h
@@ -32,6 +32,9 @@
 
     bool isRunning();
 
+  public:
+    static size_t getSystemCPUCount();
+
   protected:
     virtual void worker() = 0;
 
diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx
index ba2b2d2..724cf21 100644
--- a/common/rfb/DecodeManager.cxx
+++ b/common/rfb/DecodeManager.cxx
@@ -38,7 +38,7 @@
 DecodeManager::DecodeManager(CConnection *conn) :
   conn(conn)
 {
-  int i;
+  size_t cpuCount;
 
   memset(decoders, 0, sizeof(decoders));
 
@@ -46,9 +46,15 @@
   producerCond = new os::Condition(queueMutex);
   consumerCond = new os::Condition(queueMutex);
 
-  // Just a single thread for now as we haven't sorted out the
-  // dependencies between rects
-  for (i = 0;i < 1;i++) {
+  cpuCount = os::Thread::getSystemCPUCount();
+  if (cpuCount == 0) {
+    vlog.error("Unable to determine the number of CPU cores on this system");
+    cpuCount = 1;
+  } else {
+    vlog.info("Detected %d CPU core(s) available for decoding", (int)cpuCount);
+  }
+
+  while (cpuCount--) {
     // Twice as many possible entries in the queue as there
     // are worker threads to make sure they don't stall
     freeBuffers.push_back(new rdr::MemOutStream());