EFL Threading example 5

This is the same as EFL 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.

EFL Threading example 6

//Compile with:
//gcc -o efl_thread_5 efl_thread_5.c -g `pkg-config --cflags --libs elementary`
#include <Elementary.h>
static Ecore_Thread *thr = NULL;
static Evas_Object *win = NULL;
static Evas_Object *rect = NULL;
struct info
{
double x, y;
};
// BEGIN - code running in my custom thread instance
//
static void
th_do(void *data EINA_UNUSED, Ecore_Thread *th)
{
double t = 0.0;
// inside our "do" function for the ecore thread, lets do the real work
for (;;)
{
struct info *inf = malloc(sizeof(struct info));
if (inf)
{
inf->x = 200 + (200 * sin(t));
inf->y = 200 + (200 * cos(t));
// now we have recorded the timepoint we pass it as feedback
// back to the mainloop. it will free it when done
ecore_thread_feedback(th, inf);
}
// and sleep and loop
usleep(1000);
t += 0.02;
// in case someone has asked us to cancel - then cancel this loop
// co-operatively (cancelling is co-operative)
if (ecore_thread_check(th)) break;
}
}
//
// END - code running in my custom thread instance
static void // when mainloop gets feedback from worker
th_feedback(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED, void *msg)
{
struct info *inf = msg;
evas_object_move(rect, inf->x - 50, inf->y - 50);
free(inf);
}
// BONUS (optional): called after th_do returns and has NOT been cancelled
static void th_end(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED) { printf("thread ended\n"); }
// BONUS (optional): called in mainloop AFTER thread has finished cancelling
static void th_cancel(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED) { printf("thread cancelled\n"); }
// just test cancelling the thread worker
static void
down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if (thr) ecore_thread_cancel(thr);
thr = NULL;
}
// on window delete - cancel thread then delete window and exit mainloop
static void
del(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
if (thr) ecore_thread_cancel(thr);
thr = NULL;
evas_object_del(obj);
elm_exit();
}
EAPI_MAIN int
elm_main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
{
Evas_Object *o;
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
win = elm_win_util_standard_add("efl-thread-5", "EFL Thread 5");
evas_object_smart_callback_add(win, "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;
// explicitly create ecore thread to do some "work on the side" and pass
// in NULL as data ptr to callbacks and true at the end means to actually
// make a new thread and not use the thread pool (there is a thread pool
// with as many thread workers as there are cpu's so this means you do not
// overload the cpu's with more work than you actually have processing
// units *IF* your threads do actually spend their time doing actual
// 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();
if (thr) ecore_thread_cancel(thr);
return 0;
}
ELM_MAIN()
EVAS_CALLBACK_MOUSE_DOWN
@ EVAS_CALLBACK_MOUSE_DOWN
Mouse Button Down Event.
Definition: Evas_Common.h:422
Ecore_Thread
struct _Ecore_Thread Ecore_Thread
A handle for threaded jobs.
Definition: Ecore_Common.h:1729
ecore_thread_feedback_run
Ecore_Thread * ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy, Ecore_Thread_Notify_Cb func_notify, Ecore_Thread_Cb func_end, Ecore_Thread_Cb func_cancel, const void *data, Eina_Bool try_no_queue)
Launches a thread to run a task that can talk back to the main thread.
Definition: ecore_thread.c:911
ecore_thread_check
Eina_Bool ecore_thread_check(Ecore_Thread *thread)
Checks if a thread is pending cancellation.
Definition: ecore_thread.c:892
ecore_thread_feedback
Eina_Bool ecore_thread_feedback(Ecore_Thread *thread, const void *msg_data)
Sends data from the worker thread to the main loop.
Definition: ecore_thread.c:1037
ecore_thread_cancel
Eina_Bool ecore_thread_cancel(Ecore_Thread *thread)
Cancels a running thread.
Definition: ecore_thread.c:741
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339
ELM_MAIN
#define ELM_MAIN()
macro to be used after the elm_main() function
Definition: elm_general.h:556
elm_policy_set
Eina_Bool elm_policy_set(unsigned int policy, int value)
Set a new policy's value (for a given policy group/identifier).
Definition: elm_main.c:1380
elm_exit
void elm_exit(void)
Ask to exit Elementary's main loop.
Definition: elm_main.c:1373
elm_run
void elm_run(void)
Run Elementary's main loop.
Definition: elm_main.c:1357
ELM_POLICY_QUIT_LAST_WINDOW_CLOSED
@ ELM_POLICY_QUIT_LAST_WINDOW_CLOSED
quit when the application's last window is closed
Definition: elm_general.h:248
ELM_POLICY_QUIT
@ ELM_POLICY_QUIT
under which circumstances the application should quit automatically.
Definition: elm_general.h:227
elm_win_util_standard_add
Evas_Object * elm_win_util_standard_add(const char *name, const char *title)
Adds a window object with standard setup.
Definition: efl_ui_win.c:9576
Evas
Eo Evas
An opaque handle to an Evas canvas.
Definition: Evas_Common.h:163
evas_object_show
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition: evas_object_main.c:1814
evas_object_del
EVAS_API void evas_object_del(Evas_Object *obj)
Marks the given Evas object for deletion (when Evas will free its memory).
Definition: evas_object_main.c:928
evas_object_color_set
EVAS_API void evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
Sets the general/main color of the given Evas object to the given one.
Definition: evas_object_main.c:2024
evas_object_event_callback_add
EVAS_API void evas_object_event_callback_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
Add (register) a callback function to a given Evas object event.
Definition: evas_callbacks.c:478
evas_object_move
EVAS_API void evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
Move the given Evas object to the given location inside its canvas' viewport.
Definition: evas_object_main.c:1171
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185
evas_object_resize
EVAS_API void evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Changes the size of the given Evas object.
Definition: evas_object_main.c:1236
evas_object_evas_get
EVAS_API Evas * evas_object_evas_get(const Eo *eo_obj)
Get the Evas to which this object belongs to.
Definition: evas_object_main.c:2662
evas_object_rectangle_add
EVAS_API Evas_Object * evas_object_rectangle_add(Evas *e)
Adds a rectangle to the given evas.
Definition: evas_object_rectangle.c:78
evas_object_smart_callback_add
EVAS_API void evas_object_smart_callback_add(Evas_Object *eo_obj, const char *event, Evas_Smart_Cb func, const void *data)
Add (register) a callback function to the smart event specified by event on the smart object obj.
Definition: evas_object_smart.c:1040