array: Add fallback for qsort_r using thread-local value
Cygwin for example does not support qsort_r.
This commit is contained in:
parent
190a278854
commit
b3613c49a2
|
@ -528,7 +528,7 @@ AC_CHECK_FUNC(
|
|||
])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
],
|
||||
[AC_MSG_FAILURE([qsort_r not found])]
|
||||
[]
|
||||
)
|
||||
|
||||
AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r)
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
#include "array.h"
|
||||
|
||||
#ifndef HAVE_QSORT_R
|
||||
#include <threading/thread_value.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Data is an allocated block, with potentially unused head and tail:
|
||||
*
|
||||
|
@ -49,6 +53,11 @@ struct array_t {
|
|||
void *data;
|
||||
};
|
||||
|
||||
#ifndef HAVE_QSORT_R
|
||||
/* store data to replicate qsort_r in thread local storage */
|
||||
static thread_value_t *sort_data;
|
||||
#endif
|
||||
|
||||
/** maximum number of unused head/tail elements before cleanup */
|
||||
#define ARRAY_MAX_UNUSED 32
|
||||
|
||||
|
@ -382,11 +391,17 @@ typedef struct {
|
|||
|
||||
#ifdef HAVE_QSORT_R_GNU
|
||||
static int compare_elements(const void *a, const void *b, void *arg)
|
||||
#else /* HAVE_QSORT_R_BSD */
|
||||
#elif HAVE_QSORT_R_BSD
|
||||
static int compare_elements(void *arg, const void *a, const void *b)
|
||||
#else /* !HAVE_QSORT_R */
|
||||
static int compare_elements(const void *a, const void *b)
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_QSORT_R
|
||||
sort_data_t *data = (sort_data_t*)arg;
|
||||
#else
|
||||
sort_data_t *data = sort_data->get(sort_data);
|
||||
#endif
|
||||
|
||||
if (data->array->esize)
|
||||
{
|
||||
|
@ -412,9 +427,12 @@ void array_sort(array_t *array, int (*cmp)(const void*,const void*,void*),
|
|||
#ifdef HAVE_QSORT_R_GNU
|
||||
qsort_r(start, array->count, get_size(array, 1), compare_elements,
|
||||
&data);
|
||||
#else /* HAVE_QSORT_R_BSD */
|
||||
#elif HAVE_QSORT_R_BSD
|
||||
qsort_r(start, array->count, get_size(array, 1), &data,
|
||||
compare_elements);
|
||||
#else /* !HAVE_QSORT_R */
|
||||
sort_data->set(sort_data, &data);
|
||||
qsort(start, array->count, get_size(array, 1), compare_elements);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -531,3 +549,17 @@ void array_destroy_offset(array_t *array, size_t offset)
|
|||
array_invoke_offset(array, offset);
|
||||
array_destroy(array);
|
||||
}
|
||||
|
||||
void arrays_init()
|
||||
{
|
||||
#ifndef HAVE_QSORT_R
|
||||
sort_data = thread_value_create(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void arrays_deinit()
|
||||
{
|
||||
#ifndef HAVE_QSORT_R
|
||||
sort_data->destroy(sort_data);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -251,4 +251,16 @@ void array_destroy_function(array_t *array, array_callback_t cb, void *user);
|
|||
*/
|
||||
void array_destroy_offset(array_t *array, size_t offset);
|
||||
|
||||
|
||||
/**
|
||||
* Required on some platforms to initialize thread local value to implement
|
||||
* array_sort().
|
||||
*/
|
||||
void arrays_init();
|
||||
|
||||
/**
|
||||
* Destroys the thread local value if required.
|
||||
*/
|
||||
void arrays_deinit();
|
||||
|
||||
#endif /** ARRAY_H_ @}*/
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <threading/thread.h>
|
||||
#include <utils/identification.h>
|
||||
#include <networking/host.h>
|
||||
#include <collections/array.h>
|
||||
#include <collections/hashtable.h>
|
||||
#include <utils/backtrace.h>
|
||||
#include <selectors/traffic_selector.h>
|
||||
|
@ -142,6 +143,7 @@ void library_deinit()
|
|||
lib->leak_detective->destroy(lib->leak_detective);
|
||||
}
|
||||
|
||||
arrays_deinit();
|
||||
threads_deinit();
|
||||
backtrace_deinit();
|
||||
|
||||
|
@ -259,6 +261,7 @@ bool library_init(char *settings, const char *namespace)
|
|||
|
||||
backtrace_init();
|
||||
threads_init();
|
||||
arrays_init();
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
lib->leak_detective = leak_detective_create();
|
||||
|
|
Loading…
Reference in New Issue