+ecore_thread_pool_data_modify_or_add
[profile/ivi/ecore.git] / src / lib / ecore / ecore_thread.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef HAVE_EVIL
6 # include <Evil.h>
7 #endif
8
9 #ifdef EFL_HAVE_PTHREAD
10 # include <pthread.h>
11 #endif
12
13 #include "Ecore.h"
14 #include "ecore_private.h"
15
16 typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker;
17 typedef struct _Ecore_Pthread Ecore_Pthread;
18
19 struct _Ecore_Pthread_Worker
20 {
21    union
22      {
23        struct
24          {
25             void (*func_blocking)(void *data);
26          } short_run;
27         struct
28           {
29              void (*func_heavy)(Ecore_Thread *thread, void *data);
30              void (*func_notify)(Ecore_Thread *thread, void *msg_data, void *data);
31
32              Ecore_Pipe *notify;
33              Eina_Hash *hash;
34  #ifdef EFL_HAVE_PTHREAD
35              pthread_t self;
36  #endif
37           } long_run;
38      } u;
39
40     void (*func_cancel)(void *data);
41     void (*func_end)(void *data);
42
43     const void *data;
44
45     Eina_Bool cancel : 1;
46     Eina_Bool long_run : 1;
47 };
48
49 #ifdef EFL_HAVE_PTHREAD
50 typedef struct _Ecore_Pthread_Data Ecore_Pthread_Data;
51
52 struct _Ecore_Pthread_Data
53 {
54    Ecore_Pipe *p;
55    void *data;
56    pthread_t thread;
57 };
58 #endif
59
60 static int _ecore_thread_count_max = 0;
61 static int ECORE_THREAD_PIPE_DEL = 0;
62
63 #ifdef EFL_HAVE_PTHREAD
64 static int _ecore_thread_count = 0;
65 static Eina_Hash *_ecore_thread_global_hash = NULL;
66 static Eina_List *_ecore_active_job_threads = NULL;
67 static Eina_List *_ecore_pending_job_threads = NULL;
68 static Eina_List *_ecore_pending_job_threads_long = NULL;
69 static Ecore_Event_Handler *del_handler = NULL;
70
71 static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
72
73 static void
74 _ecore_thread_pipe_free(void *data __UNUSED__, void *event)
75 {
76    Ecore_Pipe *p = event;
77
78    ecore_pipe_del(p);
79 }
80
81 static Eina_Bool
82 _ecore_thread_pipe_del(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
83 {
84    /* This is a hack to delay pipe destruction until we are out of it's internal loop. */
85    return ECORE_CALLBACK_CANCEL;
86 }
87
88 static void
89 _ecore_thread_end(Ecore_Pthread_Data *pth)
90 {
91    Ecore_Pipe *p;
92
93    if (pthread_join(pth->thread, (void **) &p) != 0)
94      return ;
95
96    _ecore_active_job_threads = eina_list_remove(_ecore_active_job_threads, pth);
97
98    ecore_event_add(ECORE_THREAD_PIPE_DEL, pth->p, _ecore_thread_pipe_free, NULL);
99 }
100
101 static void
102 _ecore_thread_handler(void *data __UNUSED__, void *buffer, unsigned int nbyte)
103 {
104    Ecore_Pthread_Worker *work;
105
106    if (nbyte != sizeof (Ecore_Pthread_Worker *)) return ;
107
108    work = *(Ecore_Pthread_Worker **)buffer;
109
110    if (work->cancel)
111      {
112         if (work->func_cancel)
113           work->func_cancel((void *) work->data);
114      }
115    else
116      {
117         if (work->func_end)
118           work->func_end((void *) work->data);
119      }
120
121    if (work->long_run)
122      {
123         ecore_pipe_del(work->u.long_run.notify);
124         eina_hash_free(work->u.long_run.hash);
125      }
126    free(work);
127 }
128
129 static void
130 _ecore_notify_handler(void *data, void *buffer, unsigned int nbyte)
131 {
132    Ecore_Pthread_Worker *work = data;
133    void *user_data;
134
135    if (nbyte != sizeof (Ecore_Pthread_Worker *)) return ;
136
137    user_data = *(void **)buffer;
138
139    if (work->u.long_run.func_notify)
140      work->u.long_run.func_notify((Ecore_Thread *) work, user_data, (void *) work->data);
141 }
142
143 static void
144 _ecore_short_job(Ecore_Pipe *end_pipe)
145 {
146    Ecore_Pthread_Worker *work;
147
148    while (_ecore_pending_job_threads)
149      {
150         pthread_mutex_lock(&_mutex);
151
152         if (!_ecore_pending_job_threads)
153           {
154              pthread_mutex_unlock(&_mutex);
155              break;
156           }
157
158         work = eina_list_data_get(_ecore_pending_job_threads);
159         _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, _ecore_pending_job_threads);
160
161         pthread_mutex_unlock(&_mutex);
162
163         work->u.short_run.func_blocking((void *) work->data);
164
165         ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
166      }
167 }
168
169 static void
170 _ecore_long_job(Ecore_Pipe *end_pipe, pthread_t thread)
171 {
172    Ecore_Pthread_Worker *work;
173
174    while (_ecore_pending_job_threads_long)
175      {
176         pthread_mutex_lock(&_mutex);
177
178         if (!_ecore_pending_job_threads_long)
179           {
180              pthread_mutex_unlock(&_mutex);
181              break;
182           }
183
184         work = eina_list_data_get(_ecore_pending_job_threads_long);
185         _ecore_pending_job_threads_long = eina_list_remove_list(_ecore_pending_job_threads_long, _ecore_pending_job_threads_long);
186
187         pthread_mutex_unlock(&_mutex);
188
189         work->u.long_run.self = thread;
190         work->u.long_run.func_heavy((Ecore_Thread *) work, (void *) work->data);
191
192         ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
193      }
194 }
195
196 static void *
197 _ecore_direct_worker(Ecore_Pthread_Worker *work)
198 {
199    Ecore_Pthread_Data *pth;
200
201    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
202    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
203
204    pth = malloc(sizeof (Ecore_Pthread_Data));
205    if (!pth) return NULL;
206
207    pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
208    if (!pth->p)
209      {
210         free(pth);
211         return NULL;
212      }
213    pth->thread = pthread_self();
214
215    work->u.long_run.self = pth->thread;
216    work->u.long_run.func_heavy((Ecore_Thread *) work, (void *) work->data);
217
218    ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *));
219
220    work = malloc(sizeof (Ecore_Pthread_Worker));
221    if (!work)
222      {
223         ecore_pipe_del(pth->p);
224         free(pth);
225         return NULL;
226      }
227
228    work->data = pth;
229    work->u.short_run.func_blocking = NULL;
230    work->func_end = (void *) _ecore_thread_end;
231    work->func_cancel = NULL;
232    work->cancel = EINA_FALSE;
233    work->long_run = EINA_FALSE;
234
235    ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *));
236
237    return pth->p;
238 }
239
240 static void *
241 _ecore_thread_worker(Ecore_Pthread_Data *pth)
242 {
243    Ecore_Pthread_Worker *work;
244
245    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
246    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
247
248    pthread_mutex_lock(&_mutex);
249    _ecore_thread_count++;
250    pthread_mutex_unlock(&_mutex);
251
252  on_error:
253    if (_ecore_pending_job_threads) _ecore_short_job(pth->p);
254    if (_ecore_pending_job_threads_long) _ecore_long_job(pth->p, pth->thread);
255
256    /* FIXME: Check if there is long running task todo, and switch to long run handler. */
257
258    pthread_mutex_lock(&_mutex);
259    if (_ecore_pending_job_threads)
260      {
261         pthread_mutex_unlock(&_mutex);
262         goto on_error;
263      }
264    if (_ecore_pending_job_threads_long)
265      {
266         pthread_mutex_unlock(&_mutex);
267         goto on_error;
268      }
269
270    _ecore_thread_count--;
271
272    pthread_mutex_unlock(&_mutex);
273
274    work = malloc(sizeof (Ecore_Pthread_Worker));
275    if (!work) return NULL;
276
277    work->data = pth;
278    work->u.short_run.func_blocking = NULL;
279    work->func_end = (void *) _ecore_thread_end;
280    work->func_cancel = NULL;
281    work->cancel = EINA_FALSE;
282    work->long_run = EINA_FALSE;
283
284    ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *));
285
286    return pth->p;
287 }
288
289 #endif
290
291 void
292 _ecore_thread_init(void)
293 {
294    _ecore_thread_count_max = eina_cpu_count();
295    if (_ecore_thread_count_max <= 0)
296      _ecore_thread_count_max = 1;
297
298    ECORE_THREAD_PIPE_DEL = ecore_event_type_new();
299 #ifdef EFL_HAVE_PTHREAD
300    del_handler = ecore_event_handler_add(ECORE_THREAD_PIPE_DEL, _ecore_thread_pipe_del, NULL);
301 #endif
302 }
303
304 void
305 _ecore_thread_shutdown(void)
306 {
307    /* FIXME: If function are still running in the background, should we kill them ? */
308 #ifdef EFL_HAVE_PTHREAD
309    Ecore_Pthread_Worker *work;
310    Ecore_Pthread_Data *pth;
311
312    pthread_mutex_lock(&_mutex);
313
314    EINA_LIST_FREE(_ecore_pending_job_threads, work)
315      {
316         if (work->func_cancel)
317           work->func_cancel((void *)work->data);
318         free(work);
319      }
320
321    pthread_mutex_unlock(&_mutex);
322
323    EINA_LIST_FREE(_ecore_active_job_threads, pth)
324      {
325         Ecore_Pipe *p;
326
327         pthread_cancel(pth->thread);
328         pthread_join(pth->thread, (void **) &p);
329
330         ecore_pipe_del(pth->p);
331      }
332
333    ecore_event_handler_del(del_handler);
334    del_handler = NULL;
335 #endif
336 }
337 /**
338  * @defgroup Ecore_Thread Ecore Thread Functions
339  * These functions allow for ecore-managed threads which integrate with ecore's main loop.
340  */
341
342 /**
343  * @brief Run some blocking code in a parrallel thread to avoid locking the main loop.
344  * @param func_blocking The function that should run in another thread.
345  * @param func_end The function that will be called in the main loop if the thread terminate correctly.
346  * @param func_cancel The function that will be called in the main loop if the thread is cancelled.
347  * @param data User context data to pass to all callback.
348  * @return A reference to the newly created thread instance, or NULL if it failed.
349  *
350  * ecore_thread_run provide a facility for easily managing blocking task in a
351  * parallel thread. You should provide three function. The first one, func_blocking,
352  * that will do the blocking work in another thread (so you should not use the
353  * EFL in it except Eina if you are carefull). The second one, func_end,
354  * that will be called in Ecore main loop when func_blocking is done. So you
355  * can use all the EFL inside this function. The last one, func_cancel, will
356  * be called in the main loop if the thread is cancelled or could not run at all.
357  *
358  * Be aware, that you can't make assumption on the result order of func_end
359  * after many call to ecore_thread_run, as we start as much thread as the
360  * host CPU can handle.
361  */
362 EAPI Ecore_Thread *
363 ecore_thread_run(void (*func_blocking)(void *data),
364    void (*func_end)(void *data),
365    void (*func_cancel)(void *data),
366    const void *data)
367 {
368 #ifdef EFL_HAVE_PTHREAD
369    Ecore_Pthread_Worker *work;
370    Ecore_Pthread_Data *pth = NULL;
371
372    if (!func_blocking) return NULL;
373
374    work = malloc(sizeof (Ecore_Pthread_Worker));
375    if (!work)
376      {
377         func_cancel((void *) data);
378         return NULL;
379      }
380
381    work->u.short_run.func_blocking = func_blocking;
382    work->func_end = func_end;
383    work->func_cancel = func_cancel;
384    work->cancel = EINA_FALSE;
385    work->long_run = EINA_FALSE;
386    work->data = data;
387
388    pthread_mutex_lock(&_mutex);
389    _ecore_pending_job_threads = eina_list_append(_ecore_pending_job_threads, work);
390
391    if (_ecore_thread_count == _ecore_thread_count_max)
392      {
393         pthread_mutex_unlock(&_mutex);
394         return (Ecore_Thread *) work;
395      }
396
397    pthread_mutex_unlock(&_mutex);
398
399    /* One more thread could be created. */
400    pth = malloc(sizeof (Ecore_Pthread_Data));
401    if (!pth) goto on_error;
402
403    pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
404    if (!pth->p) goto on_error;
405
406    if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0)
407      return (Ecore_Thread *) work;
408
409  on_error:
410    if (pth)
411      {
412         if (pth->p) ecore_pipe_del(pth->p);
413         free(pth);
414      }
415
416    if (_ecore_thread_count == 0)
417      {
418         if (work->func_cancel)
419           work->func_cancel((void *) work->data);
420         free(work);
421         work = NULL;
422      }
423    return (Ecore_Thread *) work;
424 #else
425    /*
426      If no thread and as we don't want to break app that rely on this
427      facility, we will lock the interface until we are done.
428     */
429    func_blocking((void *)data);
430    func_end((void *)data);
431
432    return NULL;
433 #endif
434 }
435
436 /**
437  * @brief Cancel a running thread.
438  * @param thread The thread to cancel.
439  * @return Will return EINA_TRUE if the thread has been cancelled,
440  *         EINA_FALSE if it is pending.
441  *
442  * ecore_thread_cancel give the possibility to cancel a task still running. It
443  * will return EINA_FALSE, if the destruction is delayed or EINA_TRUE if it is
444  * cancelled after this call.
445  *
446  * You should use this function only in the main loop.
447  *
448  * func_end, func_cancel will destroy the handler, so don't use it after.
449  * And if ecore_thread_cancel return EINA_TRUE, you should not use Ecore_Thread also.
450  */
451 EAPI Eina_Bool
452 ecore_thread_cancel(Ecore_Thread *thread)
453 {
454 #ifdef EFL_HAVE_PTHREAD
455    Ecore_Pthread_Worker *work;
456    Eina_List *l;
457
458    pthread_mutex_lock(&_mutex);
459
460    EINA_LIST_FOREACH(_ecore_pending_job_threads, l, work)
461      if ((void *) work == (void *) thread)
462        {
463          _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, l);
464
465          pthread_mutex_unlock(&_mutex);
466
467          if (work->func_cancel)
468            work->func_cancel((void *) work->data);
469          free(work);
470
471          return EINA_TRUE;
472        }
473
474    pthread_mutex_unlock(&_mutex);
475
476    /* Delay the destruction */
477    ((Ecore_Pthread_Worker *)thread)->cancel = EINA_TRUE;
478    return EINA_FALSE;
479 #else
480    return EINA_TRUE;
481 #endif
482 }
483
484 /**
485  * @brief Tell if a thread was canceled or not.
486  * @param thread The thread to test.
487  * @return EINA_TRUE if the thread is cancelled,
488  *         EINA_FALSE if it is not.
489  *
490  * You can use this function in main loop and in the thread.
491  */
492 EAPI Eina_Bool
493 ecore_thread_check(Ecore_Thread *thread)
494 {
495    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
496
497    if (!worker) return EINA_TRUE;
498    return worker->cancel;
499 }
500
501 /**
502  * @brief Run some heavy code in a parrallel thread to avoid locking the main loop.
503  * @param func_heavy The function that should run in another thread.
504  * @param func_notify The function that will receive the data send by func_heavy in the main loop.
505  * @param func_end The function that will be called in the main loop if the thread terminate correctly.
506  * @param func_cancel The function that will be called in the main loop if the thread is cancelled.
507  * @param data User context data to pass to all callback.
508  * @param try_no_queue If you wan't to run outside of the thread pool.
509  * @return A reference to the newly created thread instance, or NULL if it failed.
510  *
511  * ecore_long_run provide a facility for easily managing heavy task in a
512  * parallel thread. You should provide four functions. The first one, func_heavy,
513  * that will do the heavy work in another thread (so you should not use the
514  * EFL in it except Eina and Eet if you are carefull). The second one, func_notify,
515  * will receive the data send from the thread function (func_heavy) by ecore_thread_notify
516  * in the main loop (and so, can use all the EFL). Tje third, func_end,
517  * that will be called in Ecore main loop when func_heavy is done. So you
518  * can use all the EFL inside this function. The last one, func_cancel, will
519  * be called in the main loop also, if the thread is cancelled or could not run at all.
520  *
521  * Be aware, that you can't make assumption on the result order of func_end
522  * after many call to ecore_long_run, as we start as much thread as the
523  * host CPU can handle.
524  *
525  * If you set try_no_queue, it will try to run outside of the thread pool, this can bring
526  * the CPU down, so be carefull with that. Of course if it can't start a new thread, it will
527  * try to use one from the pool.
528  */
529 EAPI Ecore_Thread *
530 ecore_long_run(void (*func_heavy)(Ecore_Thread *thread, void *data),
531         void (*func_notify)(Ecore_Thread *thread, void *msg_data, void *data),
532         void (*func_end)(void *data),
533         void (*func_cancel)(void *data),
534         const void *data,
535         Eina_Bool try_no_queue)
536 {
537
538 #ifdef EFL_HAVE_PTHREAD
539    Ecore_Pthread_Worker *worker;
540    Ecore_Pthread_Data *pth = NULL;
541
542    if (!func_heavy) return NULL;
543
544    worker = malloc(sizeof (Ecore_Pthread_Worker));
545    if (!worker) goto on_error;
546
547    worker->u.long_run.func_heavy = func_heavy;
548    worker->u.long_run.func_notify = func_notify;
549    worker->u.long_run.hash = NULL;
550    worker->func_cancel = func_cancel;
551    worker->func_end = func_end;
552    worker->data = data;
553    worker->cancel = EINA_FALSE;
554    worker->long_run = EINA_TRUE;
555
556    worker->u.long_run.notify = ecore_pipe_add(_ecore_notify_handler, worker);
557
558    if (!try_no_queue)
559      {
560         pthread_t t;
561
562         if (pthread_create(&t, NULL, (void *) _ecore_direct_worker, worker) == 0)
563           return (Ecore_Thread *) worker;
564      }
565
566    pthread_mutex_lock(&_mutex);
567    _ecore_pending_job_threads_long = eina_list_append(_ecore_pending_job_threads_long, worker);
568
569    if (_ecore_thread_count == _ecore_thread_count_max)
570      {
571         pthread_mutex_unlock(&_mutex);
572         return (Ecore_Thread *) worker;
573      }
574
575    pthread_mutex_unlock(&_mutex);
576
577    /* One more thread could be created. */
578    pth = malloc(sizeof (Ecore_Pthread_Data));
579    if (!pth) goto on_error;
580
581    pth->p = ecore_pipe_add(_ecore_thread_handler, NULL);
582    if (pth->p) goto on_error;
583
584    if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0)
585      return (Ecore_Thread *) worker;
586
587  on_error:
588    if (pth)
589      {
590         if (pth->p) ecore_pipe_del(pth->p);
591         free(pth);
592      }
593
594    if (_ecore_thread_count == 0)
595      {
596         if (func_cancel) func_cancel((void *) data);
597
598         if (worker)
599           {
600              ecore_pipe_del(worker->u.long_run.notify);
601              free(worker);
602              worker = NULL;
603           }
604      }
605
606    return (Ecore_Thread *) worker;
607 #else
608    Ecore_Pthread_Worker worker;
609
610    (void) try_no_queue;
611
612    /*
613      If no thread and as we don't want to break app that rely on this
614      facility, we will lock the interface until we are done.
615     */
616    worker.u.long_run.func_heavy = func_heavy;
617    worker.u.long_run.func_notify = func_notify;
618    worker->u.long_run.hash = NULL;
619    worker.u.long_run.notify = NULL;
620    worker.func_cancel = func_cancel;
621    worker.func_end = func_end;
622    worker.data = data;
623    worker.cancel = EINA_FALSE;
624    worker.long_run = EINA_TRUE;
625
626    func_heavy((Ecore_Thread *) &worker, (void *)data);
627
628    if (worker.cancel) func_cancel((void *)data);
629    else func_end((void *)data);
630
631    return NULL;
632 #endif
633 }
634
635 /**
636  * @brief Send data to main loop from worker thread.
637  * @param thread The current Ecore_Thread context to send data from
638  * @param data Data to be transmitted to the main loop
639  * @return EINA_TRUE if data was successfully send to main loop,
640  *         EINA_FALSE if anything goes wrong.
641  *
642  * After a succesfull call, the data should be considered owned
643  * by the main loop.
644  *
645  * You should use this function only in the func_heavy call.
646  */
647 EAPI Eina_Bool
648 ecore_thread_notify(Ecore_Thread *thread, const void *data)
649 {
650    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
651
652    if (!worker) return EINA_FALSE;
653    if (!worker->long_run) return EINA_FALSE;
654
655 #ifdef EFL_HAVE_PTHREAD
656    if (worker->u.long_run.self != pthread_self()) return EINA_FALSE;
657
658    ecore_pipe_write(worker->u.long_run.notify, &data, sizeof (void *));
659
660    return EINA_TRUE;
661 #else
662    worker->u.long_run.func_notify(thread, (void*) data, (void*) worker->data);
663
664    return EINA_TRUE;
665 #endif
666 }
667
668 /**
669  * @brief Get number of active thread jobs
670  * @return Number of active threads running jobs
671  * This returns the number of threads currently running jobs through the
672  * ecore_thread api.
673  */
674 EAPI int
675 ecore_thread_active_get(void)
676 {
677    int ret;
678 #ifdef EFL_HAVE_PTHREAD
679    pthread_mutex_lock(&_mutex);
680    ret = _ecore_thread_count;
681    pthread_mutex_unlock(&_mutex);
682    return ret;
683 #else
684    return 0;
685 #endif
686 }
687
688 /**
689  * @brief Get number of pending (short) thread jobs
690  * @return Number of pending threads running "short" jobs
691  * This returns the number of threads currently running jobs through the
692  * ecore_thread_run api call.
693  */
694 EAPI int
695 ecore_thread_pending_get(void)
696 {
697    int ret;
698 #ifdef EFL_HAVE_PTHREAD
699    pthread_mutex_lock(&_mutex);
700    ret = eina_list_count(_ecore_pending_job_threads);
701    pthread_mutex_unlock(&_mutex);
702    return ret;
703 #else
704    return 0;
705 #endif
706 }
707
708 /**
709  * @brief Get number of pending long thread jobs
710  * @return Number of pending threads running "long" jobs
711  * This returns the number of threads currently running jobs through the
712  * ecore_long_run api call.
713  */
714 EAPI int
715 ecore_thread_pending_long_get(void)
716 {
717    int ret;
718 #ifdef EFL_HAVE_PTHREAD
719    pthread_mutex_lock(&_mutex);
720    ret = eina_list_count(_ecore_pending_job_threads_long);
721    pthread_mutex_unlock(&_mutex);
722    return ret;
723 #else
724    return 0;
725 #endif
726 }
727
728 /**
729  * @brief Get number of pending thread jobs
730  * @return Number of pending threads running jobs
731  * This returns the number of threads currently running jobs through the
732  * ecore_thread_run and ecore_long_run api calls combined.
733  */
734 EAPI int
735 ecore_thread_pending_total_get(void)
736 {
737    int ret;
738 #ifdef EFL_HAVE_PTHREAD
739    pthread_mutex_lock(&_mutex);
740    ret = eina_list_count(_ecore_pending_job_threads) + eina_list_count(_ecore_pending_job_threads_long);
741    pthread_mutex_unlock(&_mutex);
742    return ret;
743 #else
744    return 0;
745 #endif
746 }
747
748 /**
749  * @brief Get the max number of threads that can run simultaneously
750  * @return Max number of threads ecore will run
751  * This returns the total number of threads that ecore will attempt to run
752  * simultaneously.
753  */
754 EAPI int
755 ecore_thread_max_get(void)
756 {
757    int ret;
758    pthread_mutex_lock(&_mutex);
759    ret = _ecore_thread_count_max;
760    pthread_mutex_unlock(&_mutex);
761
762    return _ecore_thread_count_max;
763 }
764
765 /**
766  * @brief Set the max number of threads that can run simultaneously
767  * @param num The new maximum
768  * This sets the maximum number of threads that ecore will try to run
769  * simultaneously.  This number cannot be < 1 or >= 2x the number of active cpus.
770  */
771 EAPI void
772 ecore_thread_max_set(int num)
773 {
774    if (num < 1) return;
775    /* avoid doing something hilarious by blocking dumb users */
776    if (num >= (2 * eina_cpu_count())) return;
777
778    pthread_mutex_lock(&_mutex);
779    _ecore_thread_count_max = num;
780    pthread_mutex_unlock(&_mutex);
781 }
782
783 /**
784  * @brief Reset the max number of threads that can run simultaneously
785  * This resets the maximum number of threads that ecore will try to run
786  * simultaneously to the number of active cpus.
787  */
788 EAPI void
789 ecore_thread_max_reset(void)
790 {
791    pthread_mutex_lock(&_mutex);
792    _ecore_thread_count_max = eina_cpu_count();
793    pthread_mutex_unlock(&_mutex);
794 }
795
796 /**
797  * @brief Get the number of threads which are available to be used
798  * @return The number of available threads
799  * This returns the number of threads slots that ecore has currently available.
800  * Assuming that you haven't changed the max number of threads with @ref ecore_thread_max_set
801  * this should be equal to (num_cpus - (active_running + active_long_running))
802  */
803 EAPI int
804 ecore_thread_available_get(void)
805 {
806    int ret;
807 #ifdef EFL_HAVE_PTHREAD
808    pthread_mutex_lock(&_mutex);
809    ret = _ecore_thread_count_max - _ecore_thread_count;
810    pthread_mutex_unlock(&_mutex);
811    return ret;
812 #else
813    return 0;
814 #endif
815 }
816
817 /**
818  * @brief Add data to the pool for subsequent uses
819  * @param thread The thread context to add to
820  * @param key The name string to add the data with
821  * @param value The data to add
822  * @param direct If true, this will not copy the key string (like eina_hash_direct_add)
823  * @return EINA_TRUE on success, EINA_FALSE on failure
824  * This adds data to the thread context, allowing for subsequent users of the thread's pool
825  * to retrieve and use it without complicated mutexing.  This function can only be called by a
826  * heavy_run thread INSIDE the thread and will return EINA_FALSE in any case but success.
827  * All data added to the thread pool must be freed in the thread's func_end/func_cancel
828  * functions to avoid leaks.
829  */
830 EAPI Eina_Bool
831 ecore_thread_pool_data_add(Ecore_Thread *thread, const char *key, const void *value, Eina_Bool direct)
832 {
833    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
834    if ((!thread) || (!key) || (!value))
835      return EINA_FALSE;
836 #ifdef EFL_HAVE_PTHREAD
837    if (worker->u.long_run.self != pthread_self()) return EINA_FALSE;
838
839    if (!worker->u.long_run.hash)
840      worker->u.long_run.hash = eina_hash_string_small_new(NULL);
841
842    if (!worker->u.long_run.hash)
843      return EINA_FALSE;
844    if (direct)
845      return eina_hash_direct_add(worker->u.long_run.hash, key, value);
846    return eina_hash_add(worker->u.long_run.hash, key, value);
847 #else
848    return EINA_TRUE;
849 #endif
850 }
851
852 /**
853  * @brief Modify data in the pool, or add if not found
854  * @param thread The thread context
855  * @param key The name string to add the data with
856  * @param value The data to add
857  * @param direct If true, this will not copy the key string (like eina_hash_direct_add)
858  * @return The old data associated with @p key on success if modified, NULL if added
859  * This adds/modifies data in the thread context, adding only if modify fails.
860  * This function can only be called by a heavy_run thread INSIDE the thread.
861  * All data added to the thread pool must be freed in the thread's func_end/func_cancel
862  * functions to avoid leaks.
863  */
864 EAPI void *
865 ecore_thread_pool_data_modify_or_add(Ecore_Thread *thread, const char *key, const void *value)
866 {
867    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
868    if ((!thread) || (!key) || (!value))
869      return NULL;
870 #ifdef EFL_HAVE_PTHREAD
871    if (worker->u.long_run.self != pthread_self()) return NULL;
872
873    if (!worker->u.long_run.hash)
874      worker->u.long_run.hash = eina_hash_string_small_new(NULL);
875
876    if (!worker->u.long_run.hash)
877      return NULL;
878
879    return eina_hash_modify_or_add(worker->u.long_run.hash, key, value);
880 #else
881    return NULL;
882 #endif
883 }
884
885 /**
886  * @brief Find data in the pool's data
887  * @param thread The thread context
888  * @param key The name string the data is associated with
889  * @return The value, or NULL on error
890  * This finds data in the thread context that has been previously added with @ref ecore_thread_pool_data_add
891  * This function can only be called by a heavy_run thread INSIDE the thread, and will return NULL
892  * in any case but success.
893  */
894
895 EAPI void *
896 ecore_thread_pool_data_find(Ecore_Thread *thread, const char *key)
897 {
898    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
899    if ((!thread) || (!key))
900      return NULL;
901 #ifdef EFL_HAVE_PTHREAD
902    if (worker->u.long_run.self != pthread_self()) return NULL;
903
904    if (!worker->u.long_run.hash)
905      return NULL;
906
907    return eina_hash_find(worker->u.long_run.hash, key);
908 #else
909    return NULL;
910 #endif
911 }
912
913 /**
914  * @brief Delete data from the pool's data
915  * @param thread The thread context
916  * @param key The name string the data is associated with
917  * @return EINA_TRUE on success, EINA_FALSE on failure
918  * This deletes the data pointer from the thread context which was previously added with @ref ecore_thread_pool_data_add
919  * This function can only be called by a heavy_run thread INSIDE the thread, and will return EINA_FALSE
920  * in any case but success.  Note that this WILL NOT free the data, it merely removes it from the thread pool.
921  */
922 EAPI Eina_Bool
923 ecore_thread_pool_data_del(Ecore_Thread *thread, const char *key)
924 {
925    Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
926    if ((!thread) || (!key))
927      return EINA_FALSE;
928 #ifdef EFL_HAVE_PTHREAD
929    if (worker->u.long_run.self != pthread_self()) return EINA_FALSE;
930
931    if (!worker->u.long_run.hash)
932      return EINA_FALSE;
933
934    return eina_hash_del_by_key(worker->u.long_run.hash, key);
935 #else
936    return EINA_TRUE;
937 #endif
938 }