eio: associate data to a file behing listed assynchronously.

SVN revision: 60043
This commit is contained in:
Cedric BAIL 2011-06-07 16:30:10 +00:00
parent 260718c700
commit 19d5fb205a
4 changed files with 235 additions and 21 deletions

View File

@ -142,8 +142,30 @@ _eio_file_heavy(void *data, Ecore_Thread *thread)
filter = async->filter_cb((void*) async->ls.common.data, &async->ls.common, file);
}
if (filter) ecore_thread_feedback(thread, file);
else eina_stringshare_del(file);
if (filter)
{
Eio_File_Char *send;
send = eio_char_malloc();
if (!send) goto on_error;
send->filename = file;
send->associated = async->ls.common.worker.associated;
async->ls.common.worker.associated = NULL;
ecore_thread_feedback(thread, send);
}
else
{
on_error:
eina_stringshare_del(file);
if (async->ls.common.worker.associated)
{
eina_hash_free(async->ls.common.worker.associated);
async->ls.common.worker.associated = NULL;
}
}
if (ecore_thread_check(thread))
break;
@ -158,11 +180,22 @@ static void
_eio_file_notify(void *data, Ecore_Thread *thread __UNUSED__, void *msg_data)
{
Eio_File_Char_Ls *async = data;
const char *file = msg_data;
Eio_File_Char *info = msg_data;
async->main_cb((void*) async->ls.common.data, &async->ls.common, file);
async->ls.common.main.associated = info->associated;
eina_stringshare_del(file);
async->main_cb((void*) async->ls.common.data,
&async->ls.common,
info->filename);
if (async->ls.common.main.associated)
{
eina_hash_free(async->ls.common.main.associated);
async->ls.common.main.associated = NULL;
}
eina_stringshare_del(info->filename);
eio_char_free(info);
}
static void
@ -189,15 +222,22 @@ _eio_file_eina_ls_heavy(Ecore_Thread *thread, Eio_File_Direct_Ls *async, Eina_It
if (filter)
{
Eina_File_Direct_Info *send;
Eio_File_Direct_Info *send;
send = eio_direct_info_malloc();
if (!send) continue;
memcpy(send, info, sizeof (Eina_File_Direct_Info));
memcpy(&send->info, info, sizeof (Eina_File_Direct_Info));
send->associated = async->ls.common.worker.associated;
async->ls.common.worker.associated = NULL;
ecore_thread_feedback(thread, send);
}
else if (async->ls.common.worker.associated)
{
eina_hash_free(async->ls.common.worker.associated);
async->ls.common.worker.associated = NULL;
}
if (ecore_thread_check(thread))
break;
@ -234,16 +274,28 @@ static void
_eio_file_direct_notify(void *data, Ecore_Thread *thread __UNUSED__, void *msg_data)
{
Eio_File_Direct_Ls *async = data;
Eina_File_Direct_Info *info = msg_data;
Eio_File_Direct_Info *info = msg_data;
async->main_cb((void*) async->ls.common.data, &async->ls.common, info);
async->ls.common.main.associated = info->associated;
async->main_cb((void*) async->ls.common.data,
&async->ls.common,
&info->info);
if (async->ls.common.main.associated)
{
eina_hash_free(async->ls.common.main.associated);
async->ls.common.main.associated = NULL;
}
eio_direct_info_free(info);
}
#ifdef HAVE_XATTR
static void
_eio_file_copy_xattr(Ecore_Thread *thread, Eio_File_Progress *op, int in, int out)
_eio_file_copy_xattr(Ecore_Thread *thread __UNUSED__,
Eio_File_Progress *op __UNUSED__,
int in, int out)
{
char *tmp;
ssize_t length;
@ -849,6 +901,75 @@ eio_file_container_get(Eio_File *ls)
return ls->container;
}
/**
* @brief Associate data with the current filtered file.
* @param ls The Eio_File ls request currently calling the filter callback.
* @param key The key to associate data to.
* @param data The data to associate the data to.
* @param free_cb The function to call to free the associated data, @p free will be called if not specified.
* @return EINA_TRUE if insertion was fine.
*
* This function could only be safely called from within the filter callback.
* If you don't need to copy the key around you can use @ref eio_file_associate_direct_add
*/
EAPI Eina_Bool
eio_file_associate_add(Eio_File *ls,
const char *key,
void *data, Eina_Free_Cb free_cb)
{
/* FIXME: Check if we are in the right worker thred */
if (!ls->worker.associated)
ls->worker.associated = eina_hash_string_small_new(eio_associate_free);
return eina_hash_add(ls->worker.associated,
key,
eio_associate_malloc(data, free_cb));
}
/**
* @brief Associate data with the current filtered file.
* @param ls The Eio_File ls request currently calling the filter callback.
* @param key The key to associate data to (will not be copied, and the pointer will be used as long as the file is not notified).
* @param data The data to associate the data to.
* @param free_cb The function to call to free the associated data, @p free will be called if not specified.
* @return EINA_TRUE if insertion was fine.
*
* This function could only be safely called from within the filter callback.
* If you need eio to make a proper copy of the @p key to be safe use
* @ref eio_file_associate_add instead.
*/
EAPI Eina_Bool
eio_file_associate_direct_add(Eio_File *ls,
const char *key,
void *data, Eina_Free_Cb free_cb)
{
/* FIXME: Check if we are in the right worker thred */
if (!ls->worker.associated)
ls->worker.associated = eina_hash_string_small_new(eio_associate_free);
return eina_hash_direct_add(ls->worker.associated,
key,
eio_associate_malloc(data, free_cb));
}
/**
* @brief Get the data associated during the filter callback inside the main loop
* @param ls The Eio_File ls request currently calling the notify callback.
* @param key The key pointing to the data to retrieve.
* @return the data associated with the key or @p NULL if not found.
*/
EAPI void *
eio_file_associate_find(Eio_File *ls, const char *key)
{
Eio_File_Associate *search;
if (!ls->main.associated)
return NULL;
search = eina_hash_find(ls->main.associated, key);
if (!search) return NULL;
return search->data;
}
/**
* @brief Copy a file asynchronously

View File

@ -59,7 +59,9 @@ struct _Eio_Alloc_Pool
static int _eio_count = 0;
static Eio_Alloc_Pool progress_pool = { 0, NULL, EIO_MUTEX_INITIALIZER };
static Eio_Alloc_Pool direct_info = { 0, NULL, EIO_MUTEX_INITIALIZER };
static Eio_Alloc_Pool direct_info_pool = { 0, NULL, EIO_MUTEX_INITIALIZER };
static Eio_Alloc_Pool char_pool = { 0, NULL, EIO_MUTEX_INITIALIZER };
static Eio_Alloc_Pool associate_pool = { 0, NULL, EIO_MUTEX_INITIALIZER };
static void *
_eio_pool_malloc(Eio_Alloc_Pool *pool, size_t sz)
@ -142,18 +144,57 @@ eio_progress_send(Ecore_Thread *thread, Eio_File_Progress *op, long long current
ecore_thread_feedback(thread, progress);
}
Eina_File_Direct_Info *
Eio_File_Direct_Info *
eio_direct_info_malloc(void)
{
return _eio_pool_malloc(&direct_info, sizeof (Eina_File_Direct_Info));
return _eio_pool_malloc(&direct_info_pool, sizeof (Eio_File_Direct_Info));
}
void
eio_direct_info_free(Eina_File_Direct_Info *data)
eio_direct_info_free(Eio_File_Direct_Info *data)
{
_eio_pool_free(&direct_info, data);
_eio_pool_free(&direct_info_pool, data);
}
Eio_File_Char *
eio_char_malloc(void)
{
return _eio_pool_malloc(&char_pool, sizeof (Eio_File_Char));
}
void
eio_char_free(Eio_File_Char *data)
{
_eio_pool_free(&char_pool, data);
}
Eio_File_Associate *
eio_associate_malloc(void *data, Eina_Free_Cb free_cb)
{
Eio_File_Associate *tmp;
tmp = _eio_pool_malloc(&associate_pool, sizeof (Eio_File_Associate));
if (!tmp) return tmp;
tmp->data = data;
tmp->free_cb = free_cb ? free_cb : free;
return tmp;
}
void
eio_associate_free(void *data)
{
Eio_File_Associate *tmp;
if (!data) return ;
tmp = data;
tmp->free_cb(tmp->data);
_eio_pool_free(&associate_pool, tmp);
}
/**
* @endcond
*/
@ -184,7 +225,9 @@ eio_init(void)
ecore_init();
EIO_MUTEX_INIT(progress_pool);
EIO_MUTEX_INIT(direct_info);
EIO_MUTEX_INIT(direct_info_pool);
EIO_MUTEX_INIT(char_pool);
EIO_MUTEX_INIT(associate_pool);
eio_monitor_init();
@ -198,8 +241,10 @@ eio_init(void)
EAPI int
eio_shutdown(void)
{
Eina_File_Direct_Info *info;
Eio_File_Direct_Info *info;
Eio_File_Char *cin;
Eio_Progress *pg;
Eio_File_Associate *asso;
_eio_count--;
@ -207,15 +252,25 @@ eio_shutdown(void)
EIO_MUTEX_DESTROY(direct_info);
EIO_MUTEX_DESTROY(progress_pool);
EIO_MUTEX_DESTROY(char_pool);
EIO_MUTEX_DESTROY(associate_pool);
/* Cleanup pool */
EINA_TRASH_CLEAN(&progress_pool.trash, pg)
free(pg);
progress_pool.count = 0;
EINA_TRASH_CLEAN(&direct_info.trash, info)
EINA_TRASH_CLEAN(&direct_info_pool.trash, info)
free(info);
direct_info.count = 0;
direct_info_pool.count = 0;
EINA_TRASH_CLEAN(&char_pool.trash, cin)
free(cin);
char_pool.count = 0;
EINA_TRASH_CLEAN(&associate_pool.trash, asso)
free(asso);
associate_pool.count = 0;
ecore_shutdown();
eina_shutdown();

View File

@ -63,6 +63,32 @@ typedef struct _Eio_Monitor_Backend Eio_Monitor_Backend;
typedef struct _Eio_Dir_Copy Eio_Dir_Copy;
typedef struct _Eio_File_Direct_Info Eio_File_Direct_Info;
typedef struct _Eio_File_Char Eio_File_Char;
typedef struct _Eio_File_Associate Eio_File_Associate;
struct _Eio_File_Associate
{
void *data;
Eina_Free_Cb free_cb;
};
struct _Eio_File_Direct_Info
{
Eina_File_Direct_Info info;
Eina_Hash *associated;
};
struct _Eio_File_Char
{
const char *filename;
Eina_Hash *associated;
};
struct _Eio_File
{
Ecore_Thread *thread;
@ -73,6 +99,10 @@ struct _Eio_File
Eio_Error_Cb error_cb;
Eio_Done_Cb done_cb;
struct {
Eina_Hash *associated;
} worker, main;
};
struct _Eio_File_Ls
@ -198,8 +228,14 @@ void eio_file_container_set(Eio_File *common, void *container);
void eio_file_error(Eio_File *common);
void eio_file_thread_error(Eio_File *common, Ecore_Thread *thread);
Eina_File_Direct_Info *eio_direct_info_malloc(void);
void eio_direct_info_free(Eina_File_Direct_Info *data);
Eio_File_Direct_Info *eio_direct_info_malloc(void);
void eio_direct_info_free(Eio_File_Direct_Info *data);
Eio_File_Char *eio_char_malloc(void);
void eio_char_free(Eio_File_Char *data);
Eio_File_Associate *eio_associate_malloc(void *data, Eina_Free_Cb free_cb);
void eio_associate_free(void *data);
Eio_Progress *eio_progress_malloc(void);
void eio_progress_free(Eio_Progress *progress);

View File

@ -276,6 +276,8 @@ eio_long_file_set(Eio_File *common,
common->error = 0;
common->thread = NULL;
common->container = NULL;
common->worker.associated = NULL;
common->main.associated = NULL;
/* Be aware that ecore_thread_feedback_run could call cancel_cb if something goes wrong.
This means that common would be destroyed if thread == NULL.