From ebd21717c654e69176fa6c6eeb4190281bc20478 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 22 Jul 2010 20:28:34 +0000 Subject: [PATCH] +ecore_thread_pool_data_{add,find,del}: start of ecore_thread_pool api. these calls are used from heavy_run to manage data within a thread pool. more to come SVN revision: 50438 --- legacy/ecore/src/lib/ecore/Ecore.h | 18 +-- legacy/ecore/src/lib/ecore/ecore_thread.c | 138 ++++++++++++++++++---- 2 files changed, 129 insertions(+), 27 deletions(-) diff --git a/legacy/ecore/src/lib/ecore/Ecore.h b/legacy/ecore/src/lib/ecore/Ecore.h index 204d398655..98de188da2 100644 --- a/legacy/ecore/src/lib/ecore/Ecore.h +++ b/legacy/ecore/src/lib/ecore/Ecore.h @@ -340,13 +340,17 @@ extern "C" { void (*func_cancel)(void *data), const void *data); EAPI Ecore_Thread *ecore_long_run(void (*func_heavy)(Ecore_Thread *thread, - void *data), - void (*func_notify)(Ecore_Thread *thread, - void *msg_data, void *data), - void (*func_end)(void *data), - void (*func_cancel)(void *data), - const void *data, - Eina_Bool try_no_queue); + void *data), + void (*func_notify)(Ecore_Thread *thread, + void *msg_data, void *data), + void (*func_end)(void *data), + void (*func_cancel)(void *data), + const void *data, + Eina_Bool try_no_queue); + EAPI Eina_Bool ecore_thread_pool_data_add(Ecore_Thread *thread, const char *key, + const void *value); + EAPI void *ecore_thread_pool_data_find(Ecore_Thread *thread, const char *key); + EAPI Eina_Bool ecore_thread_pool_data_del(Ecore_Thread *thread, const char *key); EAPI Eina_Bool ecore_thread_cancel(Ecore_Thread *thread); EAPI Eina_Bool ecore_thread_check(Ecore_Thread *thread); EAPI Eina_Bool ecore_thread_notify(Ecore_Thread *thread, const void *msg_data); diff --git a/legacy/ecore/src/lib/ecore/ecore_thread.c b/legacy/ecore/src/lib/ecore/ecore_thread.c index 3f0fe37c65..b5a7ef0dec 100644 --- a/legacy/ecore/src/lib/ecore/ecore_thread.c +++ b/legacy/ecore/src/lib/ecore/ecore_thread.c @@ -18,29 +18,32 @@ typedef struct _Ecore_Pthread Ecore_Pthread; struct _Ecore_Pthread_Worker { - union { - struct { - void (*func_blocking)(void *data); - } short_run; - struct { - void (*func_heavy)(Ecore_Thread *thread, void *data); - void (*func_notify)(Ecore_Thread *thread, void *msg_data, void *data); + union + { + struct + { + void (*func_blocking)(void *data); + } short_run; + struct + { + void (*func_heavy)(Ecore_Thread *thread, void *data); + void (*func_notify)(Ecore_Thread *thread, void *msg_data, void *data); - Ecore_Pipe *notify; + Ecore_Pipe *notify; + Eina_Hash *hash; + #ifdef EFL_HAVE_PTHREAD + pthread_t self; + #endif + } long_run; + } u; -#ifdef EFL_HAVE_PTHREAD - pthread_t self; -#endif - } long_run; - } u; + void (*func_cancel)(void *data); + void (*func_end)(void *data); - void (*func_cancel)(void *data); - void (*func_end)(void *data); + const void *data; - const void *data; - - Eina_Bool cancel : 1; - Eina_Bool long_run : 1; + Eina_Bool cancel : 1; + Eina_Bool long_run : 1; }; #ifdef EFL_HAVE_PTHREAD @@ -59,6 +62,7 @@ static int ECORE_THREAD_PIPE_DEL = 0; #ifdef EFL_HAVE_PTHREAD static int _ecore_thread_count = 0; +static Eina_Hash *_ecore_thread_global_hash = NULL; static Eina_List *_ecore_active_job_threads = NULL; static Eina_List *_ecore_pending_job_threads = NULL; static Eina_List *_ecore_pending_job_threads_long = NULL; @@ -114,7 +118,11 @@ _ecore_thread_handler(void *data __UNUSED__, void *buffer, unsigned int nbyte) work->func_end((void *) work->data); } - if (work->long_run) ecore_pipe_del(work->u.long_run.notify); + if (work->long_run) + { + ecore_pipe_del(work->u.long_run.notify); + eina_hash_free(work->u.long_run.hash); + } free(work); } @@ -538,6 +546,7 @@ ecore_long_run(void (*func_heavy)(Ecore_Thread *thread, void *data), worker->u.long_run.func_heavy = func_heavy; worker->u.long_run.func_notify = func_notify; + worker->u.long_run.hash = NULL; worker->func_cancel = func_cancel; worker->func_end = func_end; worker->data = data; @@ -606,6 +615,7 @@ ecore_long_run(void (*func_heavy)(Ecore_Thread *thread, void *data), */ worker.u.long_run.func_heavy = func_heavy; worker.u.long_run.func_notify = func_notify; + worker->u.long_run.hash = NULL; worker.u.long_run.notify = NULL; worker.func_cancel = func_cancel; worker.func_end = func_end; @@ -803,3 +813,91 @@ ecore_thread_available_get(void) return 0; #endif } + +/** + * @brief Add data to the pool for subsequent uses + * @param thread The thread context to add to + * @param key The name string to add the data with + * @param value The data to add + * @return EINA_TRUE on success, EINA_FALSE on failure + * This adds data to the thread context, allowing for subsequent users of the thread's pool + * to retrieve and use it without complicated mutexing. This function can only be called by a + * heavy_run thread INSIDE the thread and will return EINA_FALSE in any case but success. + * All data added to the thread pool must be freed in the thread's func_end/func_cancel + * functions to avoid leaks. + */ +EAPI Eina_Bool +ecore_thread_pool_data_add(Ecore_Thread *thread, const char *key, const void *value) +{ + Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread; + if ((!thread) || (!key) || (!value)) + return EINA_FALSE; +#ifdef EFL_HAVE_PTHREAD + if (worker->u.long_run.self != pthread_self()) return EINA_FALSE; + + if (!worker->u.long_run.hash) + worker->u.long_run.hash = eina_hash_string_small_new(NULL); + + if (!worker->u.long_run.hash) + return EINA_FALSE; + + return eina_hash_add(worker->u.long_run.hash, key, value); +#else + return EINA_TRUE; +#endif +} + +/** + * @brief Find data in the pool's data + * @param thread The thread context + * @param key The name string the data is associated with + * @return The value, or NULL on error + * This finds data in the thread context that has been previously added with @ref ecore_thread_pool_data_add + * This function can only be called by a heavy_run thread INSIDE the thread, and will return NULL + * in any case but success. + */ + +EAPI void * +ecore_thread_pool_data_find(Ecore_Thread *thread, const char *key) +{ + Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread; + if ((!thread) || (!key)) + return NULL; +#ifdef EFL_HAVE_PTHREAD + if (worker->u.long_run.self != pthread_self()) return NULL; + + if (!worker->u.long_run.hash) + return NULL; + + return eina_hash_find(worker->u.long_run.hash, key); +#else + return NULL; +#endif +} + +/** + * @brief Delete data from the pool's data + * @param thread The thread context + * @param key The name string the data is associated with + * @return EINA_TRUE on success, EINA_FALSE on failure + * This deletes the data pointer from the thread context which was previously added with @ref ecore_thread_pool_data_add + * This function can only be called by a heavy_run thread INSIDE the thread, and will return EINA_FALSE + * in any case but success. Note that this WILL NOT free the data, it merely removes it from the thread pool. + */ +EAPI Eina_Bool +ecore_thread_pool_data_del(Ecore_Thread *thread, const char *key) +{ + Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread; + if ((!thread) || (!key)) + return EINA_FALSE; +#ifdef EFL_HAVE_PTHREAD + if (worker->u.long_run.self != pthread_self()) return EINA_FALSE; + + if (!worker->u.long_run.hash) + return EINA_FALSE; + + return eina_hash_del_by_key(worker->u.long_run.hash, key); +#else + return EINA_TRUE; +#endif +}