_adopt_thread

From RAD Studio
Jump to: navigation, search

Go Up to process.h Index


Header File

process.h

Category

Process Control Routines

Prototype

_PTHREAD_ADOPTION_DATA _adopt_thread(void (_USERENTRY *__start_address)(void *), void * __arglist, int free_flag );

Description

"Adopts" a thread, created with the Windows API CreateThread function, to the C++Builder RTL by hooking up the necessary internal data (exceptions, stack info, and so forth). _adopt_thread thereby allows the RTL to handle exception issues in that thread. The execution path of this thread is then transferred to another function (the adoptive thread function). From the RTL perspective, during the execution of this adoptive thread function, the thread appears as if it had been created by a call to _beginthreadex and is allowed all the benefits, such as calling other RTL functions and throwing/catching exceptions.

To create a thread, a user normally calls _beginthread. This hooks up the internal data automatically. _adopt_thread is primarily used in cases in which this internal data is not present. For example, this happens when a user is called from a thread that came from an outside source, such as ISAPI.

Using _adopt_thread thereby allows C++Builder compiled DLLs to be used from non-C++Builder EXEs. _adopt_thread works by:

  • calling the user function (passing in the arglist param)
  • unhooking the exception information
  • returning a handle to the thread context

This process allows the same function to be used again (without reallocating all that data). At the end of this cycle, the _unadopt_thread function can be called to finally free up the rest of this data.

The last parameter, free_flag, determines whether the thread data structures are freed upon function exit:

  • If free_flag is zero, then when the adoptive function exits only its exception handler is un-hooked. The rest of the RTL specific data that had been allocated during the thread's adoption, remains valid. If the same thread then calls _adopt_thread again, the existing data is used, the exception handler is rehooked, and the specified adoptive thread function is called.
  • If free_flag is set to non-zero, the thread data structures will be freed before _adopt_thread returns. In this case the returned thread handle will be NULL since its associated date has already been freed.

Return Value

If the __free_flag parameter is false (zero), _adopt_thread returns a handle (thread context) that can later be used to free these data structures by passing it to _unadopt_thread().

If the __free_flag parameter to _adopt_thread is non-zero, the thread data is freed before _adopt_thread returns, and the returned handle is NULL.

If an error has occurred, errno is set to:

ENOMEM Not enough memory

Example

#include <process.h>
#include <windows.h>
void adopted_thread(void*)
{
  printf("Running in a RTL-managed thread!\n");
}

unsigned long __stdcall winapi_thread(void*)
{
  /*
   This code runs on another thread, created by CreateThread Win32 API.
   _adopt_thread is used to continue the execution in the routine that
   is RTL managed (in the same thread context).
  */
  printf("Running in a simple thread! Adopting ...\n");
  ''_PTHREAD_ADOPTION_DATA'' data = '''_adopt_thread'''(adopted_thread, NULL, false);
   /* Un-adopt the thread and release it's resources */
  printf("Back to OS thread! Release adoption ...\n");
  _unadopt_thread(data);
}

int _tmain(int argc, _TCHAR* argv[])
{
  /* Create a thread using OS APIs, thus RTL-unmanaged */
  unsigned long threadId;
  CreateThread(NULL, 0, winapi_thread, NULL, 0, &threadId);

  Sleep(100);

  return 0;
}

Portability

POSIX Win32 ANSI C ANSI C++

+