This is the same as \hyperlink{efl_thread_4}{E\+F\+L Threading example 4} but now uses the ecore\+\_\+thread infrastructure to have a running worker thread that feeds results back to the mainloop and can easily be cancelled.

This saves some code in the application and makes for fewer problem spots if you forget a mutex.

\hyperlink{efl_thread_6}{E\+F\+L Threading example 6}


\begin{DoxyCodeInclude}
\textcolor{comment}{//Compile with:}
\textcolor{comment}{//gcc -o efl\_thread\_5 efl\_thread\_5.c -g `pkg-config --cflags --libs elementary`}
\textcolor{preprocessor}{#include <Elementary.h>}

\textcolor{keyword}{static} Ecore\_Thread *thr = NULL;

\textcolor{keyword}{static} Evas\_Object *win = NULL;
\textcolor{keyword}{static} Evas\_Object *rect = NULL;

\textcolor{keyword}{struct }info
\{
   \textcolor{keywordtype}{double} x, y;
\};

\textcolor{comment}{// BEGIN - code running in my custom thread instance}
\textcolor{comment}{//}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
th\_do(\textcolor{keywordtype}{void} *data, Ecore\_Thread *th)
\{
   \textcolor{keywordtype}{double} t = 0.0;

   \textcolor{comment}{// inside our "do" function for the ecore thread, lets do the real work}
   \textcolor{keywordflow}{for} (;;)
     \{
        \textcolor{keyword}{struct }info *inf = malloc(\textcolor{keyword}{sizeof}(\textcolor{keyword}{struct} info));

        \textcolor{keywordflow}{if} (inf)
          \{
             inf->x = 200 + (200 * sin(t));
             inf->y = 200 + (200 * cos(t));
             \textcolor{comment}{// now we have recorded the timepoint we pass it as feedback}
             \textcolor{comment}{// back to the mainloop. it will free it when done}
             ecore\_thread\_feedback(th, inf);
          \}
        \textcolor{comment}{// and sleep and loop}
        usleep(1000);
        t += 0.02;
        \textcolor{comment}{// in case someone has asked us to cancel - then cancel this loop}
        \textcolor{comment}{// co-operatively (cancelling is co-operative)}
        \textcolor{keywordflow}{if} (ecore\_thread\_check(th)) \textcolor{keywordflow}{break};
     \}
\}
\textcolor{comment}{//}
\textcolor{comment}{// END - code running in my custom thread instance}

\textcolor{keyword}{static} \textcolor{keywordtype}{void} \textcolor{comment}{// when mainloop gets feedback from worker}
th\_feedback(\textcolor{keywordtype}{void} *data, Ecore\_Thread *th, \textcolor{keywordtype}{void} *msg)
\{
   \textcolor{keyword}{struct }info *inf = msg;
   evas\_object\_move(rect, inf->x - 50, inf->y - 50);
   free(inf);
\}

\textcolor{comment}{// BONUS (optional): called after th\_do returns and has NOT been cancelled}
\textcolor{keyword}{static} \textcolor{keywordtype}{void} th\_end(\textcolor{keywordtype}{void} *data, Ecore\_Thread *th) \{ printf(\textcolor{stringliteral}{"thread ended\(\backslash\)n"}); \}
\textcolor{comment}{// BONUS (optional): called in mainloop AFTER thread has finished cancelling}
\textcolor{keyword}{static} \textcolor{keywordtype}{void} th\_cancel(\textcolor{keywordtype}{void} *data, Ecore\_Thread *th) \{ printf(\textcolor{stringliteral}{"thread cancelled\(\backslash\)n"}); \}

\textcolor{comment}{// just test cancelling the thread worker}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
down(\textcolor{keywordtype}{void} *data, Evas *e, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   \textcolor{keywordflow}{if} (thr) ecore\_thread\_cancel(thr);
   thr = NULL;
\}

\textcolor{comment}{// on window delete - cancel thread then delete window and exit mainloop}
\textcolor{keyword}{static} \textcolor{keywordtype}{void}
del(\textcolor{keywordtype}{void} *data, Evas\_Object *obj, \textcolor{keywordtype}{void} *event\_info)
\{
   \textcolor{keywordflow}{if} (thr) ecore\_thread\_cancel(thr);
   thr = NULL;
   evas\_object\_del(obj);
   elm_exit();
\}

EAPI\_MAIN \textcolor{keywordtype}{int}
elm\_main(\textcolor{keywordtype}{int} argc, \textcolor{keywordtype}{char} **argv)
\{
   Evas\_Object *o;

   elm_policy_set(ELM\_POLICY\_QUIT, ELM\_POLICY\_QUIT\_LAST\_WINDOW\_CLOSED);

   win = elm_win_util_standard_add(\textcolor{stringliteral}{"efl-thread-5"}, \textcolor{stringliteral}{"EFL Thread 5"});
   evas\_object\_smart\_callback\_add(win, \textcolor{stringliteral}{"delete,request"}, del, NULL);

   o = evas\_object\_rectangle\_add(evas\_object\_evas\_get(win));
   evas\_object\_color\_set(o, 50, 80, 180, 255);
   evas\_object\_resize(o, 100, 100);
   evas\_object\_show(o);
   evas\_object\_event\_callback\_add(o, EVAS\_CALLBACK\_MOUSE\_DOWN, down, NULL);
   rect = o;

   \textcolor{comment}{// explicitly create ecore thread to do some "work on the side" and pass}
   \textcolor{comment}{// in NULL as data ptr to callbacks and true at the end means to actually}
   \textcolor{comment}{// make a new thread and not use the thread pool (there is a thread pool}
   \textcolor{comment}{// with as many thread workers as there are cpu's so this means you do not}
   \textcolor{comment}{// overload the cpu's with more work than you actually have processing}
   \textcolor{comment}{// units *IF* your threads do actually spend their time doing actual}
   \textcolor{comment}{// heavy computation)}
   thr = ecore\_thread\_feedback\_run(th\_do, th\_feedback, th\_end, th\_cancel,
                                   NULL, EINA\_TRUE);

   evas\_object\_resize(win, 400, 400);
   evas\_object\_show(win);

   elm_run();
   \textcolor{keywordflow}{if} (thr) ecore\_thread\_cancel(thr);

   \textcolor{keywordflow}{return} 0;
\}
ELM_MAIN()
\end{DoxyCodeInclude}
 