Add native Windows thread support instead of using pthread

(less overhead). On other OS, pthread is still used by default.
Pass --enable-win32-threads to activate thread support on
Windows.


SVN revision: 50262
This commit is contained in:
Vincent Torri 2010-07-15 06:34:32 +00:00
parent cebe53cd3d
commit 8351950dee
8 changed files with 315 additions and 156 deletions

View File

@ -399,3 +399,9 @@
* Moved Eet.h into $includedir/eet-MAJOR_VERSION/
2010-07-15 Vincent Torri
* Add native Windows thread support instead of using pthread
(less overhead). On other OS, pthread is still used by default.
Pass --enable-win32-threads to activate thread support on
Windows.

View File

@ -31,6 +31,14 @@ autogen.sh \
eet.pc.in \
eet.spec.in \
eet.spec \
m4/ac_attribute.m4 \
m4/ac_path_generic.m4 \
m4/efl_binary.m4 \
m4/efl_coverage.m4 \
m4/efl_doxygen.m4 \
m4/efl_fnmatch.m4 \
m4/efl_tests.m4 \
m4/efl_threads.m4 \
README.in \
README

View File

@ -322,7 +322,18 @@ AC_MSG_RESULT(${have_signature})
# pthread library
EFL_CHECK_PTHREAD(["no"], [have_pthread="yes"], [have_pthread="no"])
EFL_CHECK_THREADS(["no"],
[
if test "x${_efl_have_posix_threads}" = "xyes" ; then
have_threads="POSIX"
else
if test "x${_efl_have_win32_threads}" = "xyes" ; then
have_threads="Win32"
else
have_threads="no"
fi
fi],
[have_threads="no"])
### Checks for header files
@ -461,7 +472,7 @@ if test "x${have_gnutls}" = "xyes" || test "x${have_openssl}" = "xyes" ; then
echo " Cipher support.....: ${have_cipher}"
echo " Signature..........: ${have_signature}"
fi
echo " Thread Support.......: ${have_pthread}"
echo " Thread Support.......: ${have_threads}"
echo
echo " Old eet file format..: ${old_eet_file_format}"
echo

View File

@ -8,6 +8,6 @@ Description: Library for speedy data storage, retrieval, and compression
@pkgconfig_requires_private@: @requirement_eet@
Version: @VERSION@
Libs: -L${libdir} -leet
Libs.private: @EET_LIBS@ @EFL_FNMATCH_LIBS@ @LIBGCRYPT_LIBS@ -ljpeg -lz -lm
Libs.private: @EET_LIBS@ @EFL_FNMATCH_LIBS@ @LIBGCRYPT_LIBS@ @EFL_PTHREAD_LIBS@ -ljpeg -lz -lm
Cflags: -I${includedir}/eet-@VMAJ@
Cflags.private: @LIBGCRYPT_CFLAGS@

View File

@ -1,130 +0,0 @@
dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
dnl That code is public domain and can be freely used or copied.
dnl Macro that check if several pthread library is available or not.
dnl Usage: EFL_CHECK_PTHREAD(want_pthread_spin[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Call AC_SUBST(EFL_PTHREAD_CFLAGS)
dnl Call AC_SUBST(EFL_PTHREAD_LIBS)
dnl Define EFL_HAVE_PTHREAD
dnl Define EFL_HAVE_PTHREAD_SPINLOCK
AC_DEFUN([EFL_CHECK_PTHREAD],
[
dnl configure option
AC_ARG_ENABLE([pthread],
[AC_HELP_STRING([--disable-pthread], [enable POSIX threads code @<:@default=auto@:>@])],
[
if test "x${enableval}" = "xyes" ; then
_efl_enable_pthread="yes"
else
_efl_enable_pthread="no"
fi
],
[_efl_enable_pthread="auto"])
AC_MSG_CHECKING([whether to build POSIX threads code])
AC_MSG_RESULT([${_efl_enable_pthread}])
dnl check if the compiler supports pthreads
case "$host_os" in
mingw*)
_efl_pthread_cflags=""
_efl_pthread_libs="-lpthreadGC2"
;;
solaris*)
_efl_pthread_cflags="-mt"
_efl_pthread_libs="-mt"
;;
*)
_efl_pthread_cflags="-pthread"
_efl_pthread_libs="-pthread"
;;
esac
_efl_have_pthread="no"
if test "x${_efl_enable_pthread}" = "xyes" || test "x${_efl_enable_pthread}" = "xauto" ; then
SAVE_CFLAGS=${CFLAGS}
CFLAGS="${CFLAGS} ${_efl_pthread_cflags}"
SAVE_LIBS=${LIBS}
LIBS="${LIBS} ${_efl_pthread_libs}"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <pthread.h>
]],
[[
pthread_t id;
id = pthread_self();
]])],
[_efl_have_pthread="yes"],
[_efl_have_pthread="no"])
CFLAGS=${SAVE_CFLAGS}
LIBS=${SAVE_LIBS}
fi
AC_MSG_CHECKING([whether system support POSIX threads])
AC_MSG_RESULT([${_efl_have_pthread}])
if test "$x{_efl_enable_pthread}" = "xyes" && test "x${_efl_have_pthread}" = "xno"; then
AC_MSG_ERROR([pthread support requested but not found.])
fi
EFL_PTHREAD_CFLAGS=""
EFL_PTHREAD_LIBS=""
if test "x${_efl_have_pthread}" = "xyes" ; then
EFL_PTHREAD_CFLAGS=${_efl_pthread_cflags}
EFL_PTHREAD_LIBS=${_efl_pthread_libs}
fi
AC_SUBST(EFL_PTHREAD_CFLAGS)
AC_SUBST(EFL_PTHREAD_LIBS)
if test "x${_efl_have_pthread}" = "xyes" ; then
AC_DEFINE(EFL_HAVE_PTHREAD, 1, [Define to mention that POSIX threads are supported])
fi
dnl check if the compiler supports pthreads spinlock
_efl_have_pthread_spinlock="no"
if test "x${_efl_have_pthread}" = "xyes" && test "x$1" = "xyes" ; then
SAVE_CFLAGS=${CFLAGS}
CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}"
SAVE_LIBS=${LIBS}
LIBS="${LIBS} ${EFL_PTHREAD_LIBS}"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <pthread.h>
]],
[[
pthread_spinlock_t lock;
int res;
res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
]])],
[_efl_have_pthread_spinlock="yes"],
[_efl_have_pthread_spinlock="no"])
CFLAGS=${SAVE_CFLAGS}
LIBS=${SAVE_LIBS}
fi
AC_MSG_CHECKING([whether to build POSIX threads spinlock code])
AC_MSG_RESULT([${_efl_have_pthread_spinlock}])
if test "x${_efl_enable_pthread}" = "xyes" && test "x${_efl_have_pthread_spinlock}" = "xno" && test "x$1" = "xyes" ; then
AC_MSG_WARN([pthread support requested but spinlocks are not supported])
fi
if test "x${_efl_have_pthread_spinlock}" = "xyes" ; then
AC_DEFINE(EFL_HAVE_PTHREAD_SPINLOCK, 1, [Define to mention that POSIX threads spinlocks are supported])
fi
AS_IF([test "x$_efl_have_pthread" = "xyes"], [$2], [$3])
AS_IF([test "x$_efl_have_pthread_spinlock" = "xyes"], [$4], [$5])
])

View File

@ -0,0 +1,189 @@
dnl Copyright (C) 2010 Vincent Torri <vtorri at univ-evry dot fr>
dnl That code is public domain and can be freely used or copied.
dnl Macro that check if POSIX or Win32 threads library is available or not.
dnl Usage: EFL_CHECK_THREADS(want_pthread_spin[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Call AC_SUBST(EFL_PTHREAD_CFLAGS)
dnl Call AC_SUBST(EFL_PTHREAD_LIBS)
dnl Define EFL_HAVE_POSIX_THREADS or EFL_HAVE_WIN32_THREADS, and EFL_HAVE_THREADS
dnl Define EFL_HAVE_POSIX_THREADS_SPINLOCK
AC_DEFUN([EFL_CHECK_THREADS],
[
dnl configure option
AC_ARG_ENABLE([posix-threads],
[AC_HELP_STRING([--disable-posix-threads], [enable POSIX threads code @<:@default=auto@:>@])],
[
if test "x${enableval}" = "xyes" ; then
_efl_enable_posix_threads="yes"
else
_efl_enable_posix_threads="no"
fi
],
[_efl_enable_posix_threads="auto"])
AC_MSG_CHECKING([whether to build POSIX threads code])
AC_MSG_RESULT([${_efl_enable_posix_threads}])
AC_ARG_ENABLE([win32-threads],
[AC_HELP_STRING([--disable-win32-threads], [enable Win32 threads code @<:@default=no@:>@])],
[
if test "x${enableval}" = "xyes" ; then
_efl_enable_win32_threads="yes"
else
_efl_enable_win32_threads="no"
fi
],
[_efl_enable_win32_threads="no"])
AC_MSG_CHECKING([whether to build Windows threads code])
AC_MSG_RESULT([${_efl_enable_win32_threads}])
dnl
dnl * no + no
dnl * yes + no : win32: error, other : pthread
dnl * yes + yes : win32 : wthread, other : pthread
dnl * no + yes : win32 : wthread, other : error
if test "x${_efl_enable_posix_threads}" = "xyes" && test "x${_efl_enable_win32_threads}" = "xyes" ; then
case "$host_os" in
mingw*)
_efl_enable_posix_threads=no
;;
*)
_efl_enable_win32_threads=no
;;
esac
fi
if test "x${_efl_enable_win32_threads}" = "xyes" ; then
case "$host_os" in
mingw*)
;;
*)
AC_MSG_ERROR([Win32 threads support requested but non Windows system found.])
;;
esac
fi
if test "x${_efl_enable_posix_threads}" = "xyes" ; then
case "$host_os" in
mingw*)
AC_MSG_ERROR([POSIX threads support requested but Windows system found.])
;;
*)
;;
esac
fi
dnl check if the compiler supports POSIX threads
case "$host_os" in
mingw*)
;;
solaris*)
_efl_thread_cflags="-mt"
_efl_thread_libs="-mt"
;;
*)
_efl_thread_cflags="-pthread"
_efl_thread_libs="-pthread"
;;
esac
_efl_have_posix_threads="no"
_efl_have_win32_threads="no"
if test "x${_efl_enable_posix_threads}" = "xyes" || test "x${_efl_enable_posix_threads}" = "xauto" ; then
SAVE_CFLAGS=${CFLAGS}
CFLAGS="${CFLAGS} ${_efl_threads_cflags}"
SAVE_LIBS=${LIBS}
LIBS="${LIBS} ${_efl_threads_libs}"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <pthread.h>
]],
[[
pthread_t id;
id = pthread_self();
]])],
[_efl_have_posix_threads="yes"],
[_efl_have_posix_threads="no"])
CFLAGS=${SAVE_CFLAGS}
LIBS=${SAVE_LIBS}
fi
AC_MSG_CHECKING([whether system support POSIX threads])
AC_MSG_RESULT([${_efl_have_posix_threads}])
if test "$x{_efl_enable_posix_threads}" = "xyes" && test "x${_efl_have_posix_threads}" = "xno"; then
AC_MSG_ERROR([POSIX threads support requested but not found.])
fi
EFL_PTHREAD_CFLAGS=""
EFL_PTHREAD_LIBS=""
if test "x${_efl_have_posix_threads}" = "xyes" ; then
EFL_PTHREAD_CFLAGS=${_efl_thread_cflags}
EFL_PTHREAD_LIBS=${_efl_thread_libs}
fi
AC_SUBST(EFL_PTHREAD_CFLAGS)
AC_SUBST(EFL_PTHREAD_LIBS)
if test "x${_efl_have_posix_threads}" = "xyes" ; then
AC_DEFINE([EFL_HAVE_POSIX_THREADS], [1], [Define to mention that POSIX threads are supported])
fi
dnl check if the compiler supports pthreads spinlock
_efl_have_posix_threads_spinlock="no"
if test "x${_efl_have_posix_threads}" = "xyes" && test "x$1" = "xyes" ; then
SAVE_CFLAGS=${CFLAGS}
CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}"
SAVE_LIBS=${LIBS}
LIBS="${LIBS} ${EFL_PTHREAD_LIBS}"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <pthread.h>
]],
[[
pthread_spinlock_t lock;
int res;
res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
]])],
[_efl_have_posix_threads_spinlock="yes"],
[_efl_have_posix_threads_spinlock="no"])
CFLAGS=${SAVE_CFLAGS}
LIBS=${SAVE_LIBS}
fi
AC_MSG_CHECKING([whether to build POSIX threads spinlock code])
AC_MSG_RESULT([${_efl_have_posix_threads_spinlock}])
if test "x${_efl_enable_posix_threads}" = "xyes" && test "x${_efl_have_posix_threads_spinlock}" = "xno" && test "x$1" = "xyes" ; then
AC_MSG_WARN([POSIX threads support requested but spinlocks are not supported])
fi
if test "x${_efl_have_posix_threads_spinlock}" = "xyes" ; then
AC_DEFINE([EFL_HAVE_POSIX_THREADS_SPINLOCK], [1], [Define to mention that POSIX threads spinlocks are supported])
fi
if test "x${_efl_enable_win32_threads}" = "xyes" ; then
_efl_have_win32_threads="yes"
AC_DEFINE([EFL_HAVE_WIN32_THREADS], [1], [Define to mention that Win32 threads are supported])
fi
if test "x${_efl_have_posix_threads}" = "xyes" || test "x${_efl_have_win32_threads}" = "xyes" ; then
AC_DEFINE([EFL_HAVE_THREADS], [1], [Define to mention that POSIX or Win32 threads are supported])
fi
AS_IF([test "x$_efl_have_posix_threads" = "xyes" || test "x$_efl_have_win32_threads" = "xyes"], [$2], [$3])
AS_IF([test "x$_efl_have_posix_threads_spinlock" = "xyes"], [$4], [$5])
])

View File

@ -60,7 +60,7 @@ void *alloca (size_t);
# include <openssl/evp.h>
#endif
#ifdef EFL_HAVE_PTHREAD
#ifdef EFL_HAVE_POSIX_THREADS
# include <pthread.h>
#endif
@ -109,8 +109,12 @@ struct _Eet_File
time_t mtime;
#ifdef EFL_HAVE_PTHREAD
#ifdef EFL_HAVE_THREADS
# ifdef EFL_HAVE_POSIX_THREADS
pthread_mutex_t file_lock;
# else
HANDLE file_lock;
# endif
#endif
unsigned char writes_pending : 1;
@ -227,28 +231,45 @@ static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int
static Eet_Error eet_internal_close(Eet_File *ef, Eina_Bool locked);
#ifdef EFL_HAVE_PTHREAD
#ifdef EFL_HAVE_THREADS
# ifdef EFL_HAVE_POSIX_THREADS
static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER;
#define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock);
#define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock);
# define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock)
# define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock)
#define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL);
#define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock);
#define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock);
#define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock);
# define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL)
# define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock)
# define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock)
# define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock)
# else /* EFL_HAVE_WIN32_THREADS */
static HANDLE eet_cache_lock = NULL;
# define LOCK_CACHE WaitForSingleObject(eet_cache_lock, INFINITE)
# define UNLOCK_CACHE ReleaseMutex(eet_cache_lock)
# define INIT_FILE(File) File->file_lock = CreateMutex(NULL, FALSE, NULL)
# define LOCK_FILE(File) WaitForSingleObject(File->file_lock, INFINITE)
# define UNLOCK_FILE(File) ReleaseMutex(File->file_lock)
# define DESTROY_FILE(File) CloseHandle(File->file_lock)
# endif /* EFL_HAVE_WIN32_THREADS */
#else
#define LOCK_CACHE ;
#define UNLOCK_CACHE ;
# define LOCK_CACHE do {} while (0)
# define UNLOCK_CACHE do {} while (0)
#define INIT_FILE(File) ;
#define LOCK_FILE(File) ;
#define UNLOCK_FILE(File) ;
#define DESTROY_FILE(File) ;
# define INIT_FILE(File) do {} while (0)
# define LOCK_FILE(File) do {} while (0)
# define UNLOCK_FILE(File) do {} while (0)
# define DESTROY_FILE(File) do {} while (0)
#endif
#endif /* EFL_HAVE_THREADS */
/* cache. i don't expect this to ever be large, so arrays will do */
static int eet_writers_num = 0;

View File

@ -1,3 +1,8 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
@ -6,14 +11,13 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#ifdef EFL_HAVE_POSIX_THREADS
# include <pthread.h>
#endif
#include <check.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eina.h>
#include "eet_suite.h"
@ -1428,7 +1432,12 @@ START_TEST(eet_cipher_decipher_simple)
}
END_TEST
#ifdef EFL_HAVE_THREADS
static Eina_Bool open_worker_stop;
# ifdef EFL_HAVE_POSIX_THREADS
static void*
open_close_worker(void* path)
{
@ -1450,6 +1459,31 @@ open_close_worker(void* path)
pthread_exit(NULL);
}
# else
static unsigned int __stdcall
open_close_worker(void *path)
{
while (!open_worker_stop)
{
Eet_File *ef = eet_open((char const *)path, EET_FILE_MODE_READ);
if (ef == NULL)
{
_endthreadex(-1);
}
else
{
Eet_Error err_code = eet_close(ef);
if (err_code != EET_ERROR_NONE)
_endthreadex(-2);
}
}
_endthreadex(0);
}
# endif
START_TEST(eet_cache_concurrency)
{
char *file = strdup("/tmp/eet_suite_testXXXXXX");
@ -1457,6 +1491,13 @@ START_TEST(eet_cache_concurrency)
Eet_File *ef;
void *thread_ret;
unsigned int n;
# ifdef EFL_HAVE_POSIX_THREADS
pthread_t thread;
# else
uintptr_t thread;
unsigned int thread_id;
DWORD ret;
# endif
eet_init();
@ -1468,9 +1509,11 @@ START_TEST(eet_cache_concurrency)
/* start a thread that repeatedly opens and closes a file */
open_worker_stop = 0;
pthread_t thread;
# ifdef EFL_HAVE_POSIX_THREADS
pthread_create(&thread, NULL, open_close_worker, file);
# else
thread = _beginthreadex(NULL, 0, open_close_worker, file, 0, &thread_id);
# endif
/* clear the cache repeatedly in this thread */
for (n = 0; n < 50000; ++n)
{
@ -1479,14 +1522,23 @@ START_TEST(eet_cache_concurrency)
/* join the other thread, and fail if it returned an error message */
open_worker_stop = 1;
# ifdef EFL_HAVE_POSIX_THREADS
fail_if(pthread_join(thread, &thread_ret) != 0);
fail_unless(thread_ret == NULL, (char const*)thread_ret);
# else
ret = WaitForSingleObject((HANDLE)thread, INFINITE);
fail_if(ret != WAIT_OBJECT_0);
fail_if(GetExitCoeThread((HANDLE)thread, &ret) == FALSE);
fail_if(ret != 0)
# endif
fail_if(unlink(file) != 0);
eet_shutdown();
}
END_TEST
#endif /* EFL_HAVE_THREADS */
typedef struct _Eet_Connection_Data Eet_Connection_Data;
struct _Eet_Connection_Data
{
@ -2236,9 +2288,11 @@ eet_suite(void)
suite_add_tcase(s, tc);
#endif
#ifdef EFL_HAVE_THREADS
tc = tcase_create("Eet Cache");
tcase_add_test(tc, eet_cache_concurrency);
suite_add_tcase(s, tc);
#endif
tc = tcase_create("Eet Connection");
tcase_add_test(tc, eet_connection_check);