WinRT _真的_支持线程本地存储函数 (Tls*) 吗?
Does WinRT _really_ support thread local storage functions (Tls*)?
我正在将遗留 Windows 代码移植到 Windows 运行时 (WinRT),特别是 Windows Phone 8.1。该代码包含对线程本地存储函数(如 TlsAlloc、TlsFree、TlsGetValue 和 TlsSetValue)的调用。根据 MSDN 的 "Win32 and COM for Windows Runtime apps (system)" page, these four TLS functions are supported under WinRT. Reading the TlsAlloc documentation,例如,一个是:
Windows Phone 8.1: This function is supported for Windows Phone Store
apps on Windows Phone 8.1 and later. When a Windows Phone Store app
calls this function, it is replaced with an inline call to FlsAlloc.
Refer to FlsAlloc for function documentation.
当我在遗留代码中#include 指示的 header 文件 Processthreadsapi.h 时,编译失败:
error C2039: 'TlsAlloc' : is not a member of '`global namespace''
检查 Processthreadsapi.h 说明了为什么它对我没有帮助:
/***********************************************************************************
* *
* processthreadsapi.h -- ApiSet Contract for api-ms-win-core-processthreads-l1 *
* *
* Copyright (c) Microsoft Corporation. All rights reserved. *
* *
***********************************************************************************/
. . .
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
. . .
#ifndef FLS_OUT_OF_INDEXES
#define FLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
#endif
#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
_Must_inspect_result_
WINBASEAPI
DWORD
WINAPI
TlsAlloc(
VOID
);
WINBASEAPI
LPVOID
WINAPI
TlsGetValue(
_In_ DWORD dwTlsIndex
);
WINBASEAPI
BOOL
WINAPI
TlsSetValue(
_In_ DWORD dwTlsIndex,
_In_opt_ LPVOID lpTlsValue
);
WINBASEAPI
BOOL
WINAPI
TlsFree(
_In_ DWORD dwTlsIndex
);
. . .
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
. . .
问题很明确:WinRT属于WINAPI_PARTITION_APP的世界,不属于WINAPI_PARTITION_DESKTOP的世界。因此,当我为 WinRT 编译我的应用程序时,我没有得到任何这些符号和函数声明。
这是否只是一个 Windows header 问题,MS 应该在其中包含 WinRT 的 Tls* 函数?或者与文档相反,WinRT 不支持线程本地存储?
是的,确实如此。 Copy/pasted 来自 c:\Program Files (x86)\Windows Phone Kits.1\Include\minwin\processthreadsapi.h,第 411 行:
// TlsAlloc, TlsFree, TlsGetValue and TlsSetValue are defined as inlines
// only for the store apps, not for desktop apps
#pragma region Application Family
#if WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
#include <fibersapi.h>
FORCEINLINE
_Must_inspect_result_
WINBASEAPI
DWORD
WINAPI
TlsAlloc(
VOID
)
{
return FlsAlloc(NULL);
}
// etc..
您描述的文件是文件的 8.0
版本。当然不知道这是怎么发生的。也许你有一个早期的测试版,也许你复制了文件来解决问题。登录页面 is here,我确实下载了 8.1 Update 1 模拟器,但不知道是否也更新了 SDK headers。
这仅在 VS 2013 Update 4 中添加。如果您有较早的安装(包括 Update 4 RC),则不会有更新的 headers。
另一种方法是 __declspec(thread),它可能更易于使用。它可能映射到相同的功能。
我正在将遗留 Windows 代码移植到 Windows 运行时 (WinRT),特别是 Windows Phone 8.1。该代码包含对线程本地存储函数(如 TlsAlloc、TlsFree、TlsGetValue 和 TlsSetValue)的调用。根据 MSDN 的 "Win32 and COM for Windows Runtime apps (system)" page, these four TLS functions are supported under WinRT. Reading the TlsAlloc documentation,例如,一个是:
Windows Phone 8.1: This function is supported for Windows Phone Store apps on Windows Phone 8.1 and later. When a Windows Phone Store app calls this function, it is replaced with an inline call to FlsAlloc. Refer to FlsAlloc for function documentation.
当我在遗留代码中#include 指示的 header 文件 Processthreadsapi.h 时,编译失败:
error C2039: 'TlsAlloc' : is not a member of '`global namespace''
检查 Processthreadsapi.h 说明了为什么它对我没有帮助:
/***********************************************************************************
* *
* processthreadsapi.h -- ApiSet Contract for api-ms-win-core-processthreads-l1 *
* *
* Copyright (c) Microsoft Corporation. All rights reserved. *
* *
***********************************************************************************/
. . .
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
. . .
#ifndef FLS_OUT_OF_INDEXES
#define FLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
#endif
#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
_Must_inspect_result_
WINBASEAPI
DWORD
WINAPI
TlsAlloc(
VOID
);
WINBASEAPI
LPVOID
WINAPI
TlsGetValue(
_In_ DWORD dwTlsIndex
);
WINBASEAPI
BOOL
WINAPI
TlsSetValue(
_In_ DWORD dwTlsIndex,
_In_opt_ LPVOID lpTlsValue
);
WINBASEAPI
BOOL
WINAPI
TlsFree(
_In_ DWORD dwTlsIndex
);
. . .
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
. . .
问题很明确:WinRT属于WINAPI_PARTITION_APP的世界,不属于WINAPI_PARTITION_DESKTOP的世界。因此,当我为 WinRT 编译我的应用程序时,我没有得到任何这些符号和函数声明。
这是否只是一个 Windows header 问题,MS 应该在其中包含 WinRT 的 Tls* 函数?或者与文档相反,WinRT 不支持线程本地存储?
是的,确实如此。 Copy/pasted 来自 c:\Program Files (x86)\Windows Phone Kits.1\Include\minwin\processthreadsapi.h,第 411 行:
// TlsAlloc, TlsFree, TlsGetValue and TlsSetValue are defined as inlines
// only for the store apps, not for desktop apps
#pragma region Application Family
#if WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
#include <fibersapi.h>
FORCEINLINE
_Must_inspect_result_
WINBASEAPI
DWORD
WINAPI
TlsAlloc(
VOID
)
{
return FlsAlloc(NULL);
}
// etc..
您描述的文件是文件的 8.0
版本。当然不知道这是怎么发生的。也许你有一个早期的测试版,也许你复制了文件来解决问题。登录页面 is here,我确实下载了 8.1 Update 1 模拟器,但不知道是否也更新了 SDK headers。
这仅在 VS 2013 Update 4 中添加。如果您有较早的安装(包括 Update 4 RC),则不会有更新的 headers。
另一种方法是 __declspec(thread),它可能更易于使用。它可能映射到相同的功能。