1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-01-27 14:03:36 +03:00

globals: Add a few comments

This commit is contained in:
Nick Wellnhofer 2023-09-20 12:45:14 +02:00
parent ecbd634c9f
commit 759767423a

View File

@ -25,6 +25,29 @@
#include "private/threads.h" #include "private/threads.h"
#include "private/tree.h" #include "private/tree.h"
/*
* Thread-local storage emulation.
*
* This works by replacing a global variable
*
* extern xmlError xmlLastError;
*
* with a macro that calls a function returning a pointer to the global in
* thread-local storage:
*
* xmlError *__xmlLastError(void);
* #define xmlError (*__xmlLastError());
*
* The code can operate in a multitude of ways depending on the environment.
* First we support POSIX and Windows threads. Then we support both thread-local
* storage provided by the compiler and older methods like thread-specific data
* (pthreads) or TlsAlloc (Windows).
*
* To clean up thread-local storage, we use thread-specific data on POSIX.
* On Windows, we either use DllMain when compiling a DLL or a registered wait
* function for static builds.
*/
/* /*
* Helpful Macro * Helpful Macro
*/ */
@ -79,6 +102,11 @@ static int libxml_is_threaded = -1;
#endif #endif
/*
* On POSIX, we need thread-specific data even with thread-local storage
* to destroy indirect references from global state (xmlLastError) at
* thread exit.
*/
static pthread_key_t globalkey; static pthread_key_t globalkey;
static pthread_t mainthread; static pthread_t mainthread;
@ -629,19 +657,21 @@ xmlIsMainThread(void) {
} }
#ifdef LIBXML_THREAD_ENABLED #ifdef LIBXML_THREAD_ENABLED
/**
* xmlFreeGlobalState:
* @state: a thread global state
*
* xmlFreeGlobalState() is called when a thread terminates with a non-NULL
* global state. It is is used here to reclaim memory resources.
*/
static void static void
xmlFreeGlobalState(void *state) xmlFreeGlobalState(void *state)
{ {
xmlGlobalState *gs = (xmlGlobalState *) state; xmlGlobalState *gs = (xmlGlobalState *) state;
/* free any memory allocated in the thread's xmlLastError */ /*
* Free any memory allocated in the thread's xmlLastError. If it
* weren't for this indirect allocation, we wouldn't need
* a destructor with thread-local storage at all!
*
* It would be nice if we could make xmlLastError a special error
* type which uses statically allocated, fixed-size buffers.
* But the xmlError struct is fully public and widely used,
* so changes are dangerous.
*/
xmlResetError(&(gs->gs_xmlLastError)); xmlResetError(&(gs->gs_xmlLastError));
#ifndef XML_THREAD_LOCAL #ifndef XML_THREAD_LOCAL
free(state); free(state);
@ -805,14 +835,18 @@ xmlGetThreadLocalStorage(void) {
* *
* Check whether thread-local storage could be allocated. * Check whether thread-local storage could be allocated.
* *
* In multithreaded environments, this function should be called once * In cross-platform code running in multithreaded environments, this
* in each thread before calling other library functions to make sure * function should be called once in each thread before calling other
* that thread-local storage was allocated properly. * library functions to make sure that thread-local storage was
* allocated properly.
* *
* Returns 0 on success or -1 if a memory allocation failed. A failed * Returns 0 on success or -1 if a memory allocation failed. A failed
* allocation signals a typically fatal and irrecoverable out-of-memory * allocation signals a typically fatal and irrecoverable out-of-memory
* situation. Don't call any library functions in this case. * situation. Don't call any library functions in this case.
* *
* This function never fails if the library is compiled with support
* for thread-local storage.
*
* This function never fails for the "main" thread which is the first * This function never fails for the "main" thread which is the first
* thread calling xmlInitParser. * thread calling xmlInitParser.
* *