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:
e47edc250d.

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
This commit is contained in:
Tom Hacohen 2016-02-03 16:14:07 +00:00
parent 43d05a334d
commit 668fd4a6e8
7 changed files with 28 additions and 6 deletions

View File

@ -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\
";

View File

@ -123,6 +123,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); \

View File

@ -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;
}

View File

@ -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
/**

View File

@ -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.

View File

@ -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 $.

View File

@ -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);