and i implemented module UNLOADING. given enough cycles of non-use of a

module and no references, it will get.... UNLOADED :)


SVN revision: 25954
This commit is contained in:
Carsten Haitzler 2006-09-18 09:40:29 +00:00
parent 2b66c36e64
commit 3115a52684
8 changed files with 111 additions and 11 deletions

View File

@ -146,6 +146,8 @@ evas_free(Evas *e)
free(e->locks.lock.list[i]);
if (e->locks.lock.list) free(e->locks.lock.list);
if (e->engine.module) evas_module_unref(e->engine.module);
e->magic = 0;
free(e);
}
@ -216,6 +218,10 @@ evas_output_method_set(Evas *e, int render_method)
/* set the correct render */
e->output.render_method = render_method;
e->engine.func = (em->functions);
evas_module_use(em);
if (e->engine.module) evas_module_unref(e->engine.module);
e->engine.module = em;
evas_module_ref(em);
/* get the engine info struct */
if (e->engine.func->info) e->engine.info = e->engine.func->info(e);
return;

View File

@ -396,6 +396,9 @@ evas_render_updates_internal(Evas *e, unsigned char make_updates)
e->changed = 0;
e->viewport.changed = 0;
e->output.changed = 0;
evas_module_clean();
return updates;
}
@ -428,8 +431,7 @@ evas_render_updates(Evas *e)
return NULL;
MAGIC_CHECK_END();
if (!e->changed)
return NULL;
if (!e->changed) return NULL;
return evas_render_updates_internal(e, 1);
}
@ -446,7 +448,6 @@ evas_render(Evas *e)
return;
MAGIC_CHECK_END();
if (!e->changed)
return;
(void)evas_render_updates_internal(e, 0);
if (!e->changed) return;
evas_render_updates_internal(e, 0);
}

View File

@ -11,6 +11,7 @@ evas_common_load_image_from_file(const char *file, const char *key, RGBA_Image_L
RGBA_Image *im;
char *p;
char *loader = NULL;
Evas_Module *em;
if (file == NULL) return NULL;
@ -50,13 +51,12 @@ evas_common_load_image_from_file(const char *file, const char *key, RGBA_Image_L
}
if (loader)
{
Evas_Module *em;
em = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
if (em)
{
if (evas_module_load(em))
{
evas_module_use(em);
evas_image_load_func = em->functions;
if (evas_image_load_func->file_head(im, file, key))
goto ok;
@ -66,12 +66,11 @@ evas_common_load_image_from_file(const char *file, const char *key, RGBA_Image_L
for (l = evas_modules; l; l = l->next)
{
Evas_Module *em;
em = l->data;
if (em->type != EVAS_MODULE_TYPE_IMAGE_LOADER) continue;
if (!evas_module_load(em)) continue;
evas_image_load_func = em->functions;
evas_module_use(em);
if (evas_image_load_func->file_head(im, file, key))
{
if (evas_modules != l)
@ -86,9 +85,11 @@ evas_common_load_image_from_file(const char *file, const char *key, RGBA_Image_L
return NULL;
ok:
im->info.module = (void *)em;
im->info.loader = (void *)evas_image_load_func;
im->info.file = (char *)evas_stringshare_add(file);
if (key) im->info.key = (char *)evas_stringshare_add(key);
evas_module_ref((Evas_Module *)im->info.module);
evas_common_image_ref(im);
return im;
}
@ -101,6 +102,7 @@ evas_common_load_image_data_from_file(RGBA_Image *im)
if (im->image->data) return;
evas_image_load_func = im->info.loader;
evas_module_use((Evas_Module *)im->info.module);
if (!evas_image_load_func->file_data(im, im->info.file, im->info.key))
{
evas_common_image_surface_alloc(im->image);
@ -114,4 +116,9 @@ evas_common_load_image_data_from_file(RGBA_Image *im)
im->image->no_free = 1;
}
}
else
{
evas_module_unref((Evas_Module *)im->info.module);
im->info.module = NULL;
}
}

View File

@ -268,6 +268,7 @@ evas_common_image_free(RGBA_Image *im)
// if (im->info.real_file) evas_stringshare_del(im->info.real_file);
if (im->info.key) evas_stringshare_del(im->info.key);
// if (im->info.comment) evas_stringshare_del(im->info.comment);
if (im->info.module) evas_module_unref((Evas_Module *)im->info.module);
free(im);
}

View File

@ -38,6 +38,7 @@ evas_common_save_image_to_file(RGBA_Image *im, const char *file, const char *key
em = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_SAVER, saver);
if (em)
{
evas_module_use(em);
if (evas_module_load(em))
{
evas_image_save_func = em->functions;

View File

@ -158,7 +158,7 @@ evas_module_init(void)
{
Evas_Module *em;
em = malloc(sizeof(Evas_Module));
em = calloc(1, sizeof(Evas_Module));
if (!em) continue;
em->name = strdup(de->d_name);
em->path = strdup(mp->path);
@ -223,6 +223,7 @@ evas_module_load(Evas_Module *em)
if (em->loaded) return 1;
// printf("LOAD %s\n", em->name);
snprintf(buf, sizeof(buf), "%s/%s/%s/module.so", em->path, em->name, MODULE_ARCH);
if (!evas_file_path_exists(buf))
{
@ -282,6 +283,76 @@ evas_module_unload(Evas_Module *em)
em->loaded = 0;
}
void
evas_module_ref(Evas_Module *em)
{
em->ref++;
// printf("M: %s ref++ = %i\n", em->name, em->ref);
}
void
evas_module_unref(Evas_Module *em)
{
em->ref--;
// printf("M: %s ref-- = %i\n", em->name, em->ref);
}
static int use_count = 0;
void
evas_module_use(Evas_Module *em)
{
em->last_used = use_count;
}
void
evas_module_clean(void)
{
static int call_count = 0;
int ago;
int noclean = -1;
Evas_List *l;
Evas_Module *em;
/* only clean modules every 32 calls */
call_count++;
if (call_count <= 32) return;
call_count = 0;
if (noclean == -1)
{
if (getenv("EVAS_NOCLEAN"))
{
noclean = 1;
}
noclean = 0;
}
if (noclean == 1) return;
/* incriment use counter = 28bits */
use_count++;
if (use_count > 0x0fffffff) use_count = 0;
// printf("CLEAN!\n");
/* go through all modules */
for (l = evas_modules; l; l = l->next)
{
em = l->data;
// printf("M %s %i %i\n", em->name, em->ref, em->loaded);
/* if the module is refernced - skip */
if ((em->ref > 0) || (!em->loaded)) continue;
/* how many clean cycles ago was this module last used */
ago = use_count - em->last_used;
if (em->last_used > use_count) ago += 0x10000000;
/* if it was used last more than N clean cycles ago - unload */
if (ago > 3)
{
// printf(" UNLOAD %s\n", em->name);
evas_module_unload(em);
}
}
}
/* will dlclose all the modules loaded and free all the structs */
void
evas_module_shutdown(void)
@ -329,6 +400,9 @@ _evas_module_engine_inherit(Evas_Func *funcs, char *name)
{
if (evas_module_load(em))
{
/* FIXME: no way to unref */
evas_module_ref(em);
evas_module_use(em);
*funcs = *((Evas_Func *)(em->functions));
return 1;
}

View File

@ -249,6 +249,7 @@ struct _RGBA_Image
RGBA_Image_Flags flags;
struct
{
void *module;
void *loader;
// int format;
char *file;

View File

@ -45,10 +45,13 @@ struct _Evas_Module
int (*open)(Evas_Module *);
void (*close)(Evas_Module *);
} func;
unsigned char loaded : 1;
unsigned char loaded : 1;
void *functions; /* this are the functions exported by the module */
void *data; /* some internal data for the module i.e the id for engines */
int ref; /* how many refs */
int last_used; /* the cycle count when it was last used */
};
@ -308,6 +311,7 @@ struct _Evas
int events_frozen;
struct {
Evas_Module *module;
Evas_Func *func;
struct {
void *output;
@ -743,7 +747,12 @@ void evas_module_init(void);
Evas_Module * evas_module_find_type(Evas_Module_Type type, const char *name);
int evas_module_load(Evas_Module *em);
void evas_module_unload(Evas_Module *em);
void evas_module_ref(Evas_Module *em);
void evas_module_unref(Evas_Module *em);
void evas_module_use(Evas_Module *em);
void evas_module_clean(void);
void evas_module_shutdown(void);
EAPI int _evas_module_engine_inherit(Evas_Func *funcs, char *name);
#define EVAS_API_OVERRIDE(func, api, prefix) \