*/
EAPI void *ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data);
+ /**
+ * @brief This function suspend the main loop in a know state
+ * @since 1.1.0
+ *
+ * @result EINA_TRUE if the main loop was suspended correcly.
+ *
+ * This function suspend the main loop in a know state, this let you
+ * use any EFL call you want after it return. Be carefull, the main loop
+ * is blocked until you call ecore_thread_main_loop_end(). This is
+ * the only sane way to achieve pseudo thread safety.
+ *
+ * Notice that until the main loop is blocked, the thread is blocked
+ * and their is noway around that.
+ *
+ * We still advise you, when possible, to use ecore_main_loop_thread_safe_call_async()
+ * as it will not block the thread nor the main loop.
+ */
+ EAPI Eina_Bool ecore_thread_main_loop_begin(void);
+
+ /**
+ * @brief Unlock the main loop.
+ * @since 1.1.0
+ *
+ * After a call to ecore_thread_main_loop_begin(), you need to absolutly
+ * call ecore_thread_main_loop_end(), or you application will stay frozen.
+ */
+ EAPI void ecore_thread_main_loop_end(void);
+
/**
* @}
*/
Eina_Condition c;
Eina_Bool sync : 1;
+ Eina_Bool suspend : 1;
};
static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order);
static Eina_List *_thread_cb = NULL;
static Ecore_Pipe *_thread_call = NULL;
static Eina_Lock _thread_safety;
+
+static Eina_Bool _thread_loop = EINA_FALSE;
+static Eina_Lock _thread_mutex;
+static Eina_Condition _thread_cond;
+
Eina_Lock _ecore_main_loop_lock;
int _ecore_main_lock_count;
_ecore_time_init();
eina_lock_new(&_thread_safety);
- eina_lock_new(&_ecore_main_loop_lock);
+ eina_lock_new(&_thread_mutex);
+ eina_condition_new(&_thread_cond, &_thread_mutex);
_thread_call = ecore_pipe_add(_thread_callback, NULL);
+ eina_lock_new(&_ecore_main_loop_lock);
+
#if HAVE_MALLINFO
if (getenv("ECORE_MEM_STAT"))
{
order->cb.async = callback;
order->data = data;
order->sync = EINA_FALSE;
+ order->suspend = EINA_FALSE;
_ecore_main_loop_thread_safe_call(order);
}
eina_lock_new(&order->m);
eina_condition_new(&order->c, &order->m);
order->sync = EINA_TRUE;
+ order->suspend = EINA_FALSE;
_ecore_main_loop_thread_safe_call(order);
return ret;
}
+EAPI Eina_Bool
+ecore_thread_main_loop_begin(void)
+{
+ Ecore_Safe_Call *order;
+
+ if (eina_main_loop_is())
+ return EINA_FALSE;
+
+ order = malloc(sizeof (Ecore_Safe_Call));
+ if (!order) return EINA_FALSE;
+
+ eina_lock_new(&order->m);
+ eina_condition_new(&order->c, &order->m);
+ order->suspend = EINA_TRUE;
+
+ _ecore_main_loop_thread_safe_call(order);
+
+ eina_lock_take(&order->m);
+ eina_condition_wait(&order->c);
+ eina_lock_release(&order->m);
+
+ eina_main_loop_define();
+
+ _thread_loop = EINA_TRUE;
+
+ return EINA_TRUE;
+}
+
+EAPI void
+ecore_thread_main_loop_end(void)
+{
+ if (!_thread_loop) return ;
+ /* until we unlock the main loop, this thread has the main loop id */
+ if (!eina_main_loop_is()) return ;
+
+ eina_condition_broadcast(&_thread_cond);
+}
+
EAPI void
ecore_print_warning(const char *function, const char *sparam)
{
EINA_LIST_FREE(callback, call)
{
- if (call->sync)
+ if (call->suspend)
+ {
+ eina_condition_broadcast(&call->c);
+
+ eina_lock_take(&_thread_mutex);
+ eina_condition_wait(&_thread_cond);
+ eina_lock_release(&_thread_mutex);
+
+ eina_main_loop_define();
+
+ _thread_safe_cleanup(call);
+ free(call);
+ }
+ else if (call->sync)
{
call->data = call->cb.sync(call->data);
eina_condition_broadcast(&call->c);