ThreadLocalValueImpl.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #pragma once
  2. #include "il2cpp-config.h"
  3. #if IL2CPP_THREADS_WIN32
  4. #include "os/c-api/il2cpp-config-platforms.h"
  5. #include "os/ErrorCodes.h"
  6. #include "utils/NonCopyable.h"
  7. // We declare windows APIs here instead of including windows system headers
  8. // to avoid leaking windows system headers to all of il2cpp and il2cpp-generated
  9. // code.
  10. // On UWP, old Windows SDKs (10586 and older) did not have support for Tls* functions
  11. // so instead we used forwarded them to Fls* equivalents. Using Tls* functions directly
  12. // with these old SDKs causes linker errors.
  13. #define IL2CPP_USE_WINRT_FLS_WORKAROUND (IL2CPP_TARGET_WINRT && WINDOWS_SDK_BUILD_VERSION <= 10586)
  14. #if !IL2CPP_USE_WINRT_FLS_WORKAROUND
  15. extern "C" {
  16. __declspec(dllimport) unsigned long __stdcall TlsAlloc(void);
  17. __declspec(dllimport) void* __stdcall TlsGetValue(unsigned long dwTlsIndex);
  18. __declspec(dllimport) int __stdcall TlsSetValue(unsigned long dwTlsIndex, void* lpTlsValue);
  19. __declspec(dllimport) int __stdcall TlsFree(unsigned long dwTlsIndex);
  20. __declspec(dllimport) unsigned long __stdcall GetLastError(void);
  21. }
  22. #else
  23. extern "C" {
  24. typedef void (__stdcall* PFLS_CALLBACK_FUNCTION)(void* lpFlsData);
  25. __declspec(dllimport) unsigned long __stdcall FlsAlloc(PFLS_CALLBACK_FUNCTION callback);
  26. __declspec(dllimport) void* __stdcall FlsGetValue(unsigned long dwTlsIndex);
  27. __declspec(dllimport) int __stdcall FlsSetValue(unsigned long dwTlsIndex, void* lpTlsValue);
  28. __declspec(dllimport) int __stdcall FlsFree(unsigned long dwTlsIndex);
  29. __declspec(dllimport) unsigned long __stdcall GetLastError(void);
  30. }
  31. #define TlsAlloc() FlsAlloc(NULL)
  32. #define TlsGetValue FlsGetValue
  33. #define TlsSetValue FlsSetValue
  34. #define TlsFree FlsFree
  35. #endif
  36. #define IL2CPP_TLS_OUT_OF_INDEXES ((unsigned long)0xFFFFFFFF)
  37. namespace il2cpp
  38. {
  39. namespace os
  40. {
  41. class ThreadLocalValueImpl : public il2cpp::utils::NonCopyable
  42. {
  43. public:
  44. inline ThreadLocalValueImpl()
  45. {
  46. m_Index = TlsAlloc();
  47. IL2CPP_ASSERT(m_Index != IL2CPP_TLS_OUT_OF_INDEXES);
  48. }
  49. inline ~ThreadLocalValueImpl()
  50. {
  51. bool success = TlsFree(m_Index);
  52. NO_UNUSED_WARNING(success);
  53. IL2CPP_ASSERT(success);
  54. }
  55. inline ErrorCode SetValue(void* value)
  56. {
  57. if (TlsSetValue(m_Index, value) == false)
  58. return static_cast<ErrorCode>(GetLastError());
  59. return kErrorCodeSuccess;
  60. }
  61. inline ErrorCode GetValue(void** value)
  62. {
  63. *value = TlsGetValue(m_Index);
  64. if (*value)
  65. return kErrorCodeSuccess;
  66. unsigned long lastError = GetLastError();
  67. if (lastError == 0)
  68. return kErrorCodeSuccess;
  69. return static_cast<ErrorCode>(lastError);
  70. }
  71. private:
  72. unsigned long m_Index;
  73. };
  74. }
  75. }
  76. #if IL2CPP_USE_WINRT_FLS_WORKAROUND
  77. #undef TlsAlloc
  78. #undef TlsGetValue
  79. #undef TlsSetValue
  80. #undef TlsFree
  81. #endif
  82. #endif // IL2CPP_THREADS_WIN32