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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user