Author Topic: Thread Local Storage (MSDN Example)  (Read 3052 times)

0 Members and 1 Guest are viewing this topic.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Thread Local Storage (MSDN Example)
« on: May 11, 2021, 07:23:26 pm »
This code comes from the MSDN page on Using Thread Local Storage.
Quote from: MSDN
Thread local storage (TLS) enables multiple threads of the same process to use an index allocated by the TlsAlloc function to store and retrieve a value that is local to the thread. In this example, an index is allocated when the process starts. When each thread starts, it allocates a block of dynamic memory and stores a pointer to this memory in the TLS slot using the TlsSetValue function. The CommonFunc function uses the TlsGetValue function to access the data associated with the index that is local to the calling thread. Before each thread terminates, it releases its dynamic memory. Before the process terminates, it calls TlsFree to release the index.

A couple of headers are required:
Code: C++: [Select]
  1. //save as stderr.h
  2. FILE *stderrf (){
  3.     return stderr;
  4. }
Code: C++: [Select]
  1. //save as threadfunc.h
  2. #include<strsafe.h>
  3. int32 FUNC_THREADFUNC();
  4. extern "C"{
  5.         __declspec(dllexport) int32 ThreadFunc(){
  6.                 return FUNC_THREADFUNC();
  7.         }
  8. }

And the QB64 code:
Code: QB64: [Select]
  1.  
  2. Const THREADCOUNT = 4
  3. Const ERROR_SUCCESS = 0
  4. Const LPTR = &H0040
  5. Const TLS_OUT_OF_INDEXES = &HFFFFFFFF
  6. Const INFINITE = 4294967295
  7.  
  8.     Function LoadLibrary%& (lpLibFileName As String)
  9.     Function GetProcAddress%& (ByVal hModule As _Offset, lpProcName As String)
  10.     Sub FreeLibrary (ByVal hLibModule As _Offset)
  11.     Sub fprintf (ByVal stream As _Offset, format As String, argument As String)
  12.     Sub ExitProcess (ByVal uExitCode As _Unsigned Long)
  13.     Function TlsGetValue%& (ByVal dwTlsIndex As Long)
  14.     Function TlsSetValue%% (ByVal dwTlsIndex As Long, Byval lpTlsValue As _Offset)
  15.     Function TlsAlloc& ()
  16.     Sub TlsFree (ByVal dwTlsIndex As Long)
  17.     Function GetLastError& ()
  18.     Function GetCurrentThreadId& ()
  19.     Sub printf (format As String, Byval dwarg As Long, Byval lparg As _Offset)
  20.     Function CreateThread%& (ByVal lpThreadAttributes As _Offset, Byval dwStackSize As _Offset, Byval lpStartAddress As _Offset, Byval lpParameter As _Offset, Byval dwCreationFlags As Long, Byval lpThreadId As _Offset)
  21.     Function LocalAlloc%& (ByVal uFlags As _Unsigned Long, Byval uBytes As _Unsigned _Offset)
  22.     Sub LocalFree (ByVal hMem As _Offset)
  23.     Function CreateMutex%& Alias "CreateMutexA" (ByVal lpMutexAttributes As _Offset, Byval bInitialOwner As Long, Byval lpName As _Offset)
  24.     Sub WaitForSingleObject (ByVal hHandle As _Offset, Byval dwMilliseconds As Long)
  25.     Sub CloseHandle (ByVal hObject As _Offset)
  26.  
  27.     Function stderr%& Alias "stderrf" ()
  28.  
  29. Declare Library "threadfunc"
  30.  
  31. Dim Shared As Long dwTlsIndex
  32. Dim As Long IDThread, i
  33. Dim As _Offset hThread(1 To THREADCOUNT)
  34.  
  35. Dim As _Offset libload: libload = LoadLibrary(Command$(0))
  36. Dim As _Offset pThreadFunc: pThreadFunc = GetProcAddress(libload, "ThreadFunc")
  37.  
  38. 'Allocate a TLS index
  39.  
  40. dwTlsIndex = TlsAlloc
  41. If dwTlsIndex = TLS_OUT_OF_INDEXES Then _
  42.     ErrorExit "TlsAlloc failed"
  43.  
  44. 'Create multiple threads
  45.  
  46. For i = 1 To THREADCOUNT
  47.     hThread(i) = CreateThread(0,_
  48.        0,_
  49.         pThreadFunc,_
  50.        0,_
  51.        0,_
  52.         _Offset(IDThread))
  53.  
  54.     'Check the return value for success
  55.     If hThread(i) = 0 Then _
  56.         ErrorExit "CreateThread error"
  57.  
  58. For i = 1 To THREADCOUNT
  59.     WaitForSingleObject hThread(i), INFINITE
  60.  
  61. TlsFree dwTlsIndex
  62. FreeLibrary libload
  63.  
  64. Sub CommonFunc ()
  65.     Dim As _Offset lpvData
  66.  
  67.     'Retrieve a data pointer for the current thread
  68.  
  69.     lpvData = TlsGetValue(dwTlsIndex)
  70.     If lpvData = 0 And GetLastError <> ERROR_SUCCESS Then _
  71.         ErrorExit "TlsGetValue error"
  72.  
  73.     'Use the data stored for the current thread
  74.  
  75.     printf "common: thread %d: lpvData=%lx" + Chr$(10) + Chr$(0), GetCurrentThreadId, lpvData
  76.     Sleep 5
  77.  
  78. Function ThreadFunc& ()
  79.     Dim As _Offset lpvData
  80.  
  81.     'Initialize the TLS index for this thread
  82.  
  83.     lpvData = LocalAlloc(LPTR, 256)
  84.     If TlsSetValue(dwTlsIndex, lpvData) = 0 Then _
  85.         ErrorExit "TlsSetValue error"
  86.  
  87.     printf "thread %d: lpvData=%lx" + Chr$(10) + Chr$(0), GetCurrentThreadId, lpvData
  88.  
  89.     CommonFunc
  90.  
  91.     'Release the dynamic memory before the thread returns
  92.  
  93.     lpvData = TlsGetValue(dwTlsIndex)
  94.     If lpvData <> 0 Then _
  95.         LocalFree lpvData
  96.  
  97.     ThreadFunc = 0
  98.  
  99. Sub ErrorExit (message As String)
  100.     fprintf stderr, "%s" + Chr$(10) + Chr$(0), message + Chr$(0)
  101.     ExitProcess 0

 
Screenshot 2021-05-11 192251.png
« Last Edit: May 11, 2021, 09:54:48 pm by SpriggsySpriggs »
Shuwatch!