1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2026-01-26 21:41:34 +03:00

dict: Rework reference counting

Use C11 atomics if available. Otherwise, fall back to pthread mutex
inlined in xmlDict struct or Win32 atomics.

This should fix lock contention reported in #970.
This commit is contained in:
Nick Wellnhofer
2025-08-16 14:36:43 +02:00
parent 24caea6383
commit 18bbdb5117
4 changed files with 141 additions and 41 deletions

View File

@@ -50,11 +50,6 @@ typedef struct {
const xmlChar *name;
} xmlHashedString;
XML_HIDDEN void
xmlInitDictInternal(void);
XML_HIDDEN void
xmlCleanupDictInternal(void);
XML_HIDDEN unsigned
xmlDictComputeHash(const xmlDict *dict, const xmlChar *string);
XML_HIDDEN unsigned

View File

@@ -48,6 +48,141 @@ struct _xmlRMutex {
#endif
};
#if defined(LIBXML_THREAD_ENABLED) && \
__STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
/** Atomic reference count */
typedef _Atomic size_t xmlRefCount;
/**
* Initialize refcount.
*
* @param r refcount
*/
static XML_INLINE void
xmlRefCountInit(xmlRefCount *r) {
*r = 1;
}
/**
* Increase refcount.
*
* @param r refcount
*/
static XML_INLINE void
xmlRefCountInc(xmlRefCount *r) {
*r += 1;
}
/**
* Decrease refcount.
*
* @param r refcount
* @returns 0 if refcount reached zero, 1 otherwise
*/
static XML_INLINE int
xmlRefCountDec(xmlRefCount *r) {
return --*r > 0;
}
#elif defined(HAVE_POSIX_THREADS)
typedef struct {
pthread_mutex_t mutex;
size_t count;
} xmlRefCount;
static XML_INLINE void
xmlRefCountInit(xmlRefCount *r) {
pthread_mutex_init(&r->mutex, NULL);
r->count = 1;
}
static XML_INLINE void
xmlRefCountInc(xmlRefCount *r) {
pthread_mutex_lock(&r->mutex);
r->count += 1;
pthread_mutex_unlock(&r->mutex);
}
static XML_INLINE int
xmlRefCountDec(xmlRefCount *r) {
size_t val;
pthread_mutex_lock(&r->mutex);
val = --r->count;
pthread_mutex_unlock(&r->mutex);
if (val > 0)
return 1;
pthread_mutex_destroy(&r->mutex);
return 0;
}
#elif defined(HAVE_WIN32_THREADS)
#ifdef _WIN64
typedef __int64 xmlRefCount;
static XML_INLINE void
xmlRefCountInit(xmlRefCount *r) {
*r = 1;
}
static XML_INLINE void
xmlRefCountInc(xmlRefCount *r) {
InterlockedIncrement64(r);
}
static XML_INLINE int
xmlRefCountDec(xmlRefCount *r) {
return InterlockedDecrement64(r) > 0;
}
#else /* 32-bit */
typedef long xmlRefCount;
static XML_INLINE void
xmlRefCountInit(xmlRefCount *r) {
*r = 1;
}
static XML_INLINE void
xmlRefCountInc(xmlRefCount *r) {
InterlockedIncrement(r);
}
static XML_INLINE int
xmlRefCountDec(xmlRefCount *r) {
return InterlockedDecrement(r) > 0;
}
#endif
#else /* no threads */
typedef size_t xmlRefCount;
static XML_INLINE void
xmlRefCountInit(xmlRefCount *r) {
*r = 1;
}
static XML_INLINE void
xmlRefCountInc(xmlRefCount *r) {
*r += 1;
}
static XML_INLINE int
xmlRefCountDec(xmlRefCount *r) {
return --*r > 0;
}
#endif
XML_HIDDEN void
xmlInitMutex(xmlMutex *mutex);
XML_HIDDEN void