home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / samples / compiler / tls / tls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-20  |  6.8 KB  |  178 lines

  1. /******************************************************************************/
  2. /* TLS SAMPLE: TLS.C                                                          */
  3. /*                                                                            */
  4. /* COPYRIGHT:                                                                 */
  5. /* ----------                                                                 */
  6. /* Copyright (C) International Business Machines Corp., 1995.                 */
  7. /*                                                                            */
  8. /******************************************************************************/
  9. /*                                                                            */
  10. /*  Sample to demonstrate thread-local storage                                */
  11. /*                                                                            */
  12. /*  This program demonstrates the use of the thread-local storage capability  */
  13. /*  of the IBM VisualAge C++ compiler.                                        */
  14. /*                                                                            */
  15. /*  This sample program creates two threads.  Thread 1 will wait for          */
  16. /*  Thread 2 to be created. When Thread 2 starts, it will signal Thread 1     */
  17. /*  to resume execution. When Thread 1 resumes, it will modify the static     */
  18. /*  TLS variable "dwGlobalId" to the value of its thread id. Thread 1 then    */
  19. /*  suspends itself to wait while Thread 2 queries the value of "dwGlobalId". */
  20. /*  Thread 2 will find that its thread-local copy of "dwGlobalId" has not     */
  21. /*  not been changed by Thread 1.                                             */
  22. /*                                                                            */
  23. /*  The sample prints the following output to the screen:                     */
  24. /*                                                                            */
  25. /*       Starting main thread: dwMainId = 133  dwGlobalId = 133               */
  26. /*       Starting Thread 1: dwThread1Id = 138                                 */
  27. /*       Suspending Thread 1 to wait for Thread 2                             */
  28. /*       Starting Thread 2: dwThread2Id = 132  dwGlobalId = 132               */
  29. /*       dwGlobalId modified in Thread 1: dwGlobalId = 138                    */
  30. /*       Suspending Thread 1 for Thread 2 to check dwGlobalId                 */
  31. /*       In Thread 2 after resuming Thread 1: dwGlobalId = 132                */
  32. /*       Ending Thread 2: dwThread2Id = 132  dwGlobalId = 132                 */
  33. /*       Ending Thread 1: dwThread1Id = 138  dwGlobalId = 138                 */
  34. /*       Ending main thread: dwMainId = 133  dwGlobalId = 133                 */
  35. /*                                                                            */
  36. /******************************************************************************/
  37. #include <stdio.h>
  38. #include <process.h>
  39. #include <windows.h>
  40.  
  41.  
  42. void errorExit(LPTSTR);
  43. DWORD WINAPI threadfunc2(HANDLE);
  44. DWORD WINAPI threadfunc1(LPVOID);
  45.  
  46. /*
  47.  * Static TLS variable
  48.  */
  49. __thread DWORD dwGlobalId;
  50.  
  51. /*
  52.  * Function executed by Thread 1. Will wait for Thread 2 to begin, then
  53.  * modify the static TLS variable to the value of its thread id. The function
  54.  * will then wait for Thread 2 to check the value of the TLS variable before
  55.  * completing.
  56.  */
  57. DWORD WINAPI threadfunc1(LPVOID lpvParm)
  58. {
  59.    DWORD  dwThread1Id, dwRc;
  60.    HANDLE hThread1;
  61.  
  62.    dwThread1Id = GetCurrentThreadId();
  63.    printf("Starting Thread 1: dwThread1Id = %u\n", dwThread1Id);
  64.    hThread1 = GetCurrentThread();
  65.  
  66.    /* Wait for Thread 2 to begin  */
  67.  
  68.    printf("Suspending Thread 1 to wait for Thread 2\n");
  69.    dwRc = SuspendThread(hThread1);
  70.    if (dwRc != 0)
  71.       errorExit("Error: Suspend thread failed\n");
  72.  
  73.    /* Modify the static TLS variable to the id of Thread 1 */
  74.  
  75.    dwGlobalId = dwThread1Id;
  76.  
  77.    printf("dwGlobalId modified in Thread 1: dwGlobalId = %u\n", dwGlobalId);
  78.    printf("Suspending Thread 1 for Thread 2 to check dwGlobalId\n");
  79.  
  80.    /* Wait for Thread 2 to check the value of the TLS variable */
  81.  
  82.    dwRc = SuspendThread(hThread1);
  83.    if (dwRc != 0)
  84.       errorExit("Error: Suspend thread failed\n");
  85.    printf("Ending Thread 1: dwThread1Id = %u  dwGlobalId = %u\n", dwThread1Id, dwGlobalId);
  86.  
  87.    return(0);
  88. }
  89.  
  90. /*
  91.  * Function executed by Thread 2. When Thread 2 begins, Thread 1 is suspended
  92.  * waiting for Thread 2. Resume Thread 1. Thread 1 will then modify the TLS
  93.  * variable and suspend itself waiting for Thread 2 to print the value. Once
  94.  * The TLS variable has been printed, resume Thread 1.
  95.  */
  96.  
  97. DWORD WINAPI threadfunc2(HANDLE hThread1)
  98. {
  99.    DWORD  dwThread2Id, dwRc;
  100.  
  101.    dwThread2Id = dwGlobalId = GetCurrentThreadId();
  102.    printf("Starting Thread 2: dwThread2Id = %u  dwGlobalId = %u\n", dwThread2Id, dwGlobalId);
  103.  
  104.    /* Resume Thread 1  */
  105.  
  106.    dwRc = ResumeThread(hThread1);
  107.    if( dwRc != 1)
  108.       errorExit("Error: Thread 1 failed to resume\n");
  109.  
  110.    /* Wait to ensure that Thread 1 is suspended */
  111.    Sleep(5000);
  112.  
  113.    /* Print the value of the TLS variable */
  114.    printf("In Thread 2 after resuming Thread 1: dwGlobalId = %u\n", dwGlobalId);
  115.  
  116.    /* Resume Thread 1 */
  117.    dwRc = ResumeThread(hThread1);
  118.    if( dwRc != 1)
  119.       errorExit("Error: Thread 1 failed to resume\n");
  120.  
  121.    printf("Ending Thread 2: dwThread2Id = %u  dwGlobalId = %u\n", dwThread2Id, dwGlobalId);
  122.  
  123.    return(0);
  124. }
  125.  
  126. /*
  127.  * main() will create Thread 1 and Thread 2, then wait for both threads to
  128.  * end.
  129.  */
  130.  
  131. int main(void)
  132. {
  133.    DWORD  dwMainId, dwThreadId, dwRc;
  134.    HANDLE hThread1, hThread2;
  135.  
  136.    dwMainId = dwGlobalId = GetCurrentThreadId();
  137.  
  138.    printf("Starting main thread: dwMainId = %u  dwGlobalId = %u\n", dwMainId, dwGlobalId);
  139.  
  140.    /* Create Thread 1  */
  141.  
  142.    hThread1 = CreateThread(NULL, 0, threadfunc1, NULL, 0, &dwThreadId);
  143.  
  144.    if (hThread1 !=NULL)
  145.    {
  146.       /* Create Thread 2 */
  147.  
  148.       hThread2 = CreateThread(NULL, 0, threadfunc2, hThread1, 0, &dwThreadId);
  149.       if (hThread2!=NULL)
  150.       {
  151.          /* Wait for Thread 1 and Thread 2 to end */
  152.  
  153.          dwRc = WaitForSingleObject(hThread2, INFINITE);
  154.          CloseHandle(hThread2);
  155.          if( dwRc != WAIT_OBJECT_0)
  156.             errorExit("Error: Wait for Thread 2 to end failed\n");
  157.  
  158.          dwRc = WaitForSingleObject(hThread1, INFINITE);
  159.          if( dwRc != WAIT_OBJECT_0)
  160.             errorExit("Error: Wait for Thread 1 to end failed\n");
  161.          CloseHandle(hThread1);
  162.  
  163.          printf("Ending main thread: dwMainId = %u  dwGlobalId = %u\n", dwMainId, dwGlobalId);
  164.       }
  165.       else
  166.          errorExit("Error: Thread 2 failed to create\n");
  167.    }
  168.    else
  169.          errorExit("Error: Thread 1 failed to create\n");
  170.    return 0;
  171. }
  172.  
  173. void errorExit(LPTSTR lpszMessage)
  174. {
  175.    printf("%s\n", lpszMessage);
  176.    ExitProcess(0);
  177. }
  178.