Enlightenment CVS committal

Author  : moom
Project : e17
Module  : proto

Dir     : e17/proto/etk/src/lib


Modified Files:
        etk_combobox.c etk_main.c etk_object.c etk_object.h 
        etk_widget.c 


Log Message:
* Now etk_object_destroy() doesn't frees the object directly, but queues 
it for freeing. It solves all sort of problems


===================================================================
RCS file: /cvs/e/e17/proto/etk/src/lib/etk_combobox.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -3 -r1.23 -r1.24
--- etk_combobox.c      8 Aug 2006 18:51:22 -0000       1.23
+++ etk_combobox.c      13 Aug 2006 19:20:28 -0000      1.24
@@ -693,6 +693,7 @@
 /* Destroys the combobox */
 static void _etk_combobox_destructor(Etk_Combobox *combobox)
 {
+   Etk_Combobox_Item *item;
    int i;
    
    if (!combobox)
@@ -701,7 +702,13 @@
    combobox->selected_item = NULL;
    combobox->active_item = NULL;
    while (combobox->items)
-      etk_object_destroy(ETK_OBJECT(combobox->items->data));
+   {
+      item = ETK_COMBOBOX_ITEM(combobox->items->data);
+      
+      item->combobox = NULL;
+      etk_object_destroy(ETK_OBJECT(item));
+      combobox->items = evas_list_remove_list(combobox->items, 
combobox->items);
+   }
    free(combobox->active_item_children);
    
    for (i = 0; i < combobox->num_cols; i++)
===================================================================
RCS file: /cvs/e/e17/proto/etk/src/lib/etk_main.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -3 -r1.29 -r1.30
--- etk_main.c  5 Aug 2006 02:37:25 -0000       1.29
+++ etk_main.c  13 Aug 2006 19:20:28 -0000      1.30
@@ -44,12 +44,12 @@
 
 /**
  * @brief Initializes Etk. This function needs to be called before any other 
call to an etk_* function. @n
- * You can call safely etk_init() several times, it will have an effect only 
the first time you call it. The other times,
+ * You can call safely etk_init() several times, it will only have an effect 
the first time you call it. The other times,
  * it will just increment a counter. etk_shutdown() will decrement this 
counter and will effectively shutdown Etk when
  * the counter reaches 0. So you need to call etk_shutdown() the same number 
of times as etk_init().
- * @param argc the location of the "argc" paramater passed to main(). It is 
used to parse the arguments specific to Etk.
+ * @param argc the location of the "argc" parameter passed to main(). It is 
used to parse the arguments specific to Etk.
  * It can be set to NULL.
- * @param argv the location of the "argv" paramater passed to main(). It is 
used to parse the arguments specific to Etk.
+ * @param argv the location of the "argv" parameter passed to main(). It is 
used to parse the arguments specific to Etk.
  * It can be set to NULL.
  * @return Returns the number of times Etk has been initialized, or 0 on 
failure
  * @note It initializes Evas, Ecore and Edje so you don't need to initialize 
them after an etk_init()
@@ -132,8 +132,8 @@
    _etk_main_init_count--;
    if (_etk_main_init_count == 0)
    {
-      /* Shutdown the subsystem of Etk */
-      etk_object_destroy_all_objects();
+      /* Shutdown the subsystems of Etk */
+      etk_object_shutdown();
       etk_signal_shutdown();
       etk_type_shutdown();
       
@@ -143,7 +143,8 @@
       etk_engine_shutdown();
       etk_theme_shutdown();
       
-      _etk_main_toplevel_widgets = evas_list_free(_etk_main_toplevel_widgets);
+      evas_list_free(_etk_main_toplevel_widgets);
+      _etk_main_toplevel_widgets = NULL;
       
       /* Shutdown the EFL*/
       edje_shutdown();
@@ -195,6 +196,8 @@
 
    if (_etk_main_init_count <= 0)
       return;
+   
+   etk_object_purge();
 
    /* TODO: only update the toplevel widgets that need to be updated */
    for (l = _etk_main_toplevel_widgets; l; l = l->next)
@@ -240,7 +243,7 @@
 }
 
 /**
- * @brief Gets the list of the created toplevel widgets (windows, ...)
+ * @brief Gets the list of the created toplevel widgets (windows, embed 
widgets, ...)
  * @return Returns the list of the created toplevel widgets
  */
 Evas_List *etk_main_toplevel_widgets_get()
===================================================================
RCS file: /cvs/e/e17/proto/etk/src/lib/etk_object.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -3 -r1.25 -r1.26
--- etk_object.c        8 Aug 2006 18:03:01 -0000       1.25
+++ etk_object.c        13 Aug 2006 19:20:28 -0000      1.26
@@ -27,10 +27,12 @@
 
 static void _etk_object_constructor(Etk_Object *object);
 static void _etk_object_destructor(Etk_Object *object);
+static void _etk_object_free(Etk_Object *object);
 static Evas_Bool _etk_object_notification_callbacks_free_cb(Evas_Hash *hash, 
const char *key, void *data, void *fdata);
 static Evas_Bool _etk_object_data_free_cb(Evas_Hash *hash, const char *key, 
void *data, void *fdata);
 
-static Evas_List *_etk_object_created_objects = NULL;
+static Etk_Object *_etk_object_objects = NULL;
+static Etk_Object *_etk_object_last_object = NULL;
 static Etk_Signal *_etk_object_signals[ETK_OBJECT_NUM_SIGNALS];
 
 /**************************
@@ -40,6 +42,32 @@
  **************************/
 
 /**
+ * @internal
+ * @brief Shutdowns the object system: it frees all the created objects
+ */
+void etk_object_shutdown()
+{
+   while (_etk_object_objects)
+      _etk_object_free(_etk_object_objects);
+}
+/**
+ * @internal
+ * @brief Frees the objects that have been marked as "destroyed".
+ * It's called at the start of each iteration of the main loop
+ */
+void etk_object_purge()
+{
+   Etk_Object *object, *next;
+   
+   for (object = _etk_object_objects; object; object = next)
+   {
+      next = object->next;
+      if (object->destroy_me)
+         _etk_object_free(object);
+   }
+}
+
+/**
  * @brief Gets the type of an Etk_Object
  * @return Returns the type of an Etk_Object
  */
@@ -99,10 +127,9 @@
 
    if (!object_type)
       return NULL;
-
+   
    new_object = malloc(object_type->type_size);
    new_object->type = object_type;
-   _etk_object_created_objects = evas_list_append(_etk_object_created_objects, 
new_object);
    
    etk_type_object_construct(object_type, new_object);
    va_copy(args2, args);
@@ -113,28 +140,29 @@
 }
 
 /**
- * @brief Destroys the object: if first emits the "destroyed" signal, sets the 
weak pointers to NULL and then
- * calls the destructors (from the destructor of the more derived class to the 
destructor of the ultimate base class)
+ * @brief Destroys the object: it first sets the weak pointers to NULL, emits 
the "destroyed" signal, and then
+ * queues the object in the list of objects to free. Thus, the destructors 
will only be called at the beginning of the
+ * next main loop iteration (from the destructor of the more derived class to 
the destructor of the ultimate base class).
  * @param object the object to destroy
+ * @warning You should not assume that this function will call directly the 
destructors of the object!
  */
 void etk_object_destroy(Etk_Object *object)
 {
-   if (!object)
+   void **weak_pointer;
+   
+   if (!object || object->destroy_me)
       return;
 
+   /* Sets the weak pointers to NULL */
+   while (object->weak_pointers_list)
+   {
+      weak_pointer = object->weak_pointers_list->data;
+      *weak_pointer =  NULL;
+      object->weak_pointers_list = 
evas_list_remove_list(object->weak_pointers_list, object->weak_pointers_list);
+   }
+   
+   object->destroy_me = ETK_TRUE;
    etk_signal_emit(_etk_object_signals[ETK_OBJECT_DESTROYED_SIGNAL], object, 
NULL);
-   etk_type_destructors_call(object->type, object);
-   _etk_object_created_objects = evas_list_remove(_etk_object_created_objects, 
object);
-   free(object);
-}
-
-/**
- * @brief Destroys all the created objects. You do not need to call it 
manually, etk_shutdown() calls it automatically
- */
-void etk_object_destroy_all_objects()
-{
-   while (_etk_object_created_objects)
-      etk_object_destroy(ETK_OBJECT(_etk_object_created_objects->data));
 }
 
 /**
@@ -223,7 +251,7 @@
  */
 void etk_object_weak_pointer_add(Etk_Object *object, void **pointer_location)
 {
-   if (!object || !pointer_location)
+   if (!object || !pointer_location || object->destroy_me)
       return;
    object->weak_pointers_list = evas_list_append(object->weak_pointers_list, 
pointer_location);
 }
@@ -571,22 +599,23 @@
    object->after_signal_callbacks_list = NULL;
    object->notification_callbacks_hash = NULL;
    object->weak_pointers_list = NULL;
+   object->destroy_me = ETK_FALSE;
+   
+   /* Append the new object to the list */
+   object->prev = _etk_object_last_object;
+   object->next = NULL;
+   if (!_etk_object_objects)
+      _etk_object_objects = object;
+   if (_etk_object_last_object)
+      _etk_object_last_object->next = object;
+   _etk_object_last_object = object;
 }
 
 /* Destroys the object */
 static void _etk_object_destructor(Etk_Object *object)
 {
-   void **weak_pointer;
-   
    if (!object)
       return;
-
-   while (object->weak_pointers_list)
-   {
-      weak_pointer = object->weak_pointers_list->data;
-      *weak_pointer =  NULL;
-      object->weak_pointers_list = 
evas_list_remove_list(object->weak_pointers_list, object->weak_pointers_list);
-   }
    
    evas_hash_foreach(object->data_hash, _etk_object_data_free_cb, NULL);
    evas_hash_free(object->data_hash);
@@ -614,6 +643,28 @@
  *
  **************************/
 
+/* Frees the object: it calls the destructors (from the destructor of the more 
derived class
+ * to the destructor of the ultimate base class) and frees the allocated 
memory */
+static void _etk_object_free(Etk_Object *object)
+{
+   if (!object)
+      return;
+   
+   etk_object_destroy(object);
+   etk_type_destructors_call(object->type, object);
+   
+   if (object->prev)
+      object->prev->next = object->next;
+   if (object->next)
+      object->next->prev = object->prev;
+   if (object == _etk_object_objects)
+      _etk_object_objects = object->next;
+   if (object == _etk_object_last_object)
+      _etk_object_last_object = object->prev;
+   
+   free(object);
+}
+
 /* Frees a list of notification callbacks (called by _etk_object_destructor()) 
*/
 static Evas_Bool _etk_object_notification_callbacks_free_cb(Evas_Hash *hash, 
const char *key, void *data, void *fdata)
 {
@@ -671,9 +722,11 @@
  * etk_object_new() automatically calls the corresponding constructors of the 
object, from the constructor of
  * the base class to the constructor of the more derived class. @n
  *
- * You can also destroy an object with etk_object_destroy(). It sets the weak 
pointers of the object to NULL
- * (see etk_object_weak_pointer_add()) and then calls the destructors from the 
destructor of the more derived class
- * to the destructor of the ultimate base class. @n @n
+ * You can then destroy the object with etk_object_destroy(): it sets the weak 
pointers of the object to NULL
+ * (see etk_object_weak_pointer_add()), emits the "destroyed" signal and 
queues the object for freeing. Thus, the
+ * destructors will only be called at the beginning of the next main loop 
iteration (from the destructor of the more
+ * derived class to the destructor of the ultimate base class). So, you should 
not assume that etk_object_destroy()
+ * will directly call the destructors. @n @n
  *
  * <b>Signal concept:</b> @n
  * Each object has a list of signals that can be connected to one or several 
callbacks. The callbacks connected to
===================================================================
RCS file: /cvs/e/e17/proto/etk/src/lib/etk_object.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -3 -r1.9 -r1.10
--- etk_object.h        8 Aug 2006 18:03:01 -0000       1.9
+++ etk_object.h        13 Aug 2006 19:20:28 -0000      1.10
@@ -51,13 +51,19 @@
    Evas_List *after_signal_callbacks_list;
    Evas_Hash *notification_callbacks_hash;
    Evas_List *weak_pointers_list;
+   Etk_Bool destroy_me;
+   
+   Etk_Object *prev;
+   Etk_Object *next;
 };
 
+void etk_object_shutdown();
+void etk_object_purge();
+
 Etk_Type *etk_object_type_get();
 Etk_Object *etk_object_new(Etk_Type *object_type, const char *first_property, 
...);
 Etk_Object *etk_object_new_valist(Etk_Type *object_type, const char 
*first_property, va_list args);
 void etk_object_destroy(Etk_Object *object);
-void etk_object_destroy_all_objects();
 
 Etk_Object *etk_object_check_cast(Etk_Object *object, Etk_Type *type);
 Etk_Type *etk_object_object_type_get(Etk_Object *object);
===================================================================
RCS file: /cvs/e/e17/proto/etk/src/lib/etk_widget.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -3 -r1.69 -r1.70
--- etk_widget.c        8 Aug 2006 18:51:22 -0000       1.69
+++ etk_widget.c        13 Aug 2006 19:20:28 -0000      1.70
@@ -87,6 +87,7 @@
 
 static void _etk_widget_constructor(Etk_Widget *widget);
 static void _etk_widget_destructor(Etk_Widget *widget);
+static void _etk_widget_destroyed_cb(Etk_Object *object, void *data);
 static void _etk_widget_property_set(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
 static void _etk_widget_property_get(Etk_Object *object, int property_id, 
Etk_Property_Value *value);
 
@@ -1927,6 +1928,7 @@
    widget->dnd_types = NULL;
    widget->dnd_types_num = 0;
    
+   etk_signal_connect("destroyed", ETK_OBJECT(widget), 
ETK_CALLBACK(_etk_widget_destroyed_cb), NULL);
    etk_signal_connect("mouse_in", ETK_OBJECT(widget), 
ETK_CALLBACK(_etk_widget_signal_mouse_in_cb), NULL);
    etk_signal_connect("mouse_out", ETK_OBJECT(widget), 
ETK_CALLBACK(_etk_widget_signal_mouse_out_cb), NULL);
    etk_signal_connect("mouse_down", ETK_OBJECT(widget), 
ETK_CALLBACK(_etk_widget_signal_mouse_down_cb), NULL);
@@ -1946,11 +1948,6 @@
       return;
 
    _etk_widget_unrealize(widget);
-   
-   /* Remove the children */
-   while (widget->children)
-      etk_object_destroy(ETK_OBJECT(widget->children->data));
-   evas_list_free(widget->focus_order);
    etk_widget_parent_set(widget, NULL);
    
    while (widget->theme_children)
@@ -1972,6 +1969,27 @@
    
    free(widget->theme_file);
    free(widget->theme_group);
+}
+
+/* Called when etk_object_destroy() is called on the widget
+ * We use this to destroy the children of the widget because ... TODO */
+void _etk_widget_destroyed_cb(Etk_Object *object, void *data)
+{
+   Etk_Widget *widget;
+   Etk_Widget *child;
+   
+   if (!(widget = ETK_WIDGET(object)))
+      return;
+   
+   /* Remove the children */
+   while (widget->children)
+   {
+      child = ETK_WIDGET(widget->children->data);
+      
+      etk_widget_parent_set(child, NULL);
+      etk_object_destroy(ETK_OBJECT(child));
+   }
+   widget->focus_order = evas_list_free(widget->focus_order);
 }
 
 /* Sets the property whose id is "property_id" to the value "value" */



-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to