The "rfb_win32" library merged with VNC 4.1.1 code.

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/branches/merge-with-vnc-4.1.1@523 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/rfb_win32/Threading.cxx b/rfb_win32/Threading.cxx
new file mode 100644
index 0000000..c41ac38
--- /dev/null
+++ b/rfb_win32/Threading.cxx
@@ -0,0 +1,151 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+ * USA.
+ */
+
+// -=- Threading.cxx
+// Win32 Threading interface implementation
+
+#include <malloc.h>
+
+#include <rdr/Exception.h>
+#include <rfb/LogWriter.h>
+#include <rfb/util.h>
+#include <rfb_win32/Threading.h>
+
+using namespace rfb;
+
+static LogWriter vlog("Threading");
+
+static DWORD threadStorage = TlsAlloc();
+
+
+inline void logAction(Thread* t, const char* action) {
+  vlog.debug("%-16.16s %s(%lx)", action, t->getName(), t);
+}
+
+inline void logError(Thread* t, const char* err) {
+  vlog.error("%-16.16s %s(%lx):%s", "failed", t->getName(), t, err);
+}
+
+
+DWORD WINAPI
+Thread::threadProc(LPVOID lpParameter) {
+  Thread* thread = (Thread*) lpParameter;
+  TlsSetValue(threadStorage, thread);
+  logAction(thread, "started");
+  try {
+    thread->run();
+    logAction(thread, "stopped");
+  } catch (rdr::Exception& e) {
+    logError(thread, e.str());
+  }
+  bool deleteThread = false;
+  {
+    Lock l(thread->mutex);
+    thread->state = ThreadStopped;
+    thread->sig->signal();
+    deleteThread = thread->deleteAfterRun;
+  }
+  if (deleteThread)
+    delete thread;
+  return 0;
+}
+
+Thread::Thread(const char* name_) : name(strDup(name_ ? name_ : "Unnamed")), sig(0), deleteAfterRun(false) {
+  sig = new Condition(mutex);
+  cond_event.h = CreateEvent(NULL, TRUE, FALSE, NULL);
+  thread.h = CreateThread(NULL, 0, threadProc, this, CREATE_SUSPENDED, &thread_id);
+  state = ThreadCreated;
+  logAction(this, "created");
+}
+
+Thread::Thread(HANDLE thread_, DWORD thread_id_) : name(strDup("Native")), sig(0), deleteAfterRun(false),
+  thread(thread_), thread_id(thread_id_) {
+  cond_event.h = CreateEvent(NULL, TRUE, FALSE, NULL);
+  state = ThreadNative;
+  logAction(this, "created");
+}
+
+Thread::~Thread() {
+  logAction(this, "destroying");
+  if (!deleteAfterRun && state != ThreadNative)
+    this->join();
+  if (sig)
+    delete sig;
+  logAction(this, "destroyed");
+}
+
+void
+Thread::run() {
+}
+
+void
+Thread::start() {
+  Lock l(mutex);
+  if (state == ThreadCreated) {
+    state = ThreadStarted;
+    sig->signal();
+    ResumeThread(thread);
+  }
+}
+
+Thread*
+Thread::join() {
+  if (deleteAfterRun)
+    throw rdr::Exception("attempt to join() with deleteAfterRun thread");
+  Lock l(mutex);
+  if (state == ThreadJoined) {
+    logAction(this, "already joined");
+  } else {
+    logAction(this, "joining");
+    while (state == ThreadStarted) {
+      sig->wait();
+      logAction(this, "checking");
+    }
+    state = ThreadJoined;
+    logAction(this, "joined");
+  }
+  return this;
+}
+
+const char*
+Thread::getName() const {
+  return name.buf;
+}
+
+ThreadState
+Thread::getState() const {
+  return state;
+}
+
+unsigned long
+Thread::getThreadId() const {
+  return thread_id;
+}
+
+
+Thread*
+Thread::self() {
+  Thread* thread = (Thread*) TlsGetValue(threadStorage);
+  if (!thread) {
+    // *** memory leak - could use GetExitCodeThread to lazily detect when
+    //     to clean up native thread objects
+    thread = new Thread(GetCurrentThread(), GetCurrentThreadId());
+    TlsSetValue(threadStorage, thread);
+  }
+  return thread;
+}