forked from enlightenment/efl
docs... and memory error stuff... auditing memory allocs and making ti very
robust if allocs fail SVN revision: 6458
This commit is contained in:
parent
ff53f70023
commit
35105b70d8
|
@ -14,7 +14,7 @@ These routines are used for Evas Library interaction
|
|||
@author Carsten Haitzler <raster@rasterman.com>
|
||||
@author Till Adam <till@adam-lilienthal.de>
|
||||
@author Steve Ireland <sireland@pobox.com>
|
||||
@date 2001-2002
|
||||
@date 2000-2002
|
||||
|
||||
|
||||
|
||||
|
@ -238,31 +238,13 @@ To be documented...
|
|||
|
||||
|
||||
@todo Document API
|
||||
@todo Document Engine API
|
||||
@todo Add keyboard callbacks/event feeds and focus
|
||||
@todo Make freetype optional and put in optional graymap font engine
|
||||
@todo Add external image loaders (application provided callbacks to load)
|
||||
@todo Add loadable image loader module support (evas loads file.so)
|
||||
@todo Add external image lodaer modules (application proivdes path to file.so)
|
||||
@todo Define image load errors (and maybe have an error to string func)
|
||||
@todo Add ability to check image comments & disk format
|
||||
@todo Add immediate mode drawing commands to image objects
|
||||
@todo Define image load errors (and maybe have an error to string func)
|
||||
@todo Add text styles (outline etc.)
|
||||
@todo Add font load query calls (so we know if a font load failed)
|
||||
@todo Add font listing calls
|
||||
@todo Add OpenGL GLX Engine
|
||||
@todo Add Win32 OpenGL Engine
|
||||
@todo Add Apple OpenGL Engine
|
||||
@todo Add X11 primtive engine
|
||||
@todo Add SDL Engine
|
||||
@todo Add Symbian Engine
|
||||
@todo Add PalmOS Engine
|
||||
@todo Fix FB engine to allocat vt and release properly
|
||||
@todo Add ellipse objects (circle, arc, ellipse etc.)
|
||||
@todo Add video/movie/animation objects
|
||||
@todo Make software engine draw lines & polys with aa
|
||||
@todo Add radial gradients to gradient objects
|
||||
@todo Allow any object to clip any other object, and not just rectangles
|
||||
@todo Free images if object invisible (and put back in chache)
|
||||
@todo Check robustness of malloc/calloc/realloc failures.
|
||||
@todo Add memory use reduction code if any allocations fail
|
||||
|
@ -270,6 +252,24 @@ To be documented...
|
|||
@todo If image load fails due to memory allocation failure, try split it up into tiles and demand-load them
|
||||
@todo Add auto-detection of what engines to build based on system/libs etc.
|
||||
@todo Add overall engine configure parameters (so you can configure an engine with defaults with 1 configure option)
|
||||
@todo Document Engine API
|
||||
@todo Add external image loaders (application provided callbacks to load)
|
||||
@todo Add loadable image loader module support (evas loads file.so)
|
||||
@todo Add external image lodaer modules (application proivdes path to file.so)
|
||||
@todo Add immediate mode drawing commands to image objects
|
||||
@todo Add OpenGL GLX Engine
|
||||
@todo Add Win32 OpenGL Engine
|
||||
@todo Add Apple OpenGL Engine
|
||||
@todo Add X11 primtive engine
|
||||
@todo Add SDL Engine
|
||||
@todo Add Symbian Engine
|
||||
@todo Add PalmOS Engine
|
||||
@todo Fix FB engine to allocate vt and release properly
|
||||
@todo Add ellipse objects (circle, arc, ellipse etc.)
|
||||
@todo Add video/movie/animation objects
|
||||
@todo Make software engine draw lines & polys with aa
|
||||
@todo Add radial gradients to gradient objects
|
||||
@todo Allow any object to clip any other object, and not just rectangles
|
||||
@todo Add more evas demos
|
||||
|
||||
*/
|
||||
|
|
|
@ -91,6 +91,10 @@ typedef struct _Evas_Event_Key_Up Evas_Event_Key_Up;
|
|||
#define EVAS_LOAD_ERROR_CORRUPT_FILE 5
|
||||
#define EVAS_LOAD_ERROR_UNKNOWN_FORMAT 6
|
||||
|
||||
#define EVAS_ALLOC_ERROR_NONE 0
|
||||
#define EVAS_ALLOC_ERROR_FATAL 1
|
||||
#define EVAS_ALLOC_ERROR_RECOVERED 2
|
||||
|
||||
struct _Evas_Engine_Info
|
||||
{
|
||||
int magic;
|
||||
|
@ -449,6 +453,8 @@ extern "C" {
|
|||
|
||||
void evas_object_event_callback_add (Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info), void *data);
|
||||
void *evas_object_event_callback_del (Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info));
|
||||
|
||||
int evas_alloc_error (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
void
|
||||
evas_object_event_callback_call(Evas_Object *obj, Evas_Callback_Type type, void *event_info)
|
||||
{
|
||||
/* MEM OK */
|
||||
Evas_Object_List **l_mod, *l;
|
||||
|
||||
switch (type)
|
||||
|
@ -41,10 +42,83 @@ evas_object_event_callback_call(Evas_Object *obj, Evas_Callback_Type type, void
|
|||
}
|
||||
|
||||
/* public functions */
|
||||
|
||||
/**
|
||||
* Add a callback function to an object
|
||||
* @param obj Object to attach a callback to
|
||||
* @param type The type of event that will trigger the callback
|
||||
* @param func The function to be called when the event is triggered
|
||||
* @param data The data pointer to be passed to @p func
|
||||
*
|
||||
* This function adds a function callback to an object when the event of type
|
||||
* @p type occurs on object @p obj. The function will be passed the pointer
|
||||
* @p data when it is called. A callback function must look like this:
|
||||
*
|
||||
* @code
|
||||
* void callback (void *data, Evas *e, Evas_Object *obj, void *event_info);
|
||||
* @endcode
|
||||
*
|
||||
* The first parameter @p data in this function will be the same value passed
|
||||
* to evas_object_event_callback_add() as the @p data parameter. The second
|
||||
* parameter is a convenience for the programmer to know what evas canvas the
|
||||
* event occured on. The third parameter @p obj is the Object handle on which
|
||||
* the event occured. The foruth parameter @p event_info is a pointer to a
|
||||
* data structure that may or may not be passed to the callback, depending on
|
||||
* the event type that triggered the callback.
|
||||
*
|
||||
* The event type @p type to trigger the function mys be one of
|
||||
* EVAS_CALLBACK_MOUSE_IN, EVAS_CALLBACK_MOUSE_OUT, EVAS_CALLBACK_MOUSE_DOWN,
|
||||
* EVAS_CALLBACK_MOUSE_UP, EVAS_CALLBACK_MOUSE_MOVE, EVAS_CALLBACK_FREE,
|
||||
* EVAS_CALLBACK_KEY_DOWN, EVAS_CALLBACK_KEY_UP, EVAS_CALLBACK_FOCUS_IN
|
||||
* or EVAS_CALLBACK_FOCUS_OUT. This determines the kind of event that will
|
||||
* trigger the callback to be called. The @p event_info pointer passed to the
|
||||
* callback will be one of the following, depending on the event tiggering it:
|
||||
*
|
||||
* EVAS_CALLBACK_MOUSE_IN: event_info = pointer to Evas_Event_Mouse_In
|
||||
*
|
||||
* This event is triggered when the mouse pointer enters the region of
|
||||
* the object @p obj. This may occur by the mouse pointer being moved by
|
||||
* evas_event_feed_mouse_move() or evas_event_feed_mouse_move_data() calls,
|
||||
* or by the object being shown, raised, moved, resized, or other objects
|
||||
* being moved out of the way, hidden, lowered or moved out of the way.
|
||||
*
|
||||
* EVAS_CALLBACK_MOUSE_OUT: event_info = pointer to Evas_Event_Mouse_Out
|
||||
*
|
||||
* This event is triggered exactly like EVAS_CALLBACK_MOUSE_IN is, but occurs
|
||||
* when the mouse pointer exits an object. Note that no out events will be
|
||||
* reported if the mouse pointer is implicitly grabbed to an object (the
|
||||
* mouse buttons are down at all and any were pressed on that object). An
|
||||
* out event will be reported as soon as the mouse is no longer grabbed
|
||||
* (no mouse buttons are depressed).
|
||||
*
|
||||
* EVAS_CALLBACK_MOUSE_DOWN: event_info = pointer to Evas_Event_Mouse_Down
|
||||
*
|
||||
* EVAS_CALLBACK_MOUSE_UP: event_info = pointer to Evas_Event_Mouse_Up
|
||||
*
|
||||
* EVAS_CALLBACK_FREE: event_info = NULL
|
||||
*
|
||||
* EVAS_CALLBACK_KEY_DOWN: event_info = pointer to Evas_Event_Key_Down
|
||||
*
|
||||
* EVAS_CALLBACK_KEY_UP: event_info = pointer to Evas_Event_Key_Up
|
||||
*
|
||||
* EVAS_CALLBACK_FOCUS_IN: event_info = NULL
|
||||
*
|
||||
* EVAS_CALLBACK_FOCUS_OUT: event_info = NULL
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* extern Evas_Object *object;
|
||||
* extern void *my_data;
|
||||
* void down_callback(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
||||
* void up_callback(void *data, Evas *e, Evas_Object *obj, void *event_info);
|
||||
*
|
||||
* evas_object_event_callback_add(object, EVAS_CALLBACK_MOUSE_UP, up_callback, my_data);
|
||||
* evas_object_event_callback_add(object, EVAS_CALLBACK_MOUSE_DOWN, down_callback, my_data);
|
||||
* @endcode
|
||||
*/
|
||||
void
|
||||
evas_object_event_callback_add(Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info), void *data)
|
||||
{
|
||||
/* MEM OK */
|
||||
Evas_Func_Node *fn;
|
||||
|
||||
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
||||
|
@ -54,39 +128,55 @@ evas_object_event_callback_add(Evas_Object *obj, Evas_Callback_Type type, void (
|
|||
if (!func) return;
|
||||
if (obj->smart.smart) return;
|
||||
|
||||
fn = calloc(1, sizeof(Evas_Func_Node));
|
||||
fn = evas_mem_calloc(sizeof(Evas_Func_Node));
|
||||
if (!fn) return;
|
||||
fn->func = func;
|
||||
fn->data = data;
|
||||
switch (type)
|
||||
do
|
||||
{
|
||||
case EVAS_CALLBACK_MOUSE_IN:
|
||||
obj->callbacks.in = evas_object_list_prepend(obj->callbacks.in, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_OUT:
|
||||
obj->callbacks.out = evas_object_list_prepend(obj->callbacks.out, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_DOWN:
|
||||
obj->callbacks.down = evas_object_list_prepend(obj->callbacks.down, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_UP:
|
||||
obj->callbacks.up = evas_object_list_prepend(obj->callbacks.up, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_MOVE:
|
||||
obj->callbacks.move = evas_object_list_prepend(obj->callbacks.move, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_FREE:
|
||||
obj->callbacks.free = evas_object_list_prepend(obj->callbacks.free, fn);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
switch (type)
|
||||
{
|
||||
case EVAS_CALLBACK_MOUSE_IN:
|
||||
obj->callbacks.in = evas_object_list_prepend(obj->callbacks.in, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_OUT:
|
||||
obj->callbacks.out = evas_object_list_prepend(obj->callbacks.out, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_DOWN:
|
||||
obj->callbacks.down = evas_object_list_prepend(obj->callbacks.down, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_UP:
|
||||
obj->callbacks.up = evas_object_list_prepend(obj->callbacks.up, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_MOUSE_MOVE:
|
||||
obj->callbacks.move = evas_object_list_prepend(obj->callbacks.move, fn);
|
||||
break;
|
||||
case EVAS_CALLBACK_FREE:
|
||||
obj->callbacks.free = evas_object_list_prepend(obj->callbacks.free, fn);
|
||||
break;
|
||||
default:
|
||||
free(fn);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (!evas_list_alloc_error()) return;
|
||||
MERR_BAD();
|
||||
if (!evas_mem_free(sizeof(Evas_List)))
|
||||
{
|
||||
if (!evas_mem_degrade(sizeof(Evas_List)))
|
||||
{
|
||||
MERR_FATAL();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (evas_list_alloc_error());
|
||||
}
|
||||
|
||||
void *
|
||||
evas_object_event_callback_del(Evas_Object *obj, Evas_Callback_Type type, void (*func) (void *data, Evas *e, Evas_Object *obj, void *event_info))
|
||||
{
|
||||
/* MEM OK */
|
||||
Evas_Object_List **l_mod, *l;
|
||||
|
||||
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
||||
|
|
|
@ -82,6 +82,13 @@ if (_r) \
|
|||
(_r)->w = (_w); (_r)->h = (_h); \
|
||||
}}
|
||||
|
||||
#define MERR_NONE() _evas_alloc_error = EVAS_ALLOC_ERROR_NONE
|
||||
#define MERR_FATAL() _evas_alloc_error = EVAS_ALLOC_ERROR_FATAL
|
||||
#define MERR_BAD() _evas_alloc_error = EVAS_ALLOC_ERROR_RECOVERED
|
||||
|
||||
#define MEM_TRY_CALLOC(_ptr, _size)
|
||||
|
||||
|
||||
struct _Evas_Smart
|
||||
{
|
||||
DATA32 magic;
|
||||
|
@ -443,6 +450,8 @@ int evas_file_path_is_file(char *path);
|
|||
int evas_file_path_is_dir(char *path);
|
||||
Evas_List *evas_file_path_list(char *path, char *match, int match_case);
|
||||
DATA64 evas_file_modified_time(const char *file);
|
||||
int evas_mem_free(int mem_required);
|
||||
int evas_mem_degrade(int mem_required);
|
||||
void evas_debug_error(void);
|
||||
void evas_debug_input_null(void);
|
||||
void evas_debug_magic_null(void);
|
||||
|
@ -452,7 +461,10 @@ void evas_object_smart_use(Evas_Smart *s);
|
|||
void evas_object_smart_unuse(Evas_Smart *s);
|
||||
void evas_object_smart_del(Evas_Object *obj);
|
||||
void evas_object_smart_cleanup(Evas_Object *obj);
|
||||
void *evas_mem_calloc(int size);
|
||||
|
||||
extern int _evas_alloc_error;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,93 @@
|
|||
#include "evas_private.h"
|
||||
#include "Evas.h"
|
||||
|
||||
int _evas_alloc_error = 0;
|
||||
|
||||
/**
|
||||
* Return if any allocation errors have occured during the prior function
|
||||
* @return The allocation error flag
|
||||
*
|
||||
* This function will return if any memory allocation errors occured during,
|
||||
* and what kind they were. The return value will be one of
|
||||
* EVAS_ALLOC_ERROR_NONE, EVAS_ALLOC_ERROR_FATAL or EVAS_ALLOC_ERROR_RECOVERED
|
||||
* with each meaning something different.
|
||||
*
|
||||
* EVAS_ALLOC_ERROR_NONE means that no errors occured at all and the function
|
||||
* worked as expected.
|
||||
*
|
||||
* EVAS_ALLOC_ERROR_FATAL means the function was completely unable to perform
|
||||
* its job and will have exited as cleanly as possible. The programmer
|
||||
* should consider this as a sign of very low memory and should try and safely
|
||||
* recover from the prior functions failure (or try free up memory elsewhere
|
||||
* and try again after more memory is freed).
|
||||
*
|
||||
* EVAS_ALLOC_ERROR_RECOVERED means that an allocation error occured, but was
|
||||
* recovered from by evas finding memory of its own it has allocated and
|
||||
* freeing what it sees as not really usefully allocated memory. What is freed
|
||||
* may vary. Evas may reduce the resolution of images, free cached images or
|
||||
* fonts, trhow out pre-rendered data, reduce the complexity of change lists
|
||||
* etc. Evas and the program will function as per normal after this, but this
|
||||
* is a sign of low memory, and it is suggested that the program try and
|
||||
* identify memory it doesn't need, and free it.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* extern Evas_Object *object;
|
||||
* void callback (void *data, Evas *e, Evas_Object *obj, void *event_info);
|
||||
*
|
||||
* evas_object_event_callback_add(object, EVAS_CALLBACK_MOUSE_DOWN, callback, NULL);
|
||||
* if (evas_alloc_error() == EVAS_ALLOC_ERROR_FATAL)
|
||||
* {
|
||||
* fprintf(stderr, "ERROR: Completely unable to attach callabck. Must\n");
|
||||
* fprintf(stderr, " destroy object now as it cannot be used.\n");
|
||||
* evas_object_del(object);
|
||||
* object = NULL;
|
||||
* fprintf(stderr, "WARNING: Memory is really low. Cleaning out RAM.\n");
|
||||
* my_memory_cleanup();
|
||||
* }
|
||||
* if (evas_alloc_error() == EVAS_ALLOC_ERROR_RECOVERED)
|
||||
* {
|
||||
* fprintf(stderr, "WARNING: Memory is really low. Cleaning out RAM.\n");
|
||||
* my_memory_cleanup();
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
int
|
||||
evas_alloc_error(void)
|
||||
{
|
||||
return _evas_alloc_error;
|
||||
}
|
||||
|
||||
/* free cached items only in ram for speed reasons. return 0 if cant free */
|
||||
int
|
||||
evas_mem_free(int mem_required)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* start reducing quality of images etc. return 0 if cant free anything */
|
||||
int
|
||||
evas_mem_degrade(int mem_required)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
evas_mem_calloc(int size)
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
ptr = calloc(1, size);
|
||||
if (ptr) return ptr;
|
||||
MERR_BAD();
|
||||
while ((!ptr) && (evas_mem_free(size))) ptr = calloc(1, size);
|
||||
if (ptr) return ptr;
|
||||
while ((!ptr) && (evas_mem_degrade(size))) ptr = calloc(1, size);
|
||||
if (ptr) return ptr;
|
||||
MERR_FATAL();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
evas_debug_error(void)
|
||||
{
|
||||
|
@ -63,6 +150,9 @@ evas_debug_magic_string_get(DATA32 magic)
|
|||
case MAGIC_OBJ_TEXT:
|
||||
return "Evas_Object (Text)";
|
||||
break;
|
||||
case MAGIC_OBJ_SMART:
|
||||
return "Evas_Object (Smart)";
|
||||
break;
|
||||
default:
|
||||
return "<UNKNOWN>";
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue