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),它可能更易于使用。它可能映射到相同的功能。