aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2016-02-03 16:14:07 +0000
committerTom Hacohen <tom@stosb.com>2016-02-04 09:27:15 +0000
commit668fd4a6e86acb24deeea38e36fbdb6d99a71cf6 (patch)
treeaa094ea79cde089451035d3035805814dfc89c49
parentRevert "Eo: Prevent shutdown from actually doing anything" (diff)
downloadefl-668fd4a6e86acb24deeea38e36fbdb6d99a71cf6.tar.gz
Eo: add support for initialising eo after it has been shut down.
Until now it wasn't allowed/possible to init (eo_init) eo after it has been shut down (eo_shutdown). This commit fixes that, so now that is fully legal to have as many init/shutdown cycles as you want. There was a previous workaround for this issue: e47edc250dc715a6b0f94be4b1cb81d32e9d97fe. This should allow more flexibility when using the EFL in loadable modules and in various other scenarios. The problem is that the class_get() functions cache the previously created class for efficiency, but the class is freed if eo is shut down, so the cached pointer is actually invalid. The solution to the problem was to maintain a generation count (incremented every time we shut down eo), and compare that to a locally saved version in class_get(). If they don't match, recreate the class, as it has already been freed. @feature
-rw-r--r--src/bin/eolian/eo_generator.c2
-rw-r--r--src/lib/eo/Eo.h16
-rw-r--r--src/lib/eo/eo.c8
-rw-r--r--src/tests/eolian/data/class_simple_ref_eo.h2
-rw-r--r--src/tests/eolian/data/docs_ref.h2
-rw-r--r--src/tests/eolian/data/struct_ref.c2
-rw-r--r--src/tests/eolian/data/typedef_ref.c2
7 files changed, 28 insertions, 6 deletions
diff --git a/src/bin/eolian/eo_generator.c b/src/bin/eolian/eo_generator.c
index 25e8372227..1223ff5ecc 100644
--- a/src/bin/eolian/eo_generator.c
+++ b/src/bin/eolian/eo_generator.c
@@ -53,7 +53,7 @@ static const char
tmpl_eo_obj_header[] = "\
#define @#CLASS_@#CLASSTYPE @#klasstype_get()\n\
\n\
-EAPI const Eo_Class *@#klasstype_get(void) EINA_CONST;\n\
+EAPI const Eo_Class *@#klasstype_get(void);\n\
\n\
";
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index d2dbfb781b..4580722d7d 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -124,6 +124,15 @@ typedef Eo Eo_Class;
EAPI extern Eina_Spinlock _eo_class_creation_lock;
/**
+ * @var _eo_init_generation
+ * This variable stores the current eo init generation. That is, how many times
+ * we have completed full init/shutdown cycles. Starts at 1 and incremeted on
+ * every call to shutdown that actually shuts down eo.
+ * @internal
+ */
+EAPI extern unsigned int _eo_init_generation;
+
+/**
* @internal
* An enum representing the possible types of an Op.
*/
@@ -292,6 +301,12 @@ class_get_func_name(void) \
static volatile char lk_init = 0; \
static Eina_Spinlock _my_lock; \
static const Eo_Class * volatile _my_class = NULL; \
+ static unsigned int _my_init_generation = 1; \
+ if (EINA_UNLIKELY(_eo_init_generation != _my_init_generation)) \
+ { \
+ _my_class = NULL; /* It's freed in eo_shutdown(). */ \
+ lk_init = 0; \
+ } \
if (EINA_LIKELY(!!_my_class)) return _my_class; \
\
eina_spinlock_take(&_eo_class_creation_lock); \
@@ -309,6 +324,7 @@ class_get_func_name(void) \
eina_spinlock_release(&_eo_class_creation_lock); \
_tmp_parent_class = parent_class; \
_my_class = eo_class_new(class_desc, _tmp_parent_class, __VA_ARGS__); \
+ _my_init_generation = _eo_init_generation; \
eina_spinlock_release(&_my_lock); \
\
eina_spinlock_take(&_eo_class_creation_lock); \
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index 94ba1053ba..6baa7e90ae 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -19,6 +19,7 @@
/* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
EAPI Eina_Spinlock _eo_class_creation_lock;
+EAPI unsigned int _eo_init_generation = 1;
int _eo_log_dom = -1;
static _Eo_Class **_eo_classes;
@@ -1876,13 +1877,18 @@ eo_shutdown(void)
eina_spinlock_free(&_eo_class_creation_lock);
if (_eo_call_stack_key != 0)
- eina_tls_free(_eo_call_stack_key);
+ {
+ eina_tls_free(_eo_call_stack_key);
+ _eo_call_stack_key = 0;
+ }
_eo_free_ids_tables();
eina_log_domain_unregister(_eo_log_dom);
_eo_log_dom = -1;
+ ++_eo_init_generation;
+
eina_shutdown();
return EINA_FALSE;
}
diff --git a/src/tests/eolian/data/class_simple_ref_eo.h b/src/tests/eolian/data/class_simple_ref_eo.h
index 83f401ea7d..52d8a58654 100644
--- a/src/tests/eolian/data/class_simple_ref_eo.h
+++ b/src/tests/eolian/data/class_simple_ref_eo.h
@@ -19,7 +19,7 @@ typedef Eo Class_Simple;
*/
#define CLASS_SIMPLE_CLASS class_simple_class_get()
-EAPI const Eo_Class *class_simple_class_get(void) EINA_CONST;
+EAPI const Eo_Class *class_simple_class_get(void);
#ifdef CLASS_SIMPLE_BETA
/**
diff --git a/src/tests/eolian/data/docs_ref.h b/src/tests/eolian/data/docs_ref.h
index a2af4a2d64..3b61d3571b 100644
--- a/src/tests/eolian/data/docs_ref.h
+++ b/src/tests/eolian/data/docs_ref.h
@@ -77,7 +77,7 @@ typedef struct _Opaque Opaque;
*/
#define DOCS_CLASS docs_class_get()
-EAPI const Eo_Class *docs_class_get(void) EINA_CONST;
+EAPI const Eo_Class *docs_class_get(void);
/**
* @brief Property common documentation.
diff --git a/src/tests/eolian/data/struct_ref.c b/src/tests/eolian/data/struct_ref.c
index a754e92ed9..7739427da8 100644
--- a/src/tests/eolian/data/struct_ref.c
+++ b/src/tests/eolian/data/struct_ref.c
@@ -28,7 +28,7 @@ typedef struct _Opaque Opaque;
#endif
#define STRUCT_CLASS struct_class_get()
-EAPI const Eo_Class *struct_class_get(void) EINA_CONST;
+EAPI const Eo_Class *struct_class_get(void);
/**
* @brief Foo docs. This is @c monospace. This is alone-standing $.
diff --git a/src/tests/eolian/data/typedef_ref.c b/src/tests/eolian/data/typedef_ref.c
index cf661c14f5..202d4cbf34 100644
--- a/src/tests/eolian/data/typedef_ref.c
+++ b/src/tests/eolian/data/typedef_ref.c
@@ -39,7 +39,7 @@ typedef enum
#endif
#define TYPEDEF_CLASS typedef_class_get()
-EAPI const Eo_Class *typedef_class_get(void) EINA_CONST;
+EAPI const Eo_Class *typedef_class_get(void);
EOAPI char *typedef_foo(int idx);