mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-01-29 21:46:59 +03:00
threads: Rework initialization
Make init/cleanup functions private. Merge xmlOnceInit into xmlInitThreadsInternal.
This commit is contained in:
parent
9dbf137455
commit
7010d8779b
@ -5,4 +5,7 @@ void __xmlGlobalInitMutexLock(void);
|
||||
void __xmlGlobalInitMutexUnlock(void);
|
||||
void __xmlGlobalInitMutexDestroy(void);
|
||||
|
||||
void xmlInitThreadsInternal(void);
|
||||
void xmlCleanupThreadsInternal(void);
|
||||
|
||||
#endif /* XML_THREADS_H_PRIVATE__ */
|
||||
|
4
parser.c
4
parser.c
@ -14495,7 +14495,7 @@ xmlInitParser(void) {
|
||||
__xmlGlobalInitMutexLock();
|
||||
if (xmlParserInitialized == 0) {
|
||||
#endif
|
||||
xmlInitThreads();
|
||||
xmlInitThreadsInternal();
|
||||
xmlInitGlobalsInternal();
|
||||
xmlInitMemoryInternal();
|
||||
xmlInitializeDict();
|
||||
@ -14555,7 +14555,7 @@ xmlCleanupParser(void) {
|
||||
xmlRelaxNGCleanupTypes();
|
||||
#endif
|
||||
xmlCleanupGlobalsInternal();
|
||||
xmlCleanupThreads(); /* must be last if called not from the main thread */
|
||||
xmlCleanupThreadsInternal();
|
||||
xmlCleanupMemoryInternal();
|
||||
xmlParserInitialized = 0;
|
||||
}
|
||||
|
124
threads.c
124
threads.c
@ -47,7 +47,6 @@ static int libxml_is_threaded = -1;
|
||||
|
||||
#define XML_PTHREAD_WEAK
|
||||
|
||||
#pragma weak pthread_once
|
||||
#pragma weak pthread_getspecific
|
||||
#pragma weak pthread_setspecific
|
||||
#pragma weak pthread_key_create
|
||||
@ -118,8 +117,6 @@ struct _xmlRMutex {
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
static pthread_key_t globalkey;
|
||||
static pthread_t mainthread;
|
||||
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
|
||||
static pthread_once_t once_control_init = PTHREAD_ONCE_INIT;
|
||||
static pthread_mutex_t global_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
#elif defined HAVE_WIN32_THREADS
|
||||
#if defined(HAVE_COMPILER_TLS)
|
||||
@ -129,19 +126,11 @@ static __declspec(thread) int tlstate_inited = 0;
|
||||
static DWORD globalkey = TLS_OUT_OF_INDEXES;
|
||||
#endif /* HAVE_COMPILER_TLS */
|
||||
static DWORD mainthread;
|
||||
static struct {
|
||||
DWORD done;
|
||||
LONG control;
|
||||
} run_once = { 0, 0};
|
||||
static volatile LPCRITICAL_SECTION global_init_lock = NULL;
|
||||
#endif
|
||||
|
||||
static xmlRMutexPtr xmlLibraryLock = NULL;
|
||||
|
||||
#ifdef LIBXML_THREAD_ENABLED
|
||||
static void xmlOnceInit(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* xmlNewMutex:
|
||||
*
|
||||
@ -538,8 +527,6 @@ xmlGetGlobalState(void)
|
||||
if (libxml_is_threaded == 0)
|
||||
return (NULL);
|
||||
|
||||
pthread_once(&once_control, xmlOnceInit);
|
||||
|
||||
if ((globalval = (xmlGlobalState *)
|
||||
pthread_getspecific(globalkey)) == NULL) {
|
||||
xmlGlobalState *tsd = xmlNewGlobalState();
|
||||
@ -560,8 +547,6 @@ xmlGetGlobalState(void)
|
||||
#else /* HAVE_COMPILER_TLS */
|
||||
xmlGlobalState *globalval;
|
||||
xmlGlobalStateCleanupHelperParams *p;
|
||||
|
||||
xmlOnceInit();
|
||||
#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
||||
globalval = (xmlGlobalState *) TlsGetValue(globalkey);
|
||||
#else
|
||||
@ -654,14 +639,10 @@ xmlGetThreadId(void)
|
||||
int
|
||||
xmlIsMainThread(void)
|
||||
{
|
||||
xmlInitParser();
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
if (libxml_is_threaded == -1)
|
||||
xmlInitThreads();
|
||||
if (libxml_is_threaded == 0)
|
||||
return (1);
|
||||
pthread_once(&once_control, xmlOnceInit);
|
||||
#elif defined HAVE_WIN32_THREADS
|
||||
xmlOnceInit();
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
@ -709,20 +690,26 @@ xmlUnlockLibrary(void)
|
||||
/**
|
||||
* xmlInitThreads:
|
||||
*
|
||||
* DEPRECATED: This function will be made private. Call xmlInitParser to
|
||||
* initialize the library.
|
||||
*
|
||||
* xmlInitThreads() is used to to initialize all the thread related
|
||||
* data of the libxml2 library.
|
||||
* DEPRECATED: Alias for xmlInitParser.
|
||||
*/
|
||||
void
|
||||
xmlInitThreads(void)
|
||||
{
|
||||
xmlInitParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlInitThreadsInternal:
|
||||
*
|
||||
* Used to to initialize all the thread related data.
|
||||
*/
|
||||
void
|
||||
xmlInitThreadsInternal(void)
|
||||
{
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
#ifdef XML_PTHREAD_WEAK
|
||||
if (libxml_is_threaded == -1) {
|
||||
if ((pthread_once != NULL) &&
|
||||
(pthread_getspecific != NULL) &&
|
||||
if ((pthread_getspecific != NULL) &&
|
||||
(pthread_setspecific != NULL) &&
|
||||
(pthread_key_create != NULL) &&
|
||||
(pthread_key_delete != NULL) &&
|
||||
@ -750,38 +737,42 @@ xmlInitThreads(void)
|
||||
}
|
||||
}
|
||||
#endif /* XML_PTHREAD_WEAK */
|
||||
pthread_key_create(&globalkey, xmlFreeGlobalState);
|
||||
mainthread = pthread_self();
|
||||
#elif defined(HAVE_WIN32_THREADS)
|
||||
#if !defined(HAVE_COMPILER_TLS)
|
||||
#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
|
||||
InitializeCriticalSection(&cleanup_helpers_cs);
|
||||
#endif
|
||||
globalkey = TlsAlloc();
|
||||
#endif
|
||||
mainthread = GetCurrentThreadId();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCleanupThreads:
|
||||
*
|
||||
* DEPRECATED: This function will be made private. Call xmlCleanupParser
|
||||
* DEPRECATED: This function is a no-op. Call xmlCleanupParser
|
||||
* to free global state but see the warnings there. xmlCleanupParser
|
||||
* should be only called once at program exit. In most cases, you don't
|
||||
* have call cleanup functions at all.
|
||||
*
|
||||
* xmlCleanupThreads() is used to to cleanup all the thread related
|
||||
* data of the libxml2 library once processing has ended.
|
||||
*
|
||||
* WARNING: if your application is multithreaded or has plugin support
|
||||
* calling this may crash the application if another thread or
|
||||
* a plugin is still using libxml2. It's sometimes very hard to
|
||||
* guess if libxml2 is in use in the application, some libraries
|
||||
* or plugins may use it without notice. In case of doubt abstain
|
||||
* from calling this function or do it just before calling exit()
|
||||
* to avoid leak reports from valgrind !
|
||||
*/
|
||||
void
|
||||
xmlCleanupThreads(void)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
xmlGenericError(xmlGenericErrorContext, "xmlCleanupThreads()\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlCleanupThreadsInternal:
|
||||
*
|
||||
* Used to to cleanup all the thread related data.
|
||||
*/
|
||||
void
|
||||
xmlCleanupThreadsInternal(void)
|
||||
{
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
if (libxml_is_threaded != 0)
|
||||
pthread_key_delete(globalkey);
|
||||
once_control = once_control_init;
|
||||
pthread_key_delete(globalkey);
|
||||
#elif defined(HAVE_WIN32_THREADS)
|
||||
#if !defined(HAVE_COMPILER_TLS)
|
||||
if (globalkey != TLS_OUT_OF_INDEXES) {
|
||||
@ -807,52 +798,9 @@ xmlCleanupThreads(void)
|
||||
DeleteCriticalSection(&cleanup_helpers_cs);
|
||||
#endif
|
||||
#endif
|
||||
run_once.done = 0;
|
||||
run_once.control = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LIBXML_THREAD_ENABLED
|
||||
|
||||
/**
|
||||
* xmlOnceInit
|
||||
*
|
||||
* xmlOnceInit() is used to initialize the value of mainthread for use
|
||||
* in other routines. This function should only be called using
|
||||
* pthread_once() in association with the once_control variable to ensure
|
||||
* that the function is only called once. See man pthread_once for more
|
||||
* details.
|
||||
*/
|
||||
static void
|
||||
xmlOnceInit(void)
|
||||
{
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
(void) pthread_key_create(&globalkey, xmlFreeGlobalState);
|
||||
mainthread = pthread_self();
|
||||
__xmlInitializeDict();
|
||||
#elif defined(HAVE_WIN32_THREADS)
|
||||
if (!run_once.done) {
|
||||
if (InterlockedIncrement(&run_once.control) == 1) {
|
||||
#if !defined(HAVE_COMPILER_TLS)
|
||||
#if !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)
|
||||
InitializeCriticalSection(&cleanup_helpers_cs);
|
||||
#endif
|
||||
globalkey = TlsAlloc();
|
||||
#endif
|
||||
mainthread = GetCurrentThreadId();
|
||||
__xmlInitializeDict();
|
||||
run_once.done = 1;
|
||||
} else {
|
||||
/* Another thread is working; give up our slice and
|
||||
* wait until they're done. */
|
||||
while (!run_once.done)
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DllMain:
|
||||
* @hinstDLL: handle to DLL instance
|
||||
|
Loading…
x
Reference in New Issue
Block a user