forked from enlightenment/efl
* 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:
parent
7de1f120c2
commit
af13fe5496
|
@ -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}"
|
||||
|
|
|
@ -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
|
||||
])
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue