ecore: add ecore_main_loop_thread_safe_call.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 28 Jul 2011 13:33:14 +0000 (13:33 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 28 Jul 2011 13:33:14 +0000 (13:33 +0000)
NOTE: that's for you mike.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@61857 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/lib/ecore/Ecore.h
src/lib/ecore/ecore.c

index 466e0de..2b69001 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 2011-07-22  Mike Blumenkrantz
 
         * Added ecore_con_url_url_get
-        
+
 2011-07-26  Carsten Haitzler (The Rasterman)
 
         * Fix timer precision handling for grouping timer ticks so
         they actually do tick off together
 
+2011-07-28  Cedric Bail
+
+       * Add ecore_main_loop_thread_safe_call.
+
index 159aac6..e57bc17 100644 (file)
@@ -737,6 +737,22 @@ extern "C" {
    EAPI void                *ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler);
 
   /**
+   * @brief Call callback in the main loop.
+   *
+   * @param callback The callback to call in the main loop
+   * @param data The data to give to that call back
+   *
+   * For all call that need to happen in the main loop (most EFL functions do),
+   * this helper function provide the infrastructure needed to do it safely
+   * by avoind dead lock, race condition and properly wake up the main loop.
+   *
+   * Remember after that function call, you should never touch again the @p data
+   * in the thread, it is owned by the main loop and you callback should take
+   * care of freeing it if necessary.
+   */
+   EAPI void                 ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data);
+
+  /**
    * @}
    */
 
index c92c241..b7e0fbd 100644 (file)
@@ -53,6 +53,17 @@ static int _ecore_init_count = 0;
 int _ecore_log_dom = -1;
 int _ecore_fps_debug = 0;
 
+typedef struct _Ecore_Safe_Call Ecore_Safe_Call;
+struct _Ecore_Safe_Call
+{
+   Ecore_Cb cb;
+   void *data;
+};
+
+static void _thread_callback(void *data, void *buffer, unsigned int nbyte);
+static Ecore_Pipe *_thread_call = NULL;
+static Eina_Lock _thread_safety;
+
 /** OpenBSD does not define CODESET
  * FIXME ??
  */
@@ -126,6 +137,9 @@ ecore_init(void)
    _ecore_job_init();
    _ecore_time_init();
 
+   eina_lock_new(&_thread_safety);
+   _thread_call = ecore_pipe_add(_thread_callback, NULL);
+
 #if HAVE_MALLINFO
    if (getenv("ECORE_MEM_STAT"))
      {
@@ -165,6 +179,9 @@ ecore_shutdown(void)
    if (--_ecore_init_count != 0)
      return _ecore_init_count;
 
+   ecore_pipe_del(_thread_call);
+   eina_lock_free(&_thread_safety);
+
    if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
    _ecore_poller_shutdown();
    _ecore_animator_shutdown();
@@ -203,6 +220,22 @@ ecore_shutdown(void)
    return _ecore_init_count;
 }
 
+EAPI void
+ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data)
+{
+   Ecore_Safe_Call *order;
+
+   order = malloc(sizeof (Ecore_Safe_Call));
+   if (!order) return ;
+
+   order->cb = callback;
+   order->data = data;
+
+   eina_lock_take(&_thread_safety);
+   ecore_pipe_write(_thread_call, &order, sizeof (Ecore_Safe_Call*));
+   eina_lock_release(&_thread_safety);
+}
+
 /**
  * @}
  */
@@ -428,3 +461,18 @@ _ecore_memory_statistic(__UNUSED__ void *data)
 }
 
 #endif
+
+static void
+_thread_callback(void *data __UNUSED__, void *buffer, unsigned int nbyte)
+{
+   Ecore_Safe_Call *call = buffer;
+
+   while (nbyte >= sizeof (Ecore_Safe_Call*))
+     {
+        call->cb(call->data);
+        free(call);
+
+        call++;
+        nbyte -= sizeof (Ecore_Safe_Call*);
+     }
+}