summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile_Eo.am1
-rw-r--r--src/tests/eo/suite/eo_suite.c1
-rw-r--r--src/tests/eo/suite/eo_suite.h1
-rw-r--r--src/tests/eo/suite/eo_test_threaded_calls.c130
4 files changed, 133 insertions, 0 deletions
diff --git a/src/Makefile_Eo.am b/src/Makefile_Eo.am
index 9b1cb117c2..bfefd27d73 100644
--- a/src/Makefile_Eo.am
+++ b/src/Makefile_Eo.am
@@ -99,6 +99,7 @@ tests/eo/suite/eo_test_class_errors.c \
tests/eo/suite/eo_test_call_errors.c \
tests/eo/suite/eo_test_general.c \
tests/eo/suite/eo_test_value.c \
+tests/eo/suite/eo_test_threaded_calls.c \
tests/eo/suite/eo_test_init.c
tests_eo_eo_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eo\" \
diff --git a/src/tests/eo/suite/eo_suite.c b/src/tests/eo/suite/eo_suite.c
index db303cfebb..42c6645156 100644
--- a/src/tests/eo/suite/eo_suite.c
+++ b/src/tests/eo/suite/eo_suite.c
@@ -22,6 +22,7 @@ static const Eo_Test_Case etc[] = {
{ "Eo class errors", eo_test_class_errors },
{ "Eo call errors", eo_test_call_errors },
{ "Eo eina value", eo_test_value },
+ { "Eo threaded eo calls", eo_test_threaded_calls },
{ NULL, NULL }
};
diff --git a/src/tests/eo/suite/eo_suite.h b/src/tests/eo/suite/eo_suite.h
index 4a3c3b0f21..94d88bd1fe 100644
--- a/src/tests/eo/suite/eo_suite.h
+++ b/src/tests/eo/suite/eo_suite.h
@@ -8,5 +8,6 @@ void eo_test_general(TCase *tc);
void eo_test_class_errors(TCase *tc);
void eo_test_call_errors(TCase *tc);
void eo_test_value(TCase *tc);
+void eo_test_threaded_calls(TCase *tc);
#endif /* _EO_SUITE_H */
diff --git a/src/tests/eo/suite/eo_test_threaded_calls.c b/src/tests/eo/suite/eo_test_threaded_calls.c
new file mode 100644
index 0000000000..a954463e46
--- /dev/null
+++ b/src/tests/eo/suite/eo_test_threaded_calls.c
@@ -0,0 +1,130 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "Eo.h"
+#include "eo_suite.h"
+
+static Eina_Barrier barrier;
+static Eina_Spinlock locks[2];
+
+typedef struct
+{
+ int v;
+} Thread_Test_Public_Data;
+
+#define THREAD_TEST_CLASS thread_test_class_get()
+const Eo_Class *thread_test_class_get(void);
+
+EO2_FUNC_BODY(thread_test_v_get, int, 0);
+EO2_VOID_FUNC_BODY(thread_test_try_swap_stack);
+EO2_VOID_FUNC_BODYV(thread_test_constructor, EO2_FUNC_CALL(v), int v);
+
+static int
+_v_get(Eo *obj EINA_UNUSED, void *class_data)
+{
+ Thread_Test_Public_Data *pd = class_data;
+
+ return pd->v;
+}
+
+static void
+_try_swap_stack(Eo *obj EINA_UNUSED, void *class_data)
+{
+ Thread_Test_Public_Data *pd = class_data;
+
+ if (pd->v == 0 )
+ {
+ eina_spinlock_release(&locks[0]);
+ eina_spinlock_take(&locks[1]);
+ eina_barrier_wait(&barrier);
+ }
+ else if (pd->v == 1 )
+ {
+ eina_barrier_wait(&barrier);
+ eina_spinlock_take(&locks[1]);
+ }
+}
+
+static void
+_constructor(Eo *obj, void *class_data EINA_UNUSED, int v)
+{
+ Thread_Test_Public_Data *pd = class_data;
+
+ eo2_do_super(obj, THREAD_TEST_CLASS, eo2_constructor());
+
+ pd->v = v;
+}
+
+static Eo2_Op_Description op_descs[] = {
+ EO2_OP_FUNC(thread_test_constructor, _constructor, "Constructor."),
+ EO2_OP_FUNC(thread_test_v_get, _v_get, "Get property v."),
+ EO2_OP_FUNC(thread_test_try_swap_stack, _try_swap_stack, "Swap call stack frames if it is not thread safe."),
+ EO2_OP_SENTINEL
+};
+
+static const Eo_Class_Description class_desc = {
+ EO2_VERSION,
+ "Thread Test",
+ EO_CLASS_TYPE_REGULAR,
+ EO2_CLASS_DESCRIPTION_OPS(op_descs),
+ NULL,
+ sizeof(Thread_Test_Public_Data),
+ NULL,
+ NULL
+};
+
+EO_DEFINE_CLASS(thread_test_class_get, &class_desc, EO2_BASE_CLASS, NULL)
+
+static void *
+_thread_job(void *data, Eina_Thread t EINA_UNUSED)
+{
+ Eo *obj;
+ int v = (int) (uintptr_t) data;
+
+ if (v == 1)
+ eina_spinlock_take(&locks[0]);
+
+ obj = eo2_add_custom(THREAD_TEST_CLASS, NULL, thread_test_constructor(v));
+
+ eo2_do(obj, thread_test_try_swap_stack(), v = thread_test_v_get());
+
+ eina_spinlock_release(&locks[1]);
+
+ eo_unref(obj);
+
+ return (void *) (uintptr_t) v;
+}
+
+START_TEST(eo_threaded_calls_test)
+{
+ Eina_Thread threads[2];
+
+ eo_init();
+
+ fail_if(!eina_spinlock_new(&locks[0]));
+ fail_if(!eina_spinlock_new(&locks[1]));
+ fail_if(!eina_barrier_new(&barrier, 2));
+
+ eina_spinlock_take(&locks[0]);
+
+ fail_if(!eina_thread_create(&threads[0], EINA_THREAD_NORMAL, 0, _thread_job, (void *) (uintptr_t)0));
+ fail_if(!eina_thread_create(&threads[1], EINA_THREAD_NORMAL, 0, _thread_job, (void *) (uintptr_t)1));
+
+ fail_if(0 != (int)(uintptr_t)eina_thread_join(threads[0]));
+ fail_if(1 != (int)(uintptr_t)eina_thread_join(threads[1]));
+
+ eina_spinlock_free(&locks[0]);
+ eina_spinlock_free(&locks[1]);
+ eina_barrier_free(&barrier);
+
+ eo_shutdown();
+}
+END_TEST
+
+void eo_test_threaded_calls(TCase *tc)
+{
+ tcase_add_test(tc, eo_threaded_calls_test);
+}