|
Boost : |
From: David Deakins (ddeakins_at_[hidden])
Date: 2007-11-01 16:19:44
Attached are some Windows CE patches for the thread rewrite code:
- boost\thread\win32\thread_primitives.hpp:
Windows CE does not supply the ANSI version of most Win32 functions
(only the wide-char versions). In addition, on WinCE certain functions
like GetCurrentThread, GetCurrentProcess, SetEvent, ResetEvent, and a
couple others are inline functions declared in the kfuncs.h header file
(rather than functions imported from the Win32 DLLs). The patch
implements workarounds for these issues.
- boost\thread\win32\thread_heap_alloc.hpp:
In DEBUG debugs, Windows CE headers define a macro for HeapAlloc to
remap it to a HeapAllocTrace function. This wreaks havoc on the code to
pull HeapAlloc into Boost.Thread's win32 namespace. At this point, the
best solution I could see was to undef this HeapAlloc macro if present.
- libs\thread\src\win32\thread.cpp:
Windows CE does not have a process.h header. It also does not support
the __declspec(thread) construct. Finally, _beginthreadex is not part
of the WinCE CRT so an emulation of this function using ::CreateThread
is included in the patch.
- libs\thread\src\win32\tss.cpp:
- libs\thread\src\win32\tss_hooks.cpp:
Windows CE does not define the TLS_OUT_OF_INDEXES constant. The patch
defines this constant to the right value for WinCE builds.
- libs\thread\src\tss_null.cpp:
- libs\thread\src\win32\tss_pe.cpp:
The Windows CE linker and loader do not seem to support all the fancy
magic involved in registering the TSS callback handler with the
static-link version of the library (DLL version works fine). The patch
reflects that automatic tss cleanup is not available in WinCE version of
the static-link library.
Thanks,
-Dave
Index: thread_heap_alloc.hpp
===================================================================
--- thread_heap_alloc.hpp (revision 40640)
+++ thread_heap_alloc.hpp (working copy)
@@ -25,6 +25,10 @@
#else
+#ifdef HeapAlloc
+#undef HeapAlloc
+#endif
+
namespace boost
{
namespace detail
Index: thread_primitives.hpp
===================================================================
--- thread_primitives.hpp (revision 40611)
+++ thread_primitives.hpp (working copy)
@@ -28,9 +28,15 @@
unsigned const timeout=WAIT_TIMEOUT;
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
+# ifdef BOOST_NO_ANSI_APIS
+ using ::CreateMutexW;
+ using ::CreateEventW;
+ using ::CreateSemaphoreW;
+# else
using ::CreateMutexA;
using ::CreateEventA;
using ::CreateSemaphoreA;
+# endif
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
@@ -50,6 +56,29 @@
}
}
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
+
+# ifdef UNDER_CE
+# ifndef WINAPI
+# ifndef _WIN32_WCE_EMULATION
+# define WINAPI __cdecl // Note this doesn't match the desktop definition
+# else
+# define WINAPI __stdcall
+# endif
+# endif
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+typedef int BOOL;
+typedef unsigned long DWORD;
+typedef void* HANDLE;
+
+# include <kfuncs.h>
+# ifdef __cplusplus
+}
+# endif
+# endif
+
namespace boost
{
namespace detail
@@ -70,25 +99,42 @@
extern "C"
{
struct _SECURITY_ATTRIBUTES;
+# ifdef BOOST_NO_ANSI_APIS
+ __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
+ __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
+ __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
+# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
+# endif
+
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
- __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
- __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
+ __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
- __declspec(dllimport) void* __stdcall GetCurrentThread();
- __declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
__declspec(dllimport) void __stdcall Sleep(unsigned long);
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
+
+# ifndef UNDER_CE
+ __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
+ __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
+ __declspec(dllimport) void* __stdcall GetCurrentThread();
+ __declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall SetEvent(void*);
__declspec(dllimport) int __stdcall ResetEvent(void*);
- __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
+# else
+ using ::GetCurrentProcessId;
+ using ::GetCurrentThreadId;
+ using ::GetCurrentThread;
+ using ::GetCurrentProcess;
+ using ::SetEvent;
+ using ::ResetEvent;
+# endif
}
}
}
@@ -117,7 +163,11 @@
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
+#if !defined(BOOST_NO_ANSI_APIS)
handle const res=win32::CreateEventA(0,type,state,0);
+#else
+ handle const res=win32::CreateEventW(0,type,state,0);
+#endif
if(!res)
{
throw thread_resource_error();
@@ -127,7 +177,11 @@
inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
+#if !defined(BOOST_NO_ANSI_APIS)
handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL);
+#else
+ handle const res=CreateSemaphoreW(NULL,initial_count,max_count,NULL);
+#endif
if(!res)
{
throw thread_resource_error();
Index: tss.cpp
===================================================================
--- tss.cpp (revision 40611)
+++ tss.cpp (working copy)
@@ -20,6 +20,9 @@
#if defined(BOOST_HAS_WINTHREADS)
# include <windows.h>
# include <boost/thread/detail/tss_hooks.hpp>
+# if defined(UNDER_CE) && !defined(TLS_OUT_OF_INDEXES)
+# define TLS_OUT_OF_INDEXES 0xFFFFFFFF
+# endif
#endif
namespace {
Index: tss_hooks.cpp
===================================================================
--- tss_hooks.cpp (revision 40611)
+++ tss_hooks.cpp (working copy)
@@ -19,6 +19,10 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+# if defined(UNDER_CE) && !defined(TLS_OUT_OF_INDEXES)
+# define TLS_OUT_OF_INDEXES 0xFFFFFFFF
+# endif
+
namespace
{
class CScopedCSLock
Index: tss_pe.cpp
===================================================================
--- tss_pe.cpp (revision 40611)
+++ tss_pe.cpp (working copy)
@@ -5,7 +5,7 @@
#include <boost/thread/detail/config.hpp>
-#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && defined(_MSC_VER)
+#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && defined(_MSC_VER) && !defined(UNDER_CE)
#include <boost/thread/detail/tss_hooks.hpp>
Index: thread.cpp
===================================================================
--- thread.cpp (revision 40611)
+++ thread.cpp (working copy)
@@ -6,7 +6,9 @@
#include <boost/thread/thread.hpp>
#include <algorithm>
#include <windows.h>
+#ifndef UNDER_CE
#include <process.h>
+#endif
#include <stdio.h>
#include <boost/thread/once.hpp>
#include <boost/assert.hpp>
@@ -15,7 +17,7 @@
{
namespace
{
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(UNDER_CE)
__declspec(thread) detail::thread_data_base* current_thread_data=0;
detail::thread_data_base* get_current_thread_data()
{
@@ -59,6 +61,42 @@
BOOST_ASSERT(res);
}
#endif
+
+
+#ifdef BOOST_NO_THREADEX
+// Windows CE doesn't define _beginthreadex
+
+ struct ThreadProxyData
+ {
+ typedef unsigned (__stdcall* func)(void*);
+ func start_address_;
+ void* arglist_;
+ ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {}
+ };
+
+ DWORD WINAPI ThreadProxy(LPVOID args)
+ {
+ ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
+ DWORD ret=data->start_address_(data->arglist_);
+ delete data;
+ return ret;
+ }
+
+ typedef void* uintptr_t;
+
+ inline uintptr_t const _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
+ void* arglist, unsigned initflag, unsigned* thrdaddr)
+ {
+ DWORD threadID;
+ HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
+ new ThreadProxyData(start_address,arglist),initflag,&threadID);
+ if (hthread!=0)
+ *thrdaddr=threadID;
+ return reinterpret_cast<uintptr_t const>(hthread);
+ }
+
+#endif
+
}
void thread::yield()
@@ -170,7 +208,6 @@
}
~externally_launched_thread()
{
- OutputDebugString("External thread finished\n");
}
void run()
Index: tss_null.cpp
===================================================================
--- tss_null.cpp (revision 40640)
+++ tss_null.cpp (working copy)
@@ -5,7 +5,7 @@
#include <boost/thread/detail/config.hpp>
-#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST)) && !defined(_MSC_VER)
+#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST)) && !(defined(_MSC_VER) && !defined(UNDER_CE))
/*
This file is a "null" implementation of tss cleanup; it's
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk