_beginthreadNT

From RAD Studio
Jump to: navigation, search

Go Up to process.h Index


Header File

process.h

Category

Process Control Routines

Prototype

unsigned long _beginthreadNT(void (_USERENTRY *start_address)(void *), unsigned stack_size, void *arglist, void *security_attrib, unsigned long create_flags, unsigned long *thread_id);

Description

Starts execution of a new thread under Windows NT.

Note: The start_address must be declared to be _USERENTRY.

All multithread Windows NT programs must use _beginthreadNT or the _beginthread function instead of the operating system thread-creation API function because these functions perform initialization required for correct operation of the runtime library functions. The _beginthreadNT function provides support for the operating system security. These functions are available only in the multithread libraries.

The _beginthreadNT function creates and starts a new thread. The thread starts execution at start_address. When your thread terminates, the _endthread function will be called automatically. _endthread will close the thread handle, and call the ExitThread API.

The size of its stack in bytes is stack_size; the stack is allocated by the operating system after the stack size is rounded up to the next multiple of 4096. The thread arglist can be NULL, but must be present.

The _beginthreadNT function uses the security_attr pointer to access the SECURITY_ATTRIBUTES structure. The structure contains the security attributes for the thread. If security_attr is NULL, the thread is created with default security attributes. The thread handle is not inherited if security_attr is NULL.

_beginthreadNT reads the create_flags variable for flags that provide additional information about the thread creation. This variable can be zero, specifying that the thread will run immediately upon creation. The variable can also be CREATE_SUSPENDED; in which case, the thread will not run until the ResumeThread function is called. ResumeThread is provided by the Win32 API.

_beginthreadNT initializes the thread_id variable with the thread identifier.

Return Value

On success, _beginthreadNT returns the handle of the new thread. The return value is a standard Windows handle that can be used in operating system API's such as SuspendThread and ResumeThread.

On error, it returns -1, and the global variable errno is set to one of the following values:

EAGAIN

Too many threads

EINVAL

Invalid stack size (i.e. less than 16 bytes, or equal to zero)

ENOMEM

Not enough memory



Also see the description of the Win32 API GetLastError, in the MSDN Library.

Example

/*  Use the -tWM  (32-bit multi-threaded target) command-line switch for this example  */
#pragma checkoption -tWM
#include        <windows.h>
#include        <process.h>
#include        <stdio.h>
#define NTHREADS 25
static LONG runningThreads = 0;
static HANDLE doneEvent;
/* This function acts as the 'main' function for each new thread */
static void threadMain(void *arg)
{
  printf("Thread %2d has an ID of %u\n", (int)arg, GetCurrentThreadId());
  /* Use InterlockedDecrement() to modify the global runningThreads in a
 * thread safe manner.  When the count hits 0, signal the main thread if
 * it created an event for us.
 */
  if (InterlockedDecrement(&runningThreads) == 0 && doneEvent)
      SetEvent(doneEvent);
}
int main(void)
{
   HANDLE hThreads[NTHREADS];
   int i;
   DWORD  threadId;
   SECURITY_ATTRIBUTES  sa = {
          sizeof(SECURITY_ATTRIBUTES), /* structure size */
          0,      /* No security descriptor */
          TRUE    /* Thread handle is inheritable */
   };
   /* Create NTHREADS inheritable threads that are initially suspended and that will run starting at threadMain()*/
   for(i = 0; i < NTHREADS; i++) {
      hThreads[i] = (HANDLE)_beginthreadNT(
         threadMain,   /* Thread starting address */
         4096,         /* Thread stack size */
         (void *)i,    /* Thread start argument */
         &sa,          /* Thread security */
         CREATE_SUSPENDED,  /* Create in suspended state */
         &threadId);   /* Thread ID */
      if(hThreads[i] == INVALID_HANDLE_VALUE) {
         MessageBox(0, "Thread Creation Failed", "Error", MB_OK);
         return  1;
      }
      ++runningThreads;
      printf("Created thread %2d with an ID of %u\n", i, threadId);
   }
   printf("\nPress ENTER to thaw all threads\n\n");
   getchar();
   /* Create the event that will signal when all threads are done */
   doneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

   /* Resume the suspended threads */
   for(i = 0; i < NTHREADS; i++)
      ResumeThread(hThreads[i]);
   /* Wait for all threads to finish execution, if we can */
   if (doneEvent) {
     WaitForSingleObject(doneEvent, INFINITE);
     CloseHandle(doneEvent);
   }
   return 0;
}

Portability

POSIX Win32 ANSI C ANSI C++

+