* eet: All operation on Eet_File should be thread safe. This should

make use of all eet primitive thread safe now.

	Please any bug or lock that you find.


SVN revision: 44172
This commit is contained in:
Cedric BAIL 2009-12-03 15:35:04 +00:00
parent 7de1f120c2
commit af13fe5496
3 changed files with 196 additions and 36 deletions

View File

@ -175,11 +175,12 @@ AC_SUBST(pkgconfig_requires_private)
EFL_CHECK_DOXYGEN([build_doc="yes"], [build_doc="no"])
### Checks for libraries
# Evil library for compilation on Windows
EFL_CHECK_PTHREAD([have_pthread="yes"], [have_pthread="no"])
EFL_EET_BUILD=""
case "$host_os" in
mingw* | cegcc*)
@ -417,6 +418,7 @@ echo " Gnutls...............: ${have_gnutls}"
echo " Openssl..............: ${have_openssl}"
echo " Cipher support.....: ${have_cipher}"
echo " Signature..........: ${have_signature}"
echo " Thread Support.......: ${have_pthread}"
echo
echo " Amalgamation.........: ${do_amalgamation}"
echo " Documentation........: ${build_doc}"

View File

@ -0,0 +1,71 @@
dnl Copyright (C) 2008 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 ASM instruction sets are available or not.
dnl Usage: EFL_CHECK_EFL_CHECK_PTHREAD([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
dnl Call AC_SUBST(EFL_PTHREAD_FLAGS)
dnl Define EFL_HAVE_PTHREAD
AC_DEFUN([EFL_CHECK_PTHREAD],
[
dnl configure option
AC_ARG_ENABLE([pthread],
[AC_HELP_STRING([--disable-pthread], [enable POSIX threads code @<:@default=yes@:>@])],
[
if test "x${enableval}" = "xyes" ; then
_efl_enable_pthread="yes"
else
_efl_enable_pthread="no"
fi
],
[_efl_enable_pthread="yes"])
AC_MSG_CHECKING([whether to build POSIX threads code])
AC_MSG_RESULT([${_efl_enable_pthread}])
dnl check if the compiler supports pthreads
_efl_have_pthread="no"
if test "x${_efl_enable_pthread}" = "xyes" ; then
AC_CHECK_HEADER(pthread.h,
[_efl_have_pthread="yes"],
[_efl_have_pthread="no"])
fi
AC_MSG_CHECKING([whether system support POSIX threads])
AC_MSG_RESULT([${_efl_enable_pthread}])
if test "x${_efl_have_pthread}" = "xyes" ; then
case "$host_os" in
mingw*)
EFL_PTHREAD_CFLAGS="-mthreads"
EFL_PTHREAD_LIBS="-mthreads -lpthreadGC2"
;;
solaris*)
EFL_PTHREAD_CFLAGS="-mt"
EFL_PTHREAD_LIBS="-mt"
;;
*)
EFL_PTHREAD_CFLAGS="-pthread"
EFL_PTHREAD_LIBS="-pthread"
;;
esac
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
if test "x${_efl_have_pthread}" = "xyes" ; then
ifelse([$1], , :, [$1])
else
ifelse([$2], , :, [$2])
fi
])

View File

@ -60,6 +60,23 @@ void *alloca (size_t);
# include <openssl/evp.h>
#endif
#ifdef EFL_HAVE_PTHREAD
# ifdef _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# elif defined (__SUNPRO_C)
# include <unistd.h>
# elif defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) || defined (__DragonFly__) || defined (__MacOSX__) || ( defined (__MACH__) && defined (__APPLE__))
# include <unistd.h>
# include <sys/param.h>
# include <sys/sysctl.h>
# elif defined (__linux__)
# define _GNU_SOURCE
# include <sched.h>
# endif
# include <pthread.h>
#endif
#include <Eina.h>
#include "Eet.h"
@ -103,6 +120,10 @@ struct _Eet_File
time_t mtime;
#ifdef EFL_HAVE_PTHREAD
pthread_mutex_t file_lock;
#endif
unsigned char writes_pending : 1;
unsigned char delete_me_now : 1;
};
@ -210,6 +231,29 @@ static Eet_Error eet_flush2(Eet_File *ef);
static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name);
static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
#ifdef EFL_HAVE_PTHREAD
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 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
#define LOCK_CACHE ;
#define UNLOCK_CACHE ;
#define INIT_FILE(File) ;
#define LOCK_FILE(File) ;
#define UNLOCK_FILE(File) ;
#define DESTROY_FILE(File) ;
#endif
/* cache. i don't expect this to ever be large, so arrays will do */
static int eet_writers_num = 0;
static int eet_writers_alloc = 0;
@ -1279,6 +1323,7 @@ eet_memopen_read(const void *data, size_t size)
if (!ef)
return NULL;
INIT_FILE(ef);
ef->ed = NULL;
ef->path = NULL;
ef->key = NULL;
@ -1311,6 +1356,7 @@ eet_open(const char *file, Eet_File_Mode mode)
/* find the current file handle in cache*/
ef = NULL;
LOCK_CACHE;
if (mode == EET_FILE_MODE_READ)
{
ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
@ -1335,6 +1381,7 @@ eet_open(const char *file, Eet_File_Mode mode)
}
ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
}
UNLOCK_CACHE;
/* try open the file based on mode */
if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
@ -1399,6 +1446,7 @@ eet_open(const char *file, Eet_File_Mode mode)
return NULL;
/* fill some of the members */
INIT_FILE(ef);
ef->fp = fp;
ef->key = NULL;
ef->readfp = NULL;
@ -1451,11 +1499,13 @@ eet_open(const char *file, Eet_File_Mode mode)
/* add to cache */
if (ef->references == 1)
{
LOCK_CACHE;
if (ef->mode == EET_FILE_MODE_READ)
eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
else
if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
UNLOCK_CACHE;
}
return ef;
@ -1539,10 +1589,14 @@ eet_close(Eet_File *ef)
return EET_ERROR_NONE;
/* remove from cache */
LOCK_CACHE;
if (ef->mode == EET_FILE_MODE_READ)
eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
UNLOCK_CACHE;
DESTROY_FILE(ef);
/* free up data */
if (ef->header)
@ -1616,18 +1670,18 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe
if (eet_check_header(ef))
return NULL;
LOCK_FILE(ef);
/* hunt hash bucket */
efn = find_node_by_name(ef, name);
if (!efn)
return NULL;
if (!efn) goto on_error;
/* get size (uncompressed, if compressed at all) */
size = efn->data_size;
/* allocate data */
data = malloc(size);
if (!data)
return NULL;
if (!data) goto on_error;
/* uncompressed data */
if (efn->compression == 0)
@ -1639,17 +1693,13 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe
memcpy(data, efn->data, efn->size);
else
if (!read_data_from_disk(ef, efn, data, size))
{
free(data);
return NULL;
}
goto on_error;
if (efn->ciphered && cipher_key)
{
if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
{
free(data);
if (data_deciphered) free(data_deciphered);
return NULL;
goto on_error;
}
free(data);
data = data_deciphered;
@ -1673,18 +1723,14 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe
{
tmp_data = malloc(compr_size);
if (!tmp_data)
{
free(data);
return NULL;
}
goto on_error;
free_tmp = 1;
if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
{
free(tmp_data);
free(data);
return NULL;
goto on_error;
}
}
@ -1692,10 +1738,9 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe
{
if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
{
free(data);
if (free_tmp) free(tmp_data);
if (data_deciphered) free(data_deciphered);
return NULL;
goto on_error;
}
free(tmp_data);
tmp_data = data_deciphered;
@ -1706,10 +1751,7 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe
dlen = size;
if (uncompress((Bytef *)data, &dlen,
tmp_data, (uLongf)compr_size))
{
free(data);
return NULL;
}
goto on_error;
if (free_tmp)
free(tmp_data);
@ -1719,7 +1761,14 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe
if (size_ret)
*size_ret = size;
UNLOCK_FILE(ef);
return data;
on_error:
UNLOCK_FILE(ef);
free(data);
return NULL;
}
EAPI void *
@ -1751,13 +1800,14 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
if (eet_check_header(ef))
return NULL;
LOCK_FILE(ef);
/* hunt hash bucket */
efn = find_node_by_name(ef, name);
if (!efn)
return NULL;
if (!efn) goto on_error;
if (efn->offset < 0 && efn->data == NULL)
return NULL;
goto on_error;
/* get size (uncompressed, if compressed at all) */
size = efn->data_size;
@ -1774,7 +1824,13 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
if (size_ret)
*size_ret = size;
UNLOCK_FILE(ef);
return data;
on_error:
UNLOCK_FILE(ef);
return NULL;
}
EAPI int
@ -1795,25 +1851,35 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int
(ef->mode != EET_FILE_MODE_READ_WRITE))
return 0;
LOCK_FILE(ef);
if (!ef->header)
{
/* allocate header */
ef->header = calloc(1, sizeof(Eet_File_Header));
if (!ef->header)
return 0;
goto on_error;
ef->header->magic = EET_MAGIC_FILE_HEADER;
/* allocate directory block in ram */
ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
if (!ef->header->directory)
return 0;
{
free(ef->header);
ef->header = NULL;
goto on_error;
}
/* 8 bit hash table (256 buckets) */
ef->header->directory->size = 8;
/* allocate base hash table */
ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
if (!ef->header->directory->nodes)
return 0;
{
free(ef->header->directory);
ef->header = NULL;
goto on_error;
}
}
/* figure hash bucket */
@ -1824,8 +1890,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int
if (compress || !cipher_key)
{
data2 = malloc(data_size);
if (!data2)
return 0;
if (!data2) goto on_error;
}
/* if we want to compress */
@ -1905,7 +1970,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int
if (!efn)
{
free(data2);
return 0;
goto on_error;
}
efn->name = strdup(name);
efn->name_size = strlen(efn->name) + 1;
@ -1923,7 +1988,12 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int
/* flags that writes are pending */
ef->writes_pending = 1;
UNLOCK_FILE(ef);
return data_size;
on_error:
UNLOCK_FILE(ef);
return 0;
}
EAPI int
@ -1953,6 +2023,8 @@ eet_delete(Eet_File *ef, const char *name)
if (eet_check_header(ef))
return 0;
LOCK_FILE(ef);
/* figure hash bucket */
hash = _eet_hash_gen(name, ef->header->directory->size);
@ -1982,6 +2054,8 @@ eet_delete(Eet_File *ef, const char *name)
if (exists_already)
ef->writes_pending = 1;
UNLOCK_FILE(ef);
/* update access time */
return exists_already;
}
@ -2016,6 +2090,8 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret)
return NULL;
}
LOCK_FILE(ef);
/* loop through all entries */
num = (1 << ef->header->directory->size);
for (i = 0; i < num; i++)
@ -2042,10 +2118,7 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret)
{
free(list_ret);
if (count_ret)
*count_ret = 0;
return NULL;
goto on_error;
}
list_ret = new_list;
}
@ -2056,11 +2129,21 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret)
}
}
UNLOCK_FILE(ef);
/* return count and list */
if (count_ret)
*count_ret = list_count;
return list_ret;
on_error:
UNLOCK_FILE(ef);
if (count_ret)
*count_ret = 0;
return NULL;
}
EAPI int
@ -2075,6 +2158,8 @@ eet_num_entries(Eet_File *ef)
(ef->mode != EET_FILE_MODE_READ_WRITE)))
return -1;
LOCK_FILE(ef);
/* loop through all entries */
num = (1 << ef->header->directory->size);
for (i = 0; i < num; i++)
@ -2083,6 +2168,8 @@ eet_num_entries(Eet_File *ef)
ret++;
}
UNLOCK_FILE(ef);
return ret;
}