Add a proposal for a module/plugins API that should match every requirement I

received. It's a little huge right now, but work quite nicely.

It support "static" module, version, recursive lookup and should be able to
replace the module/plugins support in evas and ecore.


SVN revision: 35534
This commit is contained in:
Cedric BAIL 2008-08-18 08:18:16 +00:00
parent 0d3a45be0f
commit da8c3be66f
16 changed files with 1060 additions and 345 deletions

View File

@ -24,6 +24,12 @@ version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN"
AC_SUBST(VMAJ)
AC_SUBST(version_info)
### Needed information
MODULE_ARCH="$host_os-$host_cpu"
AC_SUBST(MODULE_ARCH)
AC_DEFINE_UNQUOTED(MODULE_ARCH, "${MODULE_ARCH}", "Module architecture")
### Additional options to configure
# Unit tests

View File

@ -27,9 +27,9 @@
*/
typedef void (*Eina_File_Dir_List_Cb)(const char *name, const char *path, void *data);
#define EINA_FILE_DIR_LIST_CB(Function) ((Eina_File_Dir_List_Cb)Function)
EAPI void eina_file_dir_list(const char *dir, int recursive, Eina_File_Dir_List_Cb cb, void *data);
EAPI void eina_file_path_nth_get(const char *path, int n, char **left, char **right);
EAPI Eina_Bool eina_file_dir_list(const char *dir, Eina_Bool recursive, Eina_File_Dir_List_Cb cb, void *data);
/** @} */

View File

@ -20,6 +20,7 @@
#define EINA_MEMPOOL_H_
#include "eina_types.h"
#include "eina_error.h"
/**
* @defgroup Memory_Pool_Group Memory Pool
@ -27,6 +28,8 @@
*/
typedef struct _Eina_Mempool Eina_Mempool;
EAPI extern Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE;
EAPI int eina_mempool_init(void);
EAPI int eina_mempool_shutdown(void);

View File

@ -26,25 +26,51 @@
* @defgroup Module_Group Module
* @{
*/
typedef struct _Eina_Module Eina_Module;
typedef struct _Eina_Module_Group Eina_Module_Group;
typedef struct _Eina_Module_Export Eina_Module_Export;
typedef int (*Eina_Module_Cb)(Eina_Module *m, void *data);
typedef Eina_Bool (*Eina_Module_Cb)(Eina_Module *m, void *data);
struct _Eina_Module_Export
{
const char *name;
const char *version;
const char *type;
const void *object;
};
EAPI Eina_Module * eina_module_new(const char *file);
EAPI void eina_module_free(Eina_Module *m);
EAPI int eina_module_init(void);
EAPI int eina_module_shutdown(void);
EAPI void eina_module_root_add(const char *root_path);
EAPI int eina_module_load(Eina_Module *m);
EAPI void eina_module_unload(Eina_Module *m);
EAPI Eina_Module_Group *eina_module_group_new(void);
EAPI void eina_module_group_delete(Eina_Module_Group *group);
EAPI char * eina_module_path_get(Eina_Module *m);
EAPI char * eina_module_name_get(Eina_Module *m);
EAPI void * eina_module_symbol_get(Eina_Module *m, const char *symbol);
EAPI void eina_module_path_register(Eina_Module_Group *modules, const char *path, Eina_Bool recursive);
EAPI void eina_module_app_register(Eina_Module_Group *modules, const char *app, const char *types, const char *version);
EAPI void eina_module_register(Eina_Module_Group *modules, const Eina_Module_Export *static_module);
EAPI Eina_List * eina_module_list_get(const char *path, unsigned int recursive, Eina_Module_Cb cb, void *data);
EAPI void eina_module_list_load(Eina_List *list);
EAPI void eina_module_list_unload(Eina_List *list);
EAPI void eina_module_list_free(Eina_List *list);
EAPI Eina_List *eina_module_list_new(Eina_Module_Group *modules, Eina_Module_Cb cb, void *data);
EAPI void eina_module_list_delete(Eina_List *modules);
EAPI Eina_Module *eina_module_new(Eina_Module_Group *modules, const char *name);
EAPI void eina_module_delete(Eina_Module *modules);
EAPI Eina_Bool eina_module_load(Eina_Module *module);
EAPI void eina_module_unload(Eina_Module *module);
EAPI void eina_module_list_load(const Eina_List *list);
EAPI void eina_module_list_unload(const Eina_List *list);
EAPI const char *eina_module_path_get(Eina_Module *module);
EAPI void *eina_module_symbol_get(Eina_Module *module, const char *symbol);
EAPI void *eina_module_export_object_get(Eina_Module *module);
EAPI const char *eina_module_export_type_get(Eina_Module *module);
EAPI const char *eina_module_export_version_get(Eina_Module *module);
EAPI const char *eina_module_export_name_get(Eina_Module *module);
#define EINA_MODULE(Name, Type, Version, Object) EAPI Eina_Module_Export Eina_Export = { Name, Version, Type, Object };
/** @} */

View File

@ -2,6 +2,9 @@ MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-I$(top_srcdir)/src/include \
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
@COVERAGE_CFLAGS@
lib_LTLIBRARIES = libeina.la

View File

@ -18,6 +18,9 @@
#define _GNU_SOURCE
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "eina_file.h"
#include "eina_private.h"
@ -33,76 +36,50 @@
* @param cb The callback to be called
* @param data The data to pass to the callback
*/
EAPI void eina_file_dir_list(const char *dir, int recursive, Eina_File_Dir_List_Cb cb, void *data)
EAPI Eina_Bool
eina_file_dir_list(const char *dir, Eina_Bool recursive, Eina_File_Dir_List_Cb cb, void *data)
{
struct dirent *de;
DIR *d;
assert(cb);
if (!cb) return EINA_FALSE;
d = opendir(dir);
if (!d)
return;
if (!d) return EINA_FALSE;
while ((de = readdir(d)))
{
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
cb(de->d_name, dir, data);
/* d_type is only available on linux and bsd (_BSD_SOURCE) */
if ((recursive) && (de->d_type == DT_DIR))
{
char path[PATH_MAX];
snprintf(path, PATH_MAX, "%s/%s", dir, de->d_name);
if (recursive == EINA_TRUE) {
char *path;
path = alloca(strlen(dir) + strlen(de->d_name) + 2);
strcpy(path, dir);
strcat(path, "/");
strcat(path, de->d_name);
if (de->d_type == DT_UNKNOWN) {
struct stat st;
if (stat(path, &st))
continue ;
if (!S_ISDIR(st.st_mode))
continue ;
} else if (de->d_type != DT_DIR) {
continue ;
}
eina_file_dir_list(path, recursive, cb, data);
}
}
closedir(d);
}
/**
*
*/
EAPI void eina_file_path_nth_get(const char *path, int n, char **left, char **right)
{
char *p;
char *end;
char *tmp;
char *delim;
int inc;
int num = 0;
if (!left && !right)
return;
if (n > 0)
{
p = (char *)path;
inc = 1;
end = (char *)path + strlen(path);
}
else
{
p = (char *)path + strlen(path);
inc = -1;
end = (char *)path;
}
for (tmp = p, delim = p; tmp != end && num != n; tmp += inc)
{
if (*tmp == '/')
{
num += inc;
delim = tmp;
}
}
if (left)
{
*left = strndup(path, delim - path + 1);
}
if (right)
{
*right = strdup(delim + 1);
}
}
closedir(d);
return EINA_TRUE;
}

View File

@ -23,9 +23,11 @@
/*============================================================================*
* Local *
*============================================================================*/
static Eina_List *_modules;
static Eina_Module_Group *_group;
static int _init_count = 0;
EAPI Eina_Error EINA_ERROR_NOT_MEMPOOL_MODULE = 0;
struct _Eina_Mempool
{
#ifdef DEBUG
@ -35,33 +37,37 @@ struct _Eina_Mempool
Eina_Mempool_Backend *backend;
void *backend_data;
};
static Eina_Mempool *
_new_from_buffer(const char *module, const char *context, const char *options, va_list args)
{
Eina_List *l;
Eina_Mempool *mp;
Eina_Module *m;
/* load the module with filename == name */
for (l = _modules; l; l = eina_list_next(l))
{
Eina_Module *m;
m = eina_list_data(l);
/* check if the requested module name exists */
if (!strncmp(eina_module_name_get(m), module, strlen(module) + 1))
{
Eina_Mempool *mp;
mp = malloc(sizeof(Eina_Mempool));
eina_module_load(m);
mp->module = m;
mp->backend = eina_module_symbol_get(m, "mp_backend");
mp->backend_data = mp->backend->init(context, options, args);
return mp;
}
eina_error_set(0);
m = eina_module_new(_group, module);
if (!m) return NULL;
if (eina_module_load(m) == EINA_FALSE) {
eina_error_set(EINA_ERROR_NOT_MEMPOOL_MODULE);
goto on_error;
}
mp = malloc(sizeof(Eina_Mempool));
if (!mp) {
eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
goto on_error;
}
mp->module = m;
mp->backend = eina_module_export_object_get(m);
mp->backend_data = mp->backend->init(context, options, args);
return mp;
on_error:
if (m) eina_module_delete(m);
return NULL;
}
/*============================================================================*
* API *
*============================================================================*/
@ -73,11 +79,19 @@ eina_mempool_init(void)
{
if (!_init_count)
{
_modules = eina_module_list_get("/usr/local/lib/eina/modules/mp", 0, NULL, NULL);
eina_module_init();
_group = eina_module_group_new();
if (!_group) return 0;
eina_module_app_register(_group, "eina", "mp", NULL);
EINA_ERROR_NOT_MEMPOOL_MODULE = eina_error_register("Not a memory pool module.");
}
/* get all the modules */
return ++_init_count;
}
/**
*
*/
@ -90,10 +104,12 @@ eina_mempool_shutdown(void)
if (!_init_count)
{
/* remove the list of modules */
eina_module_list_free(_modules);
eina_module_group_delete(_group);
eina_module_shutdown();
}
return _init_count;
}
/**
*
*/
@ -111,6 +127,7 @@ eina_mempool_new(const char *name, const char *context, const char *options, ...
return mp;
}
/**
*
*/
@ -122,6 +139,7 @@ EAPI void eina_mempool_delete(Eina_Mempool *mp)
eina_module_unload(mp->module);
free(mp);
}
/**
*
*/
@ -132,6 +150,7 @@ EAPI void * eina_mempool_realloc(Eina_Mempool *mp, void *element, unsigned int s
return mp->backend->realloc(mp->backend_data, element, size);
}
/**
*
*/
@ -142,6 +161,7 @@ EAPI void * eina_mempool_alloc(Eina_Mempool *mp, unsigned int size)
return mp->backend->alloc(mp->backend_data, size);
}
/**
*
*/

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@
#include "eina_inlist.h"
#include "eina_error.h"
#include "eina_module.h"
#include "eina_private.h"
@ -209,10 +210,12 @@ eina_chained_mempool_shutdown(void *data)
free(mp);
}
Eina_Mempool_Backend mp_backend = {
static Eina_Mempool_Backend mp_backend = {
.init = &eina_chained_mempool_init,
.shutdown = &eina_chained_mempool_shutdown,
.realloc = &eina_chained_mempool_realloc,
.alloc = &eina_chained_mempool_malloc,
.free = &eina_chained_mempool_free
};
EINA_MODULE("chaine_mempool", "mp", NULL, &mp_backend);

View File

@ -29,6 +29,7 @@
#include "eina_inlist.h"
#include "eina_error.h"
#include "eina_module.h"
#include "eina_private.h"
@ -130,7 +131,7 @@ eina_ememoa_fixed_shutdown(void *data)
free(efm);
}
Eina_Mempool_Backend mp_backend = {
static Eina_Mempool_Backend mp_backend = {
.init = &eina_ememoa_fixed_init,
.shutdown = &eina_ememoa_fixed_shutdown,
.realloc = &eina_ememoa_fixed_realloc,
@ -139,3 +140,5 @@ Eina_Mempool_Backend mp_backend = {
.garbage_collect = &eina_ememoa_fixed_gc,
.statistics = &eina_ememoa_fixed_statistics
};
EINA_MODULE("ememoa_fixed", "mp", NULL, &mp_backend);

View File

@ -29,6 +29,7 @@
#include <ememoa_mempool_unknown_size.h>
#include "eina_types.h"
#include "eina_module.h"
#include "eina_private.h"
typedef struct _Eina_Ememoa_Unknown_Size_Mempool Eina_Ememoa_Unknown_Size_Mempool;
@ -136,7 +137,7 @@ eina_ememoa_unknown_size_shutdown(void *data)
free(efm);
}
Eina_Mempool_Backend mp_backend = {
static Eina_Mempool_Backend mp_backend = {
.init = &eina_ememoa_unknown_size_init,
.shutdown = &eina_ememoa_unknown_size_shutdown,
.realloc = &eina_ememoa_unknown_size_realloc,
@ -146,3 +147,4 @@ Eina_Mempool_Backend mp_backend = {
.statistics = &eina_ememoa_unknown_size_statistics
};
EINA_MODULE("ememoa_unknown", "mp", NULL, &mp_backend);

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include "eina_types.h"
#include "eina_module.h"
#include "eina_private.h"
static void *
@ -57,7 +58,7 @@ eina_pass_through_shutdown(__UNUSED__ void *data)
{
}
Eina_Mempool_Backend mp_backend = {
static Eina_Mempool_Backend mp_backend = {
.init = &eina_pass_through_init,
.shutdown = &eina_pass_through_shutdown,
.realloc = &eina_pass_through_realloc,
@ -67,4 +68,5 @@ Eina_Mempool_Backend mp_backend = {
.statistics = NULL
};
EINA_MODULE("pass_through", "mp", NULL, &mp_backend);

View File

@ -2,9 +2,13 @@ MAINTAINERCLEANFILES = Makefile.in
benchdir = $(bindir)
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/include \
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/include \
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\" \
@CHECK_CFLAGS@
if EINA_ENABLE_TESTS
@ -24,6 +28,7 @@ eina_test_lalloc.c \
eina_test_hash.c \
eina_test_iterator.c \
eina_test_accessor.c \
eina_test_module.c \
eina_test_list.c
eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la

View File

@ -38,6 +38,7 @@ static const Eina_Test_Case etc[] = {
{ "List", eina_test_list },
{ "Iterator", eina_test_iterator },
{ "Accessor", eina_test_accessor },
{ "Module", eina_test_module },
{ NULL, NULL }
};

View File

@ -37,5 +37,6 @@ void eina_test_hash(TCase *tc);
void eina_test_list(TCase *tc);
void eina_test_iterator(TCase *tc);
void eina_test_accessor(TCase *tc);
void eina_test_module(TCase *tc);
#endif /* EINA_SUITE_H_ */

View File

@ -0,0 +1,114 @@
/* EINA - EFL data type library
* Copyright (C) 2008 Cedric Bail
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include "eina_suite.h"
#include "eina_module.h"
START_TEST(eina_module_init_shutdown)
{
eina_module_init();
eina_module_shutdown();
eina_module_init();
eina_module_init();
eina_module_init();
eina_module_shutdown();
eina_module_init();
eina_module_init();
eina_module_root_add(PACKAGE_BUILD_DIR);
eina_module_shutdown();
eina_module_shutdown();
eina_module_shutdown();
eina_module_shutdown();
}
END_TEST
static int i42 = 42;
static Eina_Module_Export static_test = { "simple", NULL, "test", &i42 };
EAPI int stupid_test = 7;
static Eina_Bool
_eina_module_test_cb(__UNUSED__ Eina_Module *m, __UNUSED__ void *data)
{
return EINA_TRUE;
}
START_TEST(eina_module_simple)
{
Eina_Module_Group *gp;
Eina_Module *m;
Eina_List *list;
eina_module_init();
eina_module_root_add(PACKAGE_BUILD_DIR"/src/tests");
gp = eina_module_group_new();
fail_if(!gp);
eina_module_path_register(gp, PACKAGE_BUILD_DIR"/src/modules", EINA_TRUE);
eina_module_path_register(gp, PACKAGE_BUILD_DIR"/src/lib", EINA_FALSE);
eina_module_path_register(gp, PACKAGE_BUILD_DIR"/src/lib", EINA_FALSE);
eina_module_app_register(gp, "eina", "test", NULL);
eina_module_app_register(gp, "eina", "bench", "1.0.0");
eina_module_register(gp, &static_test);
m = eina_module_new(gp, "unknown");
fail_if(m);
m = eina_module_new(gp, "simple");
fail_if(!m);
fail_if(eina_module_load(m) != EINA_TRUE);
fprintf(stderr, "path: %s\n", eina_module_path_get(m));
fail_if(strcmp("test", eina_module_export_type_get(m)));
fail_if(eina_module_export_version_get(m) != NULL);
fail_if(strcmp("simple", eina_module_export_name_get(m)));
fail_if(eina_module_export_object_get(m) != &i42);
fail_if(eina_module_symbol_get(m, "eina_list_init") != &eina_list_init);
eina_module_unload(m);
eina_module_delete(m);
list = eina_module_list_new(gp, _eina_module_test_cb, NULL);
eina_module_list_load(list);
eina_module_list_unload(list);
eina_module_list_delete(list);
m = eina_module_new(gp, "simple");
eina_module_group_delete(gp);
eina_module_shutdown();
}
END_TEST
void
eina_test_module(TCase *tc)
{
tcase_add_test(tc, eina_module_init_shutdown);
tcase_add_test(tc, eina_module_simple);
}