Moshe Rubin
Moshe Rubin

Reputation: 1982

Does WinRT _really_ support thread local storage functions (Tls*)?

I'm porting legacy Windows code to Windows Runtime (WinRT), specifically Windows Phone 8.1. The code contains calls to thread local storage functions like TlsAlloc, TlsFree, TlsGetValue, and TlsSetValue. According to MSDN's "Win32 and COM for Windows Runtime apps (system)" page, these four TLS functions are supported under WinRT. Reading the TlsAlloc documentation, for example, one reads:

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.

When I #include the indicated header file, Processthreadsapi.h, in my legacy code, the compile fails:

error C2039: 'TlsAlloc' : is not a member of '`global namespace''

Examining Processthreadsapi.h shows why it doesn't help me:

/***********************************************************************************
*                                                                                  *
* 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) */
. . .

The problem is clear: WinRT belongs to the world of WINAPI_PARTITION_APP, not WINAPI_PARTITION_DESKTOP. Therefore, when I compile my app for WinRT, I do not get any of these symbols and function declarations.

Is this only a Windows header problem, where MS should have included the Tls* functions for WinRT? Or is thread local storage not supported for WinRT, contrary to the documentation?

Upvotes: 1

Views: 761

Answers (3)

CÅdahl
CÅdahl

Reputation: 542

An alternative is __declspec(thread), which may be easier to use. It likely maps to the same functionality.

Upvotes: 0

Peter Torr
Peter Torr

Reputation: 12019

This is only added in VS 2013 Update 4. If you have an earlier install (including Update 4 RC) you won't have the updated headers.

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 941455

Yes, it truly does. Copy/pasted from c:\Program Files (x86)\Windows Phone Kits\8.1\Include\minwin\processthreadsapi.h, line #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..

The file that you describe is the 8.0 version of the file. No idea how this happened of course. Perhaps you have an early beta, perhaps you copied files to solve a problem. The landing page is here, I did download the 8.1 Update 1 emulators but don't know if that also updated the SDK headers.

Upvotes: 1

Related Questions