Replace Windows specific thread handling
Use the platform independent primitives instead.
diff --git a/win/rfb_win32/CMakeLists.txt b/win/rfb_win32/CMakeLists.txt
index 047b0d8..305247a 100644
--- a/win/rfb_win32/CMakeLists.txt
+++ b/win/rfb_win32/CMakeLists.txt
@@ -22,7 +22,6 @@
SInput.cxx
SocketManager.cxx
TCharArray.cxx
- Threading.cxx
TsSessions.cxx
Win32Util.cxx
WMCursor.cxx
diff --git a/win/rfb_win32/Clipboard.h b/win/rfb_win32/Clipboard.h
index 498f75f..3da7bfc 100644
--- a/win/rfb_win32/Clipboard.h
+++ b/win/rfb_win32/Clipboard.h
@@ -25,7 +25,6 @@
#define __RFB_WIN32_CLIPBOARD_H__
#include <rfb/SDesktop.h>
-#include <rfb/Threading.h>
#include <rfb_win32/MsgWindow.h>
#include <rfb_win32/DeviceFrameBuffer.h>
diff --git a/win/rfb_win32/RegConfig.cxx b/win/rfb_win32/RegConfig.cxx
index 30cb310..5c89e78 100644
--- a/win/rfb_win32/RegConfig.cxx
+++ b/win/rfb_win32/RegConfig.cxx
@@ -85,30 +85,29 @@
}
-RegConfigThread::RegConfigThread() : Thread("RegConfigThread"), config(&eventMgr) {
+RegConfigThread::RegConfigThread() : config(&eventMgr), thread_id(-1) {
}
RegConfigThread::~RegConfigThread() {
- join();
+ PostThreadMessage(thread_id, WM_QUIT, 0, 0);
+ wait();
}
bool RegConfigThread::start(const HKEY rootKey, const TCHAR* keyname) {
if (config.setKey(rootKey, keyname)) {
Thread::start();
+ while (thread_id == (DWORD)-1)
+ Sleep(0);
return true;
}
return false;
}
-void RegConfigThread::run() {
+void RegConfigThread::worker() {
DWORD result = 0;
MSG msg;
+ thread_id = GetCurrentThreadId();
while ((result = eventMgr.getMessage(&msg, 0, 0, 0)) > 0) {}
if (result < 0)
throw rdr::SystemException("RegConfigThread failed", GetLastError());
}
-
-Thread* RegConfigThread::join() {
- PostThreadMessage(getThreadId(), WM_QUIT, 0, 0);
- return Thread::join();
-}
diff --git a/win/rfb_win32/RegConfig.h b/win/rfb_win32/RegConfig.h
index e9c01b1..c092090 100644
--- a/win/rfb_win32/RegConfig.h
+++ b/win/rfb_win32/RegConfig.h
@@ -24,7 +24,8 @@
#ifndef __RFB_WIN32_REG_CONFIG_H__
#define __RFB_WIN32_REG_CONFIG_H__
-#include <rfb/Threading.h>
+#include <os/Thread.h>
+
#include <rfb/Configuration.h>
#include <rfb_win32/Registry.h>
#include <rfb_win32/EventManager.h>
@@ -63,7 +64,7 @@
RegKey key;
};
- class RegConfigThread : Thread {
+ class RegConfigThread : os::Thread {
public:
RegConfigThread();
~RegConfigThread();
@@ -71,10 +72,10 @@
// Start the thread, reading from the specified key
bool start(const HKEY rootkey, const TCHAR* keyname);
protected:
- void run();
- Thread* join();
+ virtual void worker();
EventManager eventMgr;
RegConfig config;
+ DWORD thread_id;
};
};
diff --git a/win/rfb_win32/Service.cxx b/win/rfb_win32/Service.cxx
index d054ce4..719c44b 100644
--- a/win/rfb_win32/Service.cxx
+++ b/win/rfb_win32/Service.cxx
@@ -22,7 +22,7 @@
#include <rfb_win32/MsgWindow.h>
#include <rfb_win32/ModuleFileName.h>
#include <rfb_win32/Registry.h>
-#include <rfb/Threading.h>
+#include <rfb_win32/Handle.h>
#include <logmessages/messages.h>
#include <rdr/Exception.h>
#include <rfb/LogWriter.h>
diff --git a/win/rfb_win32/Threading.cxx b/win/rfb_win32/Threading.cxx
deleted file mode 100644
index 5873b58..0000000
--- a/win/rfb_win32/Threading.cxx
+++ /dev/null
@@ -1,151 +0,0 @@
-/* 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(%p)", action, t->getName(), t);
-}
-
-inline void logError(Thread* t, const char* err) {
- vlog.error("%-16.16s %s(%p):%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_) :
- thread(thread_), thread_id(thread_id_), name(strDup("Native")), sig(0), deleteAfterRun(false) {
- 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;
-}
diff --git a/win/rfb_win32/Threading.h b/win/rfb_win32/Threading.h
deleted file mode 100644
index 70bef41..0000000
--- a/win/rfb_win32/Threading.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* 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_win32.h
-// Win32 Threading interface implementation
-
-#ifndef __RFB_THREADING_IMPL_WIN32
-#define __RFB_THREADING_IMPL_WIN32
-
-#define __RFB_THREADING_IMPL WIN32
-
-#include <rfb_win32/Handle.h>
-#include <rfb/util.h>
-#include <rdr/Exception.h>
-//#include <stdio.h>
-
-
-namespace rfb {
- class Condition;
-
- class Mutex {
- public:
- Mutex() {
- InitializeCriticalSection(&crit);
- }
- ~Mutex() {
- DeleteCriticalSection(&crit);
- }
- friend class Lock;
- friend class Condition;
- protected:
- void enter() {EnterCriticalSection(&crit);}
- void exit() {LeaveCriticalSection(&crit);}
- CRITICAL_SECTION crit;
- };
-
- class Lock {
- public:
- Lock(Mutex& m) : mutex(m) {m.enter();}
- ~Lock() {mutex.exit();}
- protected:
- Mutex& mutex;
- };
-
- enum ThreadState {ThreadCreated, ThreadStarted, ThreadStopped, ThreadJoined, ThreadNative};
-
- class Thread {
- public:
- Thread(const char* name_=0);
- virtual ~Thread();
-
- virtual void run();
-
- virtual void start();
- virtual Thread* join();
-
- const char* getName() const;
- ThreadState getState() const;
-
- // Determines whether the thread should delete itself when run() returns
- // If you set this, you must NEVER call join()!
- void setDeleteAfterRun() {deleteAfterRun = true;};
-
- unsigned long getThreadId() const;
-
- static Thread* self();
-
- friend class Condition;
-
- protected:
- Thread(HANDLE thread_, DWORD thread_id_);
- static DWORD WINAPI threadProc(LPVOID lpParameter);
-
- win32::Handle thread;
- DWORD thread_id;
- CharArray name;
- ThreadState state;
- Condition* sig;
- Mutex mutex;
-
- win32::Handle cond_event;
- Thread* cond_next;
-
- bool deleteAfterRun;
- };
-
- class Condition {
- public:
- Condition(Mutex& m) : mutex(m), waiting(0) {
- }
- ~Condition() {
- }
-
- // Wake up the specified number of threads that are waiting
- // on this Condition, or all of them if -1 is specified.
- void signal(int howMany=1) {
- Lock l(cond_lock);
- while (waiting && howMany!=0) {
- SetEvent(waiting->cond_event);
- waiting = waiting->cond_next;
- if (howMany>0) --howMany;
- }
- }
-
- // NB: Must hold "mutex" to call wait()
- // Wait until either the Condition is signalled or the timeout
- // expires.
- void wait(DWORD timeout=INFINITE) {
- Thread* self = Thread::self();
- ResetEvent(self->cond_event);
- { Lock l(cond_lock);
- self->cond_next = waiting;
- waiting = self;
- }
- mutex.exit();
- DWORD result = WaitForSingleObject(self->cond_event, timeout);
- mutex.enter();
- if (result == WAIT_TIMEOUT) {
- Lock l(cond_lock);
- // Remove this thread from the Condition
- for (Thread** removeFrom = &waiting; *removeFrom; removeFrom = &(*removeFrom)->cond_next) {
- if (*removeFrom == self) {
- *removeFrom = self->cond_next;
- break;
- }
- }
- } else if (result == WAIT_FAILED) {
- throw rdr::SystemException("failed to wait on Condition", GetLastError());
- }
- }
-
- protected:
- Mutex& mutex;
- Mutex cond_lock;
- Thread* waiting;
- };
-
-};
-
-#endif // __RFB_THREADING_IMPL
diff --git a/win/rfb_win32/WMHooks.cxx b/win/rfb_win32/WMHooks.cxx
index 0e5e70a..bbc1508 100644
--- a/win/rfb_win32/WMHooks.cxx
+++ b/win/rfb_win32/WMHooks.cxx
@@ -18,11 +18,13 @@
// -=- WMHooks.cxx
+#include <os/Mutex.h>
+#include <os/Thread.h>
+
#include <rfb_win32/WMHooks.h>
#include <rfb_win32/Service.h>
#include <rfb_win32/MsgWindow.h>
#include <rfb_win32/IntervalTimer.h>
-#include <rfb/Threading.h>
#include <rfb/LogWriter.h>
#include <list>
@@ -108,20 +110,21 @@
}
-class WMHooksThread : public Thread {
+class WMHooksThread : public os::Thread {
public:
- WMHooksThread() : Thread("WMHookThread"),
- active(true) {
- }
- virtual void run();
- virtual Thread* join();
+ WMHooksThread() : active(true), thread_id(-1) { }
+ void stop();
+ DWORD getThreadId() { return thread_id; }
+protected:
+ virtual void worker();
protected:
bool active;
+ DWORD thread_id;
};
static WMHooksThread* hook_mgr = 0;
static std::list<WMHooks*> hooks;
-static Mutex hook_mgr_lock;
+static os::Mutex hook_mgr_lock;
static bool StartHookThread() {
@@ -131,15 +134,17 @@
return false;
vlog.debug("creating thread");
hook_mgr = new WMHooksThread();
+ hook_mgr->start();
+ while (hook_mgr->getThreadId() == (DWORD)-1)
+ Sleep(0);
vlog.debug("installing hooks");
if (!WM_Hooks_Install(hook_mgr->getThreadId(), 0)) {
vlog.error("failed to initialise hooks");
- delete hook_mgr->join();
+ hook_mgr->stop();
+ delete hook_mgr;
hook_mgr = 0;
return false;
}
- vlog.debug("starting thread");
- hook_mgr->start();
return true;
}
@@ -149,14 +154,15 @@
if (!hooks.empty())
return;
vlog.debug("closing thread");
- delete hook_mgr->join();
+ hook_mgr->stop();
+ delete hook_mgr;
hook_mgr = 0;
}
static bool AddHook(WMHooks* hook) {
vlog.debug("adding hook");
- Lock l(hook_mgr_lock);
+ os::AutoMutex a(&hook_mgr_lock);
if (!StartHookThread())
return false;
hooks.push_back(hook);
@@ -166,7 +172,7 @@
static bool RemHook(WMHooks* hook) {
{
vlog.debug("removing hook");
- Lock l(hook_mgr_lock);
+ os::AutoMutex a(&hook_mgr_lock);
hooks.remove(hook);
}
StopHookThread();
@@ -174,7 +180,7 @@
}
static void NotifyHooksRegion(const Region& r) {
- Lock l(hook_mgr_lock);
+ os::AutoMutex a(&hook_mgr_lock);
std::list<WMHooks*>::iterator i;
for (i=hooks.begin(); i!=hooks.end(); i++)
(*i)->NotifyHooksRegion(r);
@@ -182,7 +188,7 @@
void
-WMHooksThread::run() {
+WMHooksThread::worker() {
// Obtain message ids for all supported hook messages
UINT windowMsg = WM_Hooks_WindowChanged();
UINT clientAreaMsg = WM_Hooks_WindowClientAreaChanged();
@@ -208,6 +214,8 @@
vlog.debug("starting hook thread");
+ thread_id = GetCurrentThreadId();
+
while (active && GetMessage(&msg, NULL, 0, 0)) {
count++;
@@ -283,13 +291,13 @@
WM_Hooks_Remove(getThreadId());
}
-Thread*
-WMHooksThread::join() {
+void
+WMHooksThread::stop() {
vlog.debug("stopping WMHooks thread");
active = false;
PostThreadMessage(thread_id, WM_QUIT, 0, 0);
- vlog.debug("joining WMHooks thread");
- return Thread::join();
+ vlog.debug("waiting for WMHooks thread");
+ wait();
}
// -=- WMHooks class
@@ -311,7 +319,7 @@
bool rfb::win32::WMHooks::getUpdates(UpdateTracker* ut) {
if (!updatesReady) return false;
- Lock l(hook_mgr_lock);
+ os::AutoMutex a(&hook_mgr_lock);
updates.copyTo(ut);
updates.clear();
updatesReady = false;
@@ -363,12 +371,12 @@
return block_ == blocking;
}
-Mutex blockMutex;
-int blockCount = 0;
+static os::Mutex blockMutex;
+static int blockCount = 0;
bool rfb::win32::WMBlockInput::blockInputs(bool on) {
if (active == on) return true;
- Lock l(blockMutex);
+ os::AutoMutex a(&blockMutex);
int newCount = on ? blockCount+1 : blockCount-1;
if (!blockRealInputs(newCount > 0))
return false;
diff --git a/win/rfb_win32/WMNotifier.h b/win/rfb_win32/WMNotifier.h
index ada45d0..3855430 100644
--- a/win/rfb_win32/WMNotifier.h
+++ b/win/rfb_win32/WMNotifier.h
@@ -28,7 +28,6 @@
#define __RFB_WIN32_NOTIFIER_H__
#include <rfb/SDesktop.h>
-#include <rfb/Threading.h>
#include <rfb_win32/MsgWindow.h>
#include <rfb_win32/DeviceFrameBuffer.h>
#include <rfb_win32/SInput.h>