ecore: add ecore_thread_reschedule.

SVN revision: 57797
This commit is contained in:
Cedric BAIL 2011-03-16 13:16:14 +00:00
parent c551a992a8
commit ab3150b53e
3 changed files with 78 additions and 9 deletions

View File

@ -81,3 +81,6 @@
* Fix detection of complete file write in ecore_file inotify.
2011-03-16 Cedric Bail
* Add ecore_thread_reschedule.

View File

@ -497,6 +497,7 @@ extern "C" {
EAPI Eina_Bool ecore_thread_cancel(Ecore_Thread *thread);
EAPI Eina_Bool ecore_thread_check(Ecore_Thread *thread);
EAPI Eina_Bool ecore_thread_feedback(Ecore_Thread *thread, const void *msg_data);
EAPI Eina_Bool ecore_thread_reschedule(Ecore_Thread *thread);
EAPI int ecore_thread_active_get(void);
EAPI int ecore_thread_pending_get(void);
EAPI int ecore_thread_pending_feedback_get(void);

View File

@ -343,6 +343,7 @@ struct _Ecore_Pthread_Worker
Eina_Bool cancel : 1;
Eina_Bool feedback_run : 1;
Eina_Bool kill : 1;
Eina_Bool reschedule : 1;
};
#ifdef EFL_HAVE_THREADS
@ -539,7 +540,18 @@ _ecore_short_job(Ecore_Pipe *end_pipe)
if (!work->cancel)
work->u.short_run.func_blocking((void *) work->data, (Ecore_Thread*) work);
ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
if (work->reschedule)
{
work->reschedule = EINA_FALSE;
LKL(_ecore_pending_job_threads_mutex);
_ecore_pending_job_threads = eina_list_append(_ecore_pending_job_threads, work);
LKU(_ecore_pending_job_threads_mutex);
}
else
{
ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
}
}
}
@ -568,7 +580,18 @@ _ecore_feedback_job(Ecore_Pipe *end_pipe, PH(thread))
if (!work->cancel)
work->u.feedback_run.func_heavy((void *) work->data, (Ecore_Thread *) work);
ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
if (work->reschedule)
{
work->reschedule = EINA_FALSE;
LKL(_ecore_pending_job_threads_mutex);
_ecore_pending_job_threads_feedback = eina_list_append(_ecore_pending_job_threads_feedback, work);
LKU(_ecore_pending_job_threads_mutex);
}
else
{
ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *));
}
}
}
@ -845,6 +868,7 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
work->cancel = EINA_FALSE;
work->feedback_run = EINA_FALSE;
work->kill = EINA_FALSE;
work->reschedule = EINA_FALSE;
work->data = data;
#ifdef EFL_HAVE_THREADS
@ -903,9 +927,18 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
If no thread and as we don't want to break app that rely on this
facility, we will lock the interface until we are done.
*/
func_blocking((void *)data, (Ecore_Thread *) work);
if (work->cancel == EINA_FALSE) func_end((void *)data, (Ecore_Thread *) work);
else func_end((void *)data, (Ecore_Thread *) work);
do {
/* Handle reschedule by forcing it here. That would mean locking the app,
* would be better with an idler, but really to complex for a case where
* thread should really exist.
*/
work->reschedule = EINA_FALSE;
func_blocking((void *)data, (Ecore_Thread *) work);
if (work->cancel == EINA_FALSE) func_end((void *)data, (Ecore_Thread *) work);
else func_end((void *)data, (Ecore_Thread *) work);
} while (work->reschedule == EINA_TRUE);
free(work);
@ -1031,7 +1064,7 @@ ecore_thread_check(Ecore_Thread *thread)
* parallel thread. You should provide four functions. The first one, func_heavy,
* that will do the heavy work in another thread (so you should not use the
* EFL in it except Eina and Eet if you are careful). The second one, func_notify,
* will receive the data send from the thread function (func_heavy) by ecore_thread_notify
* will receive the data send from the thread function (func_heavy) by ecore_thread_feedback
* in the main loop (and so, can use all the EFL). The third, func_end,
* that will be called in Ecore main loop when func_heavy is done. So you
* can use all the EFL inside this function. The last one, func_cancel, will
@ -1073,6 +1106,8 @@ EAPI Ecore_Thread *ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy,
worker->cancel = EINA_FALSE;
worker->feedback_run = EINA_TRUE;
worker->kill = EINA_FALSE;
worker->reschedule = EINA_FALSE;
worker->u.feedback_run.send = 0;
worker->u.feedback_run.received = 0;
@ -1164,10 +1199,14 @@ EAPI Ecore_Thread *ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy,
worker.feedback_run = EINA_TRUE;
worker.kill = EINA_FALSE;
func_heavy((void *)data, (Ecore_Thread *) &worker);
do {
worker.reschedule = EINA_FALSE;
if (worker.cancel) func_cancel((void *)data, (Ecore_Thread *) &worker);
else func_end((void *)data, (Ecore_Thread *) &worker);
func_heavy((void *)data, (Ecore_Thread *) &worker);
if (worker.cancel) func_cancel((void *)data, (Ecore_Thread *) &worker);
else func_end((void *)data, (Ecore_Thread *) &worker);
} while (worker.reschedule == EINA_FALSE);
return NULL;
#endif
@ -1207,6 +1246,32 @@ ecore_thread_feedback(Ecore_Thread *thread, const void *data)
#endif
}
/**
* @brief Plan to recall the heavy function once it exist it.
* @param thread The current Ecore_Thread context to reschedule
* @return EINA_TRUE if data was successfully send to main loop,
* EINA_FALSE if anything goes wrong.
*
* After a succesfull call, you can still do what you want in your thread, it
* will only reschedule it once you exit the heavy loop.
*
* You should use this function only in the func_heavy call.
*/
EAPI Eina_Bool
ecore_thread_reschedule(Ecore_Thread *thread)
{
Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) thread;
if (!worker) return EINA_FALSE;
#ifdef EFL_HAVE_THREADS
if (!PHE(worker->self, PHS())) return EINA_FALSE;
#endif
worker->reschedule = EINA_TRUE;
return EINA_TRUE;
}
/**
* @brief Get number of active thread jobs
* @return Number of active threads running jobs