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"
|
CFLAGS="$save_CFLAGS"
|
||||||
],
|
],
|
||||||
[AC_MSG_FAILURE([qsort_r not found])]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r)
|
AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r)
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
|
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_QSORT_R
|
||||||
|
#include <threading/thread_value.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data is an allocated block, with potentially unused head and tail:
|
* Data is an allocated block, with potentially unused head and tail:
|
||||||
*
|
*
|
||||||
|
@ -49,6 +53,11 @@ struct array_t {
|
||||||
void *data;
|
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 */
|
/** maximum number of unused head/tail elements before cleanup */
|
||||||
#define ARRAY_MAX_UNUSED 32
|
#define ARRAY_MAX_UNUSED 32
|
||||||
|
|
||||||
|
@ -382,11 +391,17 @@ typedef struct {
|
||||||
|
|
||||||
#ifdef HAVE_QSORT_R_GNU
|
#ifdef HAVE_QSORT_R_GNU
|
||||||
static int compare_elements(const void *a, const void *b, void *arg)
|
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)
|
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
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_QSORT_R
|
||||||
sort_data_t *data = (sort_data_t*)arg;
|
sort_data_t *data = (sort_data_t*)arg;
|
||||||
|
#else
|
||||||
|
sort_data_t *data = sort_data->get(sort_data);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (data->array->esize)
|
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
|
#ifdef HAVE_QSORT_R_GNU
|
||||||
qsort_r(start, array->count, get_size(array, 1), compare_elements,
|
qsort_r(start, array->count, get_size(array, 1), compare_elements,
|
||||||
&data);
|
&data);
|
||||||
#else /* HAVE_QSORT_R_BSD */
|
#elif HAVE_QSORT_R_BSD
|
||||||
qsort_r(start, array->count, get_size(array, 1), &data,
|
qsort_r(start, array->count, get_size(array, 1), &data,
|
||||||
compare_elements);
|
compare_elements);
|
||||||
|
#else /* !HAVE_QSORT_R */
|
||||||
|
sort_data->set(sort_data, &data);
|
||||||
|
qsort(start, array->count, get_size(array, 1), compare_elements);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,3 +549,17 @@ void array_destroy_offset(array_t *array, size_t offset)
|
||||||
array_invoke_offset(array, offset);
|
array_invoke_offset(array, offset);
|
||||||
array_destroy(array);
|
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);
|
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_ @}*/
|
#endif /** ARRAY_H_ @}*/
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <threading/thread.h>
|
#include <threading/thread.h>
|
||||||
#include <utils/identification.h>
|
#include <utils/identification.h>
|
||||||
#include <networking/host.h>
|
#include <networking/host.h>
|
||||||
|
#include <collections/array.h>
|
||||||
#include <collections/hashtable.h>
|
#include <collections/hashtable.h>
|
||||||
#include <utils/backtrace.h>
|
#include <utils/backtrace.h>
|
||||||
#include <selectors/traffic_selector.h>
|
#include <selectors/traffic_selector.h>
|
||||||
|
@ -142,6 +143,7 @@ void library_deinit()
|
||||||
lib->leak_detective->destroy(lib->leak_detective);
|
lib->leak_detective->destroy(lib->leak_detective);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arrays_deinit();
|
||||||
threads_deinit();
|
threads_deinit();
|
||||||
backtrace_deinit();
|
backtrace_deinit();
|
||||||
|
|
||||||
|
@ -259,6 +261,7 @@ bool library_init(char *settings, const char *namespace)
|
||||||
|
|
||||||
backtrace_init();
|
backtrace_init();
|
||||||
threads_init();
|
threads_init();
|
||||||
|
arrays_init();
|
||||||
|
|
||||||
#ifdef LEAK_DETECTIVE
|
#ifdef LEAK_DETECTIVE
|
||||||
lib->leak_detective = leak_detective_create();
|
lib->leak_detective = leak_detective_create();
|
||||||
|
|
Loading…
Reference in New Issue