9 #ifdef EFL_HAVE_PTHREAD
14 #include "ecore_private.h"
16 typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker;
17 typedef struct _Ecore_Pthread Ecore_Pthread;
18 typedef struct _Ecore_Thread_Data Ecore_Thread_Data;
20 struct _Ecore_Thread_Data
26 struct _Ecore_Pthread_Worker
30 Ecore_Cb func_blocking;
33 Ecore_Thread_Heavy_Cb func_heavy;
34 Ecore_Thread_Notify_Cb func_notify;
41 #ifdef EFL_HAVE_PTHREAD
45 pthread_mutex_t mutex;
51 Eina_Bool long_run : 1;
54 #ifdef EFL_HAVE_PTHREAD
55 typedef struct _Ecore_Pthread_Data Ecore_Pthread_Data;
57 struct _Ecore_Pthread_Data
65 static int _ecore_thread_count_max = 0;
66 static int ECORE_THREAD_PIPE_DEL = 0;
68 #ifdef EFL_HAVE_PTHREAD
69 static int _ecore_thread_count = 0;
71 static Eina_List *_ecore_active_job_threads = NULL;
72 static Eina_List *_ecore_pending_job_threads = NULL;
73 static Eina_List *_ecore_pending_job_threads_long = NULL;
74 static Ecore_Event_Handler *del_handler = NULL;
75 static pthread_mutex_t _ecore_pending_job_threads_mutex = PTHREAD_MUTEX_INITIALIZER;
77 static Eina_Hash *_ecore_thread_global_hash = NULL;
78 static pthread_rwlock_t _ecore_thread_global_hash_lock = PTHREAD_RWLOCK_INITIALIZER;
79 static pthread_mutex_t _ecore_thread_global_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
80 static pthread_cond_t _ecore_thread_global_hash_cond = PTHREAD_COND_INITIALIZER;
81 static pthread_t main_loop_thread;
82 static Eina_Bool have_main_loop_thread = 0;
85 _ecore_thread_data_free(void *data)
87 Ecore_Thread_Data *d = data;
89 if (d->cb) d->cb(d->data);
94 _ecore_thread_pipe_free(void *data __UNUSED__, void *event)
96 Ecore_Pipe *p = event;
102 _ecore_thread_pipe_del(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
104 /* This is a hack to delay pipe destruction until we are out of its internal loop. */
105 return ECORE_CALLBACK_CANCEL;
109 _ecore_thread_end(Ecore_Pthread_Data *pth)
113 if (pthread_join(pth->thread, (void **) &p) != 0)
116 _ecore_active_job_threads = eina_list_remove(_ecore_active_job_threads, pth);
118 ecore_event_add(ECORE_THREAD_PIPE_DEL, pth->p, _ecore_thread_pipe_free, NULL);
123 _ecore_thread_handler(void *data __UNUSED__, void *buffer, unsigned int nbyte)
125 Ecore_Pthread_Worker *work;
127 if (nbyte != sizeof (Ecore_Pthread_Worker *)) return ;
129 work = *(Ecore_Pthread_Worker **)buffer;
133 if (work->func_cancel)
134 work->func_cancel((void *) work->data);
139 work->func_end((void *) work->data);
143 ecore_pipe_del(work->u.long_run.notify);
144 pthread_cond_destroy(&work->cond);
145 pthread_mutex_destroy(&work->mutex);
147 eina_hash_free(work->hash);
152 _ecore_notify_handler(void *data, void *buffer, unsigned int nbyte)
154 Ecore_Pthread_Worker *work = data;
157 if (nbyte != sizeof (Ecore_Pthread_Worker *)) return ;
159 user_data = *(void **)buffer;
161 if (work->u.long_run.func_notify)
162 work->u.long_run.func_notify((Ecore_Thread *) work, user_data, (void *) work->data);
166 _ecore_short_job(Ecore_Pipe *end_pipe)
168 Ecore_Pthread_Worker *work;
170 while (_ecore_pending_job_threads)
172 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
174 if (!_ecore_pending_job_threads)
176 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
180 work = eina_list_data_get(_ecore_pending_job_threads);
181 _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, _ecore_pending_job_threads);
183 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
186 work->u.short_run.func_blocking((void *) work->data);
188 ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
193 _ecore_long_job(Ecore_Pipe *end_pipe, pthread_t thread)
195 Ecore_Pthread_Worker *work;
197 while (_ecore_pending_job_threads_long)
199 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
201 if (!_ecore_pending_job_threads_long)
203 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
207 work = eina_list_data_get(_ecore_pending_job_threads_long);
208 _ecore_pending_job_threads_long = eina_list_remove_list(_ecore_pending_job_threads_long, _ecore_pending_job_threads_long);
210 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
214 work->u.long_run.func_heavy((Ecore_Thread *) work, (void *) work->data);
216 ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
221 _ecore_direct_worker(Ecore_Pthread_Worker *work)
223 Ecore_Pthread_Data *pth;
225 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
226 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
228 pth = malloc(sizeof (Ecore_Pthread_Data));
229 if (!pth) return NULL;
231 pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
237 pth->thread = pthread_self();
239 work->self = pth->thread;
240 work->u.long_run.func_heavy((Ecore_Thread *) work, (void *) work->data);
242 ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *));
244 work = malloc(sizeof (Ecore_Pthread_Worker));
247 ecore_pipe_del(pth->p);
253 work->u.short_run.func_blocking = NULL;
254 work->func_end = (void *) _ecore_thread_end;
255 work->func_cancel = NULL;
256 work->cancel = EINA_FALSE;
257 work->long_run = EINA_FALSE;
259 pthread_cond_init(&work->cond, NULL);
260 pthread_mutex_init(&work->mutex, NULL);
262 ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *));
268 _ecore_thread_worker(Ecore_Pthread_Data *pth)
270 Ecore_Pthread_Worker *work;
272 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
273 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
275 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
276 _ecore_thread_count++;
277 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
280 if (_ecore_pending_job_threads) _ecore_short_job(pth->p);
281 if (_ecore_pending_job_threads_long) _ecore_long_job(pth->p, pth->thread);
283 /* FIXME: Check if there is long running task todo, and switch to long run handler. */
285 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
286 if (_ecore_pending_job_threads)
288 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
291 if (_ecore_pending_job_threads_long)
293 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
297 _ecore_thread_count--;
299 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
301 work = malloc(sizeof (Ecore_Pthread_Worker));
302 if (!work) return NULL;
305 work->u.short_run.func_blocking = NULL;
306 work->func_end = (void *) _ecore_thread_end;
307 work->func_cancel = NULL;
308 work->cancel = EINA_FALSE;
309 work->long_run = EINA_FALSE;
311 pthread_cond_init(&work->cond, NULL);
312 pthread_mutex_init(&work->mutex, NULL);
314 ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *));
322 _ecore_thread_init(void)
324 _ecore_thread_count_max = eina_cpu_count();
325 if (_ecore_thread_count_max <= 0)
326 _ecore_thread_count_max = 1;
328 ECORE_THREAD_PIPE_DEL = ecore_event_type_new();
329 #ifdef EFL_HAVE_PTHREAD
330 del_handler = ecore_event_handler_add(ECORE_THREAD_PIPE_DEL, _ecore_thread_pipe_del, NULL);
331 main_loop_thread = pthread_self();
332 have_main_loop_thread = 1;
337 _ecore_thread_shutdown(void)
339 /* FIXME: If function are still running in the background, should we kill them ? */
340 #ifdef EFL_HAVE_PTHREAD
341 Ecore_Pthread_Worker *work;
342 Ecore_Pthread_Data *pth;
344 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
346 EINA_LIST_FREE(_ecore_pending_job_threads, work)
348 if (work->func_cancel)
349 work->func_cancel((void *)work->data);
353 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
355 EINA_LIST_FREE(_ecore_active_job_threads, pth)
359 pthread_cancel(pth->thread);
360 pthread_join(pth->thread, (void **) &p);
362 ecore_pipe_del(pth->p);
364 if (_ecore_thread_global_hash)
365 eina_hash_free(_ecore_thread_global_hash);
366 ecore_event_handler_del(del_handler);
367 have_main_loop_thread = 0;
372 * @addtogroup Ecore_Thread Ecore Thread Functions
373 * These functions allow for ecore-managed threads which integrate with ecore's main loop.
378 * @brief Run some blocking code in a parrallel thread to avoid locking the main loop.
379 * @param func_blocking The function that should run in another thread.
380 * @param func_end The function that will be called in the main loop if the thread terminate correctly.
381 * @param func_cancel The function that will be called in the main loop if the thread is cancelled.
382 * @param data User context data to pass to all callback.
383 * @return A reference to the newly created thread instance, or NULL if it failed.
385 * ecore_thread_run provide a facility for easily managing blocking task in a
386 * parallel thread. You should provide three function. The first one, func_blocking,
387 * that will do the blocking work in another thread (so you should not use the
388 * EFL in it except Eina if you are carefull). The second one, func_end,
389 * that will be called in Ecore main loop when func_blocking is done. So you
390 * can use all the EFL inside this function. The last one, func_cancel, will
391 * be called in the main loop if the thread is cancelled or could not run at all.
393 * Be aware, that you can't make assumption on the result order of func_end
394 * after many call to ecore_thread_run, as we start as much thread as the
395 * host CPU can handle.
398 ecore_thread_run(Ecore_Cb func_blocking,
400 Ecore_Cb func_cancel,
403 #ifdef EFL_HAVE_PTHREAD
404 Ecore_Pthread_Worker *work;
405 Ecore_Pthread_Data *pth = NULL;
407 if (!func_blocking) return NULL;
409 work = malloc(sizeof (Ecore_Pthread_Worker));
412 func_cancel((void *) data);
416 work->u.short_run.func_blocking = func_blocking;
418 pthread_cond_init(&work->cond, NULL);
419 pthread_mutex_init(&work->mutex, NULL);
420 work->func_end = func_end;
421 work->func_cancel = func_cancel;
422 work->cancel = EINA_FALSE;
423 work->long_run = EINA_FALSE;
426 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
427 _ecore_pending_job_threads = eina_list_append(_ecore_pending_job_threads, work);
429 if (_ecore_thread_count == _ecore_thread_count_max)
431 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
432 return (Ecore_Thread *) work;
435 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
437 /* One more thread could be created. */
438 pth = malloc(sizeof (Ecore_Pthread_Data));
439 if (!pth) goto on_error;
441 pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
442 if (!pth->p) goto on_error;
444 if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0)
445 return (Ecore_Thread *) work;
450 if (pth->p) ecore_pipe_del(pth->p);
454 if (_ecore_thread_count == 0)
456 if (work->func_cancel)
457 work->func_cancel((void *) work->data);
461 return (Ecore_Thread *) work;
464 If no thread and as we don't want to break app that rely on this
465 facility, we will lock the interface until we are done.
467 func_blocking((void *)data);
468 func_end((void *)data);
475 * @brief Cancel a running thread.
476 * @param thread The thread to cancel.
477 * @return Will return EINA_TRUE if the thread has been cancelled,
478 * EINA_FALSE if it is pending.
480 * ecore_thread_cancel give the possibility to cancel a task still running. It
481 * will return EINA_FALSE, if the destruction is delayed or EINA_TRUE if it is
482 * cancelled after this call.
484 * You should use this function only in the main loop.
486 * func_end, func_cancel will destroy the handler, so don't use it after.
487 * And if ecore_thread_cancel return EINA_TRUE, you should not use Ecore_Thread also.
490 ecore_thread_cancel(Ecore_Thread *thread)
492 #ifdef EFL_HAVE_PTHREAD
493 Ecore_Pthread_Worker *work = (Ecore_Pthread_Worker *) thread;
499 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
501 if ((have_main_loop_thread) &&
502 (pthread_equal(main_loop_thread, pthread_self())))
504 EINA_LIST_FOREACH(_ecore_pending_job_threads, l, work)
506 if ((void *) work == (void *) thread)
508 _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, l);
510 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
512 if (work->func_cancel)
513 work->func_cancel((void *) work->data);
521 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
523 /* Delay the destruction */
524 ((Ecore_Pthread_Worker *)thread)->cancel = EINA_TRUE;
532 * @brief Tell if a thread was canceled or not.
533 * @param thread The thread to test.
534 * @return EINA_TRUE if the thread is cancelled,
535 * EINA_FALSE if it is not.
537 * You can use this function in main loop and in the thread.
540 ecore_thread_check(Ecore_Thread *thread)
542 Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
544 if (!worker) return EINA_TRUE;
545 return worker->cancel;
549 * @brief Run some heavy code in a parrallel thread to avoid locking the main loop.
550 * @param func_heavy The function that should run in another thread.
551 * @param func_notify The function that will receive the data send by func_heavy in the main loop.
552 * @param func_end The function that will be called in the main loop if the thread terminate correctly.
553 * @param func_cancel The function that will be called in the main loop if the thread is cancelled.
554 * @param data User context data to pass to all callback.
555 * @param try_no_queue If you wan't to run outside of the thread pool.
556 * @return A reference to the newly created thread instance, or NULL if it failed.
558 * ecore_long_run provide a facility for easily managing heavy task in a
559 * parallel thread. You should provide four functions. The first one, func_heavy,
560 * that will do the heavy work in another thread (so you should not use the
561 * EFL in it except Eina and Eet if you are carefull). The second one, func_notify,
562 * will receive the data send from the thread function (func_heavy) by ecore_thread_notify
563 * in the main loop (and so, can use all the EFL). Tje third, func_end,
564 * that will be called in Ecore main loop when func_heavy is done. So you
565 * can use all the EFL inside this function. The last one, func_cancel, will
566 * be called in the main loop also, if the thread is cancelled or could not run at all.
568 * Be aware, that you can't make assumption on the result order of func_end
569 * after many call to ecore_long_run, as we start as much thread as the
570 * host CPU can handle.
572 * If you set try_no_queue, it will try to run outside of the thread pool, this can bring
573 * the CPU down, so be carefull with that. Of course if it can't start a new thread, it will
574 * try to use one from the pool.
576 EAPI Ecore_Thread *ecore_long_run(Ecore_Thread_Heavy_Cb func_heavy,
577 Ecore_Thread_Notify_Cb func_notify,
579 Ecore_Cb func_cancel,
581 Eina_Bool try_no_queue)
584 #ifdef EFL_HAVE_PTHREAD
585 Ecore_Pthread_Worker *worker;
586 Ecore_Pthread_Data *pth = NULL;
588 if (!func_heavy) return NULL;
590 worker = malloc(sizeof (Ecore_Pthread_Worker));
591 if (!worker) goto on_error;
593 worker->u.long_run.func_heavy = func_heavy;
594 worker->u.long_run.func_notify = func_notify;
596 pthread_cond_init(&worker->cond, NULL);
597 pthread_mutex_init(&worker->mutex, NULL);
598 worker->func_cancel = func_cancel;
599 worker->func_end = func_end;
601 worker->cancel = EINA_FALSE;
602 worker->long_run = EINA_TRUE;
604 worker->u.long_run.notify = ecore_pipe_add(_ecore_notify_handler, worker);
610 if (pthread_create(&t, NULL, (void *) _ecore_direct_worker, worker) == 0)
611 return (Ecore_Thread *) worker;
614 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
615 _ecore_pending_job_threads_long = eina_list_append(_ecore_pending_job_threads_long, worker);
617 if (_ecore_thread_count == _ecore_thread_count_max)
619 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
620 return (Ecore_Thread *) worker;
623 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
625 /* One more thread could be created. */
626 pth = malloc(sizeof (Ecore_Pthread_Data));
627 if (!pth) goto on_error;
629 pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
630 if (!pth->p) goto on_error;
632 if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0)
633 return (Ecore_Thread *) worker;
638 if (pth->p) ecore_pipe_del(pth->p);
642 if (_ecore_thread_count == 0)
644 if (func_cancel) func_cancel((void *) data);
648 ecore_pipe_del(worker->u.long_run.notify);
654 return (Ecore_Thread *) worker;
656 Ecore_Pthread_Worker worker;
661 If no thread and as we don't want to break app that rely on this
662 facility, we will lock the interface until we are done.
664 worker.u.long_run.func_heavy = func_heavy;
665 worker.u.long_run.func_notify = func_notify;
666 worker.u.long_run.notify = NULL;
667 worker.func_cancel = func_cancel;
668 worker.func_end = func_end;
670 worker.cancel = EINA_FALSE;
671 worker.long_run = EINA_TRUE;
673 func_heavy((Ecore_Thread *) &worker, (void *)data);
675 if (worker.cancel) func_cancel((void *)data);
676 else func_end((void *)data);
683 * @brief Send data to main loop from worker thread.
684 * @param thread The current Ecore_Thread context to send data from
685 * @param data Data to be transmitted to the main loop
686 * @return EINA_TRUE if data was successfully send to main loop,
687 * EINA_FALSE if anything goes wrong.
689 * After a succesfull call, the data should be considered owned
692 * You should use this function only in the func_heavy call.
695 ecore_thread_notify(Ecore_Thread *thread, const void *data)
697 Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
699 if (!worker) return EINA_FALSE;
700 if (!worker->long_run) return EINA_FALSE;
702 #ifdef EFL_HAVE_PTHREAD
703 if (!pthread_equal(worker->self, pthread_self())) return EINA_FALSE;
705 ecore_pipe_write(worker->u.long_run.notify, &data, sizeof (void *));
709 worker->u.long_run.func_notify(thread, (void*) data, (void*) worker->data);
716 * @brief Get number of active thread jobs
717 * @return Number of active threads running jobs
718 * This returns the number of threads currently running jobs through the
722 ecore_thread_active_get(void)
724 #ifdef EFL_HAVE_PTHREAD
725 return _ecore_thread_count;
732 * @brief Get number of pending (short) thread jobs
733 * @return Number of pending threads running "short" jobs
734 * This returns the number of threads currently running jobs through the
735 * ecore_thread_run api call.
738 ecore_thread_pending_get(void)
741 #ifdef EFL_HAVE_PTHREAD
742 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
743 ret = eina_list_count(_ecore_pending_job_threads);
744 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
752 * @brief Get number of pending long thread jobs
753 * @return Number of pending threads running "long" jobs
754 * This returns the number of threads currently running jobs through the
755 * ecore_long_run api call.
758 ecore_thread_pending_long_get(void)
761 #ifdef EFL_HAVE_PTHREAD
762 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
763 ret = eina_list_count(_ecore_pending_job_threads_long);
764 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
772 * @brief Get number of pending thread jobs
773 * @return Number of pending threads running jobs
774 * This returns the number of threads currently running jobs through the
775 * ecore_thread_run and ecore_long_run api calls combined.
778 ecore_thread_pending_total_get(void)
781 #ifdef EFL_HAVE_PTHREAD
782 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
783 ret = eina_list_count(_ecore_pending_job_threads) + eina_list_count(_ecore_pending_job_threads_long);
784 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
792 * @brief Get the max number of threads that can run simultaneously
793 * @return Max number of threads ecore will run
794 * This returns the total number of threads that ecore will attempt to run
798 ecore_thread_max_get(void)
800 return _ecore_thread_count_max;
804 * @brief Set the max number of threads that can run simultaneously
805 * @param num The new maximum
806 * This sets the maximum number of threads that ecore will try to run
807 * simultaneously. This number cannot be < 1 or >= 2x the number of active cpus.
810 ecore_thread_max_set(int num)
813 /* avoid doing something hilarious by blocking dumb users */
814 if (num >= (2 * eina_cpu_count())) return;
816 _ecore_thread_count_max = num;
820 * @brief Reset the max number of threads that can run simultaneously
821 * This resets the maximum number of threads that ecore will try to run
822 * simultaneously to the number of active cpus.
825 ecore_thread_max_reset(void)
827 _ecore_thread_count_max = eina_cpu_count();
831 * @brief Get the number of threads which are available to be used
832 * @return The number of available threads
833 * This returns the number of threads slots that ecore has currently available.
834 * Assuming that you haven't changed the max number of threads with @ref ecore_thread_max_set
835 * this should be equal to (num_cpus - (active_running + active_long_running))
838 ecore_thread_available_get(void)
841 #ifdef EFL_HAVE_PTHREAD
842 pthread_mutex_lock(&_ecore_pending_job_threads_mutex);
843 ret = _ecore_thread_count_max - _ecore_thread_count;
844 pthread_mutex_unlock(&_ecore_pending_job_threads_mutex);
852 * @brief Add data to the thread for subsequent use
853 * @param thread The thread context to add to
854 * @param key The name string to add the data with
855 * @param value The data to add
856 * @param cb The callback to free the data with
857 * @param direct If true, this will not copy the key string (like eina_hash_direct_add)
858 * @return EINA_TRUE on success, EINA_FALSE on failure
859 * This adds data to the thread context, allowing the thread
860 * to retrieve and use it without complicated mutexing. This function can only be called by a
861 * *_run thread INSIDE the thread and will return EINA_FALSE in any case but success.
862 * All data added to the thread will be freed with its associated callback (if present)
863 * upon thread termination. If no callback is specified, it is expected that the user will free the
864 * data, but this is most likely not what you want.
867 ecore_thread_local_data_add(Ecore_Thread *thread, const char *key, void *value, Eina_Free_Cb cb, Eina_Bool direct)
869 Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
870 Ecore_Thread_Data *d;
873 if ((!thread) || (!key) || (!value))
875 #ifdef EFL_HAVE_PTHREAD
876 if (!pthread_equal(worker->self, pthread_self())) return EINA_FALSE;
879 worker->hash = eina_hash_string_small_new(_ecore_thread_data_free);
884 if (!(d = malloc(sizeof(Ecore_Thread_Data))))
891 ret = eina_hash_direct_add(worker->hash, key, d);
893 ret = eina_hash_add(worker->hash, key, d);
894 pthread_cond_broadcast(&worker->cond);
902 * @brief Modify data in the thread, or add if not found
903 * @param thread The thread context
904 * @param key The name string to add the data with
905 * @param value The data to add
906 * @param cb The callback to free the data with
907 * @param direct If true, this will not copy the key string (like eina_hash_direct_add)
908 * @return The old data associated with @p key on success if modified, NULL if added
909 * This adds/modifies data in the thread context, adding only if modify fails.
910 * This function can only be called by a *_run thread INSIDE the thread.
911 * All data added to the thread pool will be freed with its associated callback (if present)
912 * upon thread termination. If no callback is specified, it is expected that the user will free the
913 * data, but this is most likely not what you want.
916 ecore_thread_local_data_set(Ecore_Thread *thread, const char *key, void *value, Eina_Free_Cb cb)
918 Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
919 Ecore_Thread_Data *d, *r;
921 if ((!thread) || (!key) || (!value))
923 #ifdef EFL_HAVE_PTHREAD
924 if (!pthread_equal(worker->self, pthread_self())) return NULL;
927 worker->hash = eina_hash_string_small_new(_ecore_thread_data_free);
932 if (!(d = malloc(sizeof(Ecore_Thread_Data))))
938 r = eina_hash_set(worker->hash, key, d);
939 pthread_cond_broadcast(&worker->cond);
949 * @brief Find data in the thread's data
950 * @param thread The thread context
951 * @param key The name string the data is associated with
952 * @return The value, or NULL on error
953 * This finds data in the thread context that has been previously added with @ref ecore_thread_local_data_add
954 * This function can only be called by a *_run thread INSIDE the thread, and will return NULL
955 * in any case but success.
959 ecore_thread_local_data_find(Ecore_Thread *thread, const char *key)
961 Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
962 Ecore_Thread_Data *d;
964 if ((!thread) || (!key))
966 #ifdef EFL_HAVE_PTHREAD
967 if (!pthread_equal(worker->self, pthread_self())) return NULL;
972 d = eina_hash_find(worker->hash, key);
980 * @brief Delete data from the thread's data
981 * @param thread The thread context
982 * @param key The name string the data is associated with
983 * @return EINA_TRUE on success, EINA_FALSE on failure
984 * This deletes the data pointer from the thread context which was previously added with @ref ecore_thread_local_data_add
985 * This function can only be called by a *_run thread INSIDE the thread, and will return EINA_FALSE
986 * in any case but success. Note that this WILL free the data if a callback was specified.
989 ecore_thread_local_data_del(Ecore_Thread *thread, const char *key)
991 Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
992 Ecore_Thread_Data *d;
993 if ((!thread) || (!key))
995 #ifdef EFL_HAVE_PTHREAD
996 if (!pthread_equal(worker->self, pthread_self())) return EINA_FALSE;
1000 if ((d = eina_hash_find(worker->hash, key)))
1001 _ecore_thread_data_free(d);
1002 return eina_hash_del_by_key(worker->hash, key);
1009 * @brief Add data to the global data
1010 * @param key The name string to add the data with
1011 * @param value The data to add
1012 * @param cb The optional callback to free the data with once ecore is shut down
1013 * @param direct If true, this will not copy the key string (like eina_hash_direct_add)
1014 * @return EINA_TRUE on success, EINA_FALSE on failure
1015 * This adds data to the global thread data, and will return EINA_FALSE in any case but success.
1016 * All data added to global can be manually freed, or a callback can be provided with @p cb which will
1017 * be called upon ecore_thread shutting down. Note that if you have manually freed data that a callback
1018 * was specified for, you will most likely encounter a segv later on.
1021 ecore_thread_global_data_add(const char *key, void *value, Eina_Free_Cb cb, Eina_Bool direct)
1024 Ecore_Thread_Data *d;
1026 if ((!key) || (!value))
1028 #ifdef EFL_HAVE_PTHREAD
1029 pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock);
1030 if (!_ecore_thread_global_hash)
1031 _ecore_thread_global_hash = eina_hash_string_small_new(_ecore_thread_data_free);
1032 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1034 if (!(d = malloc(sizeof(Ecore_Thread_Data))))
1040 if (!_ecore_thread_global_hash)
1042 pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock);
1044 ret = eina_hash_direct_add(_ecore_thread_global_hash, key, d);
1046 ret = eina_hash_add(_ecore_thread_global_hash, key, d);
1047 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1048 pthread_cond_broadcast(&_ecore_thread_global_hash_cond);
1056 * @brief Add data to the global data
1057 * @param key The name string to add the data with
1058 * @param value The data to add
1059 * @param cb The optional callback to free the data with once ecore is shut down
1060 * @return An @ref Ecore_Thread_Data on success, NULL on failure
1061 * This adds data to the global thread data and returns NULL, or replaces the previous data
1062 * associated with @p key and returning the previous data if it existed. To see if an error occurred,
1063 * one must use eina_error_get.
1064 * All data added to global can be manually freed, or a callback can be provided with @p cb which will
1065 * be called upon ecore_thread shutting down. Note that if you have manually freed data that a callback
1066 * was specified for, you will most likely encounter a segv later on.
1069 ecore_thread_global_data_set(const char *key, void *value, Eina_Free_Cb cb)
1071 Ecore_Thread_Data *d, *r;
1074 if ((!key) || (!value))
1076 #ifdef EFL_HAVE_PTHREAD
1077 pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock);
1078 if (!_ecore_thread_global_hash)
1079 _ecore_thread_global_hash = eina_hash_string_small_new(_ecore_thread_data_free);
1080 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1082 if (!_ecore_thread_global_hash)
1085 if (!(d = malloc(sizeof(Ecore_Thread_Data))))
1091 pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock);
1092 r = eina_hash_set(_ecore_thread_global_hash, key, d);
1093 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1094 pthread_cond_broadcast(&_ecore_thread_global_hash_cond);
1105 * @brief Find data in the global data
1106 * @param key The name string the data is associated with
1107 * @return The value, or NULL on error
1108 * This finds data in the global data that has been previously added with @ref ecore_thread_global_data_add
1109 * This function will return NULL in any case but success.
1110 * All data added to global can be manually freed, or a callback can be provided with @p cb which will
1111 * be called upon ecore_thread shutting down. Note that if you have manually freed data that a callback
1112 * was specified for, you will most likely encounter a segv later on.
1113 * @note Keep in mind that the data returned can be used by multiple threads at a time, so you will most likely want to mutex
1114 * if you will be doing anything with it.
1118 ecore_thread_global_data_find(const char *key)
1120 Ecore_Thread_Data *ret;
1123 #ifdef EFL_HAVE_PTHREAD
1124 if (!_ecore_thread_global_hash) return NULL;
1126 pthread_rwlock_rdlock(&_ecore_thread_global_hash_lock);
1127 ret = eina_hash_find(_ecore_thread_global_hash, key);
1128 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1136 * @brief Delete data from the global data
1137 * @param key The name string the data is associated with
1138 * @return EINA_TRUE on success, EINA_FALSE on failure
1139 * This deletes the data pointer from the global data which was previously added with @ref ecore_thread_global_data_add
1140 * This function will return EINA_FALSE in any case but success.
1141 * Note that this WILL free the data if an @c Eina_Free_Cb was specified when the data was added.
1144 ecore_thread_global_data_del(const char *key)
1147 Ecore_Thread_Data *d;
1151 #ifdef EFL_HAVE_PTHREAD
1152 if (!_ecore_thread_global_hash)
1155 pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock);
1156 if ((d = eina_hash_find(_ecore_thread_global_hash, key)))
1157 _ecore_thread_data_free(d);
1158 ret = eina_hash_del_by_key(_ecore_thread_global_hash, key);
1159 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1167 * @brief Find data in the global data and optionally wait for the data if not found
1168 * @param key The name string the data is associated with
1169 * @param seconds The amount of time in seconds to wait for the data. If 0, the call will be async and not wait for data.
1170 * If < 0 the call will wait indefinitely for the data.
1171 * @return The value, or NULL on failure
1172 * This finds data in the global data that has been previously added with @ref ecore_thread_global_data_add
1173 * This function will return NULL in any case but success.
1174 * Use @p seconds to specify the amount of time to wait. Use > 0 for an actual wait time, 0 to not wait, and < 0 to wait indefinitely.
1175 * @note Keep in mind that the data returned can be used by multiple threads at a time, so you will most likely want to mutex
1176 * if you will be doing anything with it.
1179 ecore_thread_global_data_wait(const char *key, double seconds)
1182 Ecore_Thread_Data *ret = NULL;
1185 #ifdef EFL_HAVE_PTHREAD
1186 if (!_ecore_thread_global_hash)
1189 time = ecore_time_get() + seconds;
1193 struct timespec t = { 0, 0 };
1195 t.tv_sec = (long int)time;
1196 t.tv_nsec = (long int)((time - (double)t.tv_sec) * 1000000000);
1197 pthread_rwlock_rdlock(&_ecore_thread_global_hash_lock);
1198 ret = eina_hash_find(_ecore_thread_global_hash, key);
1199 pthread_rwlock_unlock(&_ecore_thread_global_hash_lock);
1200 if ((ret) || (!seconds) || ((seconds > 0) && (time <= ecore_time_get())))
1202 pthread_mutex_lock(&_ecore_thread_global_hash_mutex);
1203 pthread_cond_timedwait(&_ecore_thread_global_hash_cond, &_ecore_thread_global_hash_mutex, &t);
1204 pthread_mutex_unlock(&_ecore_thread_global_hash_mutex);
1206 if (ret) return ret->data;