cedric pushed a commit to branch master.

commit 7506faaca2f5f7500426d4edaf3aaaef0e0ed707
Author: Cedric Bail <[email protected]>
Date:   Fri Aug 9 20:49:52 2013 +0900

    edje: add edje_file_mmap_set.
    
    This reduce the number of system call to stat especially when using GROUP
    and reduce the risk of a race condition when using GROUP.
---
 ChangeLog                   |  4 +++
 NEWS                        |  1 +
 src/lib/edje/Edje_Eo.h      | 14 ++++++++
 src/lib/edje/Edje_Legacy.h  | 36 +++++++++++++++++++++
 src/lib/edje/edje_cache.c   | 30 ++++-------------
 src/lib/edje/edje_load.c    | 79 ++++++++++++++++++++++++++++++---------------
 src/lib/edje/edje_private.h |  5 ++-
 src/lib/edje/edje_smart.c   | 29 ++++++++++++++++-
 8 files changed, 145 insertions(+), 53 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4d4b518..4be775c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-08-09  Cedric Bail
+
+       * Edje: add edje_object_mmap_set().
+
 2013-08-08  Tom Hacohen
 
        * Evas textblock:  Make the ellipsis format the same as the surrounding.
diff --git a/NEWS b/NEWS
index c717434..0790089 100644
--- a/NEWS
+++ b/NEWS
@@ -128,6 +128,7 @@ Additions:
      - support edc map color set
      - Add threshold support to Edje draggable part.
      - Reduce load time of Edje_Object using Evas_Object_Textblock and many 
styles.
+     - Add edje_object_mmap_set.
     * Eeze:
      - Add a dummy libmount replacement for when libmount is not there.
     * Ecore_Con:
diff --git a/src/lib/edje/Edje_Eo.h b/src/lib/edje/Edje_Eo.h
index 941aee4..6678a96 100644
--- a/src/lib/edje/Edje_Eo.h
+++ b/src/lib/edje/Edje_Eo.h
@@ -132,6 +132,7 @@ enum
    EDJE_OBJ_SUB_ID_PART_EXTERNAL_PARAM_TYPE_GET,
 
    EDJE_OBJ_SUB_ID_FILE_SET,
+   EDJE_OBJ_SUB_ID_MMAP_SET,
    EDJE_OBJ_SUB_ID_FILE_GET,
    EDJE_OBJ_SUB_ID_LOAD_ERROR_GET,
 
@@ -612,6 +613,19 @@ enum
 #define edje_obj_file_set(file, group, ret) 
EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_FILE_SET), EO_TYPECHECK(const char*, file), 
EO_TYPECHECK(const char *, group), EO_TYPECHECK(Eina_Bool *, ret)
 
 /**
+ * @def edje_obj_mmap_set
+ * @since 1.8
+ *
+ * @param[in] file in
+ * @param[in] group in
+ * @param[in] nested in
+ * @param[out] ret out
+ *
+ * @see edje_object_file_set
+ */
+#define edje_obj_mmap_set(file, group, ret) 
EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MMAP_SET), EO_TYPECHECK(Eina_File*, file), 
EO_TYPECHECK(const char *, group), EO_TYPECHECK(Eina_Bool *, ret)
+
+/**
  * @def edje_obj_file_get
  * @since 1.8
  *
diff --git a/src/lib/edje/Edje_Legacy.h b/src/lib/edje/Edje_Legacy.h
index 3b0ccab..196e498 100644
--- a/src/lib/edje/Edje_Legacy.h
+++ b/src/lib/edje/Edje_Legacy.h
@@ -1770,10 +1770,46 @@ EAPI const char  *edje_object_data_get            
(const Evas_Object *obj, const
  *
  * @see edje_object_add()
  * @see edje_object_file_get()
+ * @see edje_object_mmap_set()
  */
 EAPI Eina_Bool        edje_object_file_set        (Evas_Object *obj, const 
char *file, const char *group);
 
 /**
+ * @brief Sets the @b EDJ file (and group within it) to load an Edje
+ * object's contents from
+ *
+ * @param obj A handle to an Edje object
+ * @param file The Eina_File pointing to the EDJ file to load @p from
+ * @param group The name of the group, in @p file, which implements an
+ * Edje object
+ * @return @c EINA_TRUE, on success or @c EINA_FALSE, on errors (check
+ * edje_object_load_error_get() after this call to get errors causes)
+ *
+ * Edje expects EDJ files, which are theming objects' descriptions and
+ * resources packed together in an EET file, to read Edje object
+ * definitions from. They usually are created with the @c .edj
+ * extension. EDJ files, in turn, are assembled from @b textual object
+ * description files, where one describes Edje objects declaratively
+ * -- the EDC files (see @ref edcref "the syntax" for those files).
+ *
+ * Those description files were designed so that many Edje object
+ * definitions -- also called @b groups (or collections) -- could be
+ * packed together <b>in the same EDJ file</b>, so that a whole
+ * application's theme could be packed in one file only. This is the
+ * reason for the @p group argument.
+ *
+ * Use this function after you instantiate a new Edje object, so that
+ * you can "give him life", telling where to get its contents from.
+ *
+ * @see edje_object_add()
+ * @see edje_object_file_get()
+ * @see edje_object_mmap_set()
+ * @since 1.8
+ */
+EAPI Eina_Bool edje_object_mmap_set(Evas_Object *obj, Eina_File *file, const 
char *group);
+
+
+/**
  * @brief Get the file and group name that a given Edje object is bound to
  *
  * @param obj A handle to an Edje object
diff --git a/src/lib/edje/edje_cache.c b/src/lib/edje/edje_cache.c
index aa7e075..100ca55 100644
--- a/src/lib/edje/edje_cache.c
+++ b/src/lib/edje/edje_cache.c
@@ -399,32 +399,22 @@ _edje_file_dangling(Edje_File *edf)
 #endif
 
 Edje_File *
-_edje_cache_file_coll_open(const char *file, const char *coll, int *error_ret, 
Edje_Part_Collection **edc_ret, Edje *ed)
+_edje_cache_file_coll_open(Eina_File *file, const char *coll, int *error_ret, 
Edje_Part_Collection **edc_ret, Edje *ed)
 {
-   Eina_File *f;
    Edje_File *edf;
    Eina_List *l, *hist;
    Edje_Part_Collection *edc;
    Edje_Part *ep;
 
-   f = eina_file_open(file, EINA_FALSE);
-   if (!f)
-     {
-        *error_ret = EDJE_LOAD_ERROR_DOES_NOT_EXIST;
-        return NULL;
-     }
-
    if (!_edje_file_hash)
      {
        _edje_file_hash = eina_hash_pointer_new(NULL);
        goto find_list;
      }
 
-   edf = eina_hash_find(_edje_file_hash, f);
+   edf = eina_hash_find(_edje_file_hash, file);
    if (edf)
      {
-        eina_file_close(f);
-
        edf->references++;
        goto open;
      }
@@ -432,23 +422,17 @@ _edje_cache_file_coll_open(const char *file, const char 
*coll, int *error_ret, E
 find_list:
    EINA_LIST_FOREACH(_edje_file_cache, l, edf)
      {
-       if (edf->f == f)
+       if (edf->f == file)
          {
-             eina_file_close(f);
-
             edf->references = 1;
             _edje_file_cache = eina_list_remove_list(_edje_file_cache, l);
-            eina_hash_direct_add(_edje_file_hash, f, edf);
+            eina_hash_direct_add(_edje_file_hash, file, edf);
             goto open;
          }
      }
 
-   edf = _edje_file_open(f, coll, error_ret, edc_ret, eina_file_mtime_get(f));
-   if (!edf)
-     {
-        eina_file_close(f);
-        return NULL;
-     }
+   edf = _edje_file_open(file, coll, error_ret, edc_ret, 
eina_file_mtime_get(file));
+   if (!edf) return NULL;
 
 #ifdef HAVE_EIO
    if (ed) edf->edjes = eina_list_append(edf->edjes, ed);
@@ -456,7 +440,7 @@ find_list:
    (void) ed;
 #endif
 
-   eina_hash_direct_add(_edje_file_hash, f, edf);
+   eina_hash_direct_add(_edje_file_hash, file, edf);
    /* return edf; */
 
 open:
diff --git a/src/lib/edje/edje_load.c b/src/lib/edje/edje_load.c
index 331dab5..a65dbd5 100644
--- a/src/lib/edje/edje_load.c
+++ b/src/lib/edje/edje_load.c
@@ -24,6 +24,8 @@ struct _Edje_Drag_Items
    } page;
 };
 
+void _edje_file_add(Edje *ed, Eina_File *f);
+
 /* START - Nested part support */
 #define _edje_smart_nested_type "Evas_Smart_Nested"
 typedef struct _Edje_Nested_Support Edje_Nested_Support;
@@ -80,6 +82,16 @@ edje_object_file_set(Evas_Object *obj, const char *file, 
const char *group)
    return ret;
 }
 
+EAPI Eina_Bool
+edje_object_mmap_set(Evas_Object *obj, Eina_File *file, const char *group)
+{
+   if (!obj) return EINA_FALSE;
+   Eina_Bool ret = EINA_FALSE;
+
+   eo_do(obj, edje_obj_mmap_set(file, group, &ret));
+   return ret;
+}
+
 EAPI void
 edje_object_file_get(const Evas_Object *obj, const char **file, const char 
**group)
 {
@@ -149,11 +161,14 @@ EAPI Eina_List *
 edje_file_collection_list(const char *file)
 {
    Eina_List *lst = NULL;
+   Eina_File *f;
    Edje_File *edf;
    int error_ret = 0;
 
    if ((!file) || (!*file)) return NULL;
-   edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL);
+   f = eina_file_open(file, EINA_FALSE);
+   if (!f) return NULL;
+   edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
    if (edf)
      {
         Eina_Iterator *i;
@@ -168,6 +183,7 @@ edje_file_collection_list(const char *file)
 
         _edje_cache_file_unref(edf);
      }
+   eina_file_close(f);
    return lst;
 }
 
@@ -185,6 +201,7 @@ EAPI Eina_Bool
 edje_file_group_exists(const char *file, const char *glob)
 {
    Edje_File *edf;
+   Eina_File *f;
    int error_ret = 0;
    Eina_Bool succeed = EINA_FALSE;
    Eina_Bool is_glob = EINA_FALSE;
@@ -193,9 +210,11 @@ edje_file_group_exists(const char *file, const char *glob)
    if ((!file) || (!*file) || (!glob))
       return EINA_FALSE;
 
-   edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL);
-   if (!edf)
-      return EINA_FALSE;
+   f = eina_file_open(file, EINA_FALSE);
+   if (!f) return EINA_FALSE;
+
+   edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
+   if (!edf) goto on_error;
 
    for (p = glob; *p; p++)
      {
@@ -240,6 +259,8 @@ edje_file_group_exists(const char *file, const char *glob)
 
    DBG("edje_file_group_exists: '%s', '%s': %i.", file, glob, succeed);
 
+ on_error:
+   eina_file_close(f);
    return succeed;
 }
 
@@ -248,12 +269,16 @@ EAPI char *
 edje_file_data_get(const char *file, const char *key)
 {
    Edje_File *edf;
+   Eina_File *f;
    char *str = NULL;
    int error_ret = 0;
 
    if (key)
      {
-        edf = _edje_cache_file_coll_open(file, NULL, &error_ret, NULL, NULL);
+        f = eina_file_open(file, EINA_FALSE);
+        if (!f) return NULL;
+
+        edf = _edje_cache_file_coll_open(f, NULL, &error_ret, NULL, NULL);
         if (edf)
           {
              str = (char*) edje_string_get(eina_hash_find(edf->data, key));
@@ -262,6 +287,8 @@ edje_file_data_get(const char *file, const char *key)
 
              _edje_cache_file_unref(edf);
           }
+
+        eina_file_close(f);
      }
    return str;
 }
@@ -290,7 +317,7 @@ _edje_physics_world_update_cb(void *data, EPhysics_World 
*world EINA_UNUSED, voi
 #endif
 
 int
-_edje_object_file_set_internal(Evas_Object *obj, const char *file, const char 
*group, const char *parent, Eina_List *group_path, Eina_Array *nested)
+_edje_object_file_set_internal(Evas_Object *obj, Eina_File *file, const char 
*group, const char *parent, Eina_List *group_path, Eina_Array *nested)
 {
    Edje *ed;
    Evas *tev;
@@ -310,18 +337,11 @@ _edje_object_file_set_internal(Evas_Object *obj, const 
char *file, const char *g
 
    ed = _edje_fetch(obj);
    if (!ed) return 0;
-   if (!file) file = "";
    if (!group) group = "";
-   if (((ed->path) && (!strcmp(file, ed->path))) &&
-       (ed->group) && (!strcmp(group, ed->group)) &&
-       ed->file)
+   if ((ed->file) && (ed->file->f == file) &&
+       (ed->group) && (!strcmp(group, ed->group)))
      {
-        struct stat st;
-
-        if (stat(file, &st) != 0)
-          return 1;
-        if (st.st_mtime == ed->file->mtime)
-          return 1;
+        return 1;
      }
 
    tev = evas_object_evas_get(obj);
@@ -343,13 +363,13 @@ _edje_object_file_set_internal(Evas_Object *obj, const 
char *file, const char *g
 
    _edje_file_del(ed);
 
-   eina_stringshare_replace(&ed->path, file);
+   eina_stringshare_replace(&ed->path, file ? eina_file_filename_get(file) : 
NULL);
    eina_stringshare_replace(&ed->group, group);
 
    ed->parent = eina_stringshare_add(parent);
 
    ed->load_error = EDJE_LOAD_ERROR_NONE;
-   _edje_file_add(ed);
+   _edje_file_add(ed, file);
    ed->block_break = EINA_FALSE;
 
    if (ed->file && ed->file->external_dir)
@@ -567,7 +587,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char 
*file, const char *g
                           break;
                        case EDJE_PART_TYPE_GRADIENT:
                           ERR("SPANK ! SPANK ! SPANK ! YOU ARE USING GRADIENT 
IN PART %s FROM GROUP %s INSIDE FILE %s !! THEY ARE NOW REMOVED !",
-                              ep->name, group, file);
+                              ep->name, group, eina_file_filename_get(file));
                           break;
                        case EDJE_PART_TYPE_SPACER:
                           rp->object = NULL;
@@ -834,7 +854,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char 
*file, const char *g
                               if (data == group_path_entry)
                                 {
                                    ERR("recursive loop group '%s' already 
included inside part '%s' of group '%s' from file '%s'",
-                                       group_path_entry, rp->part->name, 
group, file);
+                                       group_path_entry, rp->part->name, 
group, eina_file_filename_get(file));
                                    ed->load_error = 
EDJE_LOAD_ERROR_RECURSIVE_REFERENCE;
                                    eina_stringshare_del(group_path_entry);
                                    goto on_error;
@@ -862,7 +882,7 @@ _edje_object_file_set_internal(Evas_Object *obj, const char 
*file, const char *g
                               if (!_edje_object_file_set_internal(child_obj, 
file, source, rp->part->name, group_path, nested))
                                 {
                                    ERR("impossible to set part '%s' of group 
'%s' from file '%s' to '%s'",
-                                       rp->part->name, group_path_entry, file, 
source);
+                                       rp->part->name, group_path_entry, 
eina_file_filename_get(file), source);
                                    ed->load_error = 
edje_object_load_error_get(child_obj);
                                    evas_object_del(child_obj);
                                    eina_stringshare_del(group_path_entry);
@@ -1106,13 +1126,20 @@ on_error:
 }
 
 void
-_edje_file_add(Edje *ed)
+_edje_file_add(Edje *ed, Eina_File *f)
 {
    if (!_edje_edd_edje_file) return;
-   ed->file = _edje_cache_file_coll_open(ed->path, ed->group,
-                                         &(ed->load_error),
-                                         &(ed->collection),
-                                         ed);
+   if (!f)
+     {
+        ed->load_error = EDJE_LOAD_ERROR_DOES_NOT_EXIST;
+     }
+   else
+     {
+        ed->file = _edje_cache_file_coll_open(f, ed->group,
+                                              &(ed->load_error),
+                                              &(ed->collection),
+                                              ed);
+     }
 
    if (!ed->collection)
      {
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index b29b469..608aa01 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -1967,9 +1967,8 @@ void *_edje_signal_callback_disable(const 
Edje_Signal_Callback_Group *cgp,
 EAPI void _edje_edd_init(void);
 EAPI void _edje_edd_shutdown(void);
 
-int _edje_object_file_set_internal(Evas_Object *obj, const char *file, const 
char *group, const char *parent, Eina_List *group_path, Eina_Array *nested);
+int _edje_object_file_set_internal(Evas_Object *obj, Eina_File *file, const 
char *group, const char *parent, Eina_List *group_path, Eina_Array *nested);
 
-void  _edje_file_add(Edje *ed);
 void  _edje_file_del(Edje *ed);
 void  _edje_file_free(Edje_File *edf);
 void  _edje_file_cache_shutdown(void);
@@ -2150,7 +2149,7 @@ void _edje_textblock_styles_del(Edje *ed);
 void _edje_textblock_style_all_update(Edje *ed);
 void _edje_textblock_style_parse_and_fix(Edje_File *edf);
 void _edje_textblock_style_cleanup(Edje_File *edf);
-Edje_File *_edje_cache_file_coll_open(const char *file, const char *coll, int 
*error_ret, Edje_Part_Collection **edc_ret, Edje *ed);
+Edje_File *_edje_cache_file_coll_open(Eina_File *file, const char *coll, int 
*error_ret, Edje_Part_Collection **edc_ret, Edje *ed);
 void _edje_cache_coll_clean(Edje_File *edf);
 void _edje_cache_coll_flush(Edje_File *edf);
 void _edje_cache_coll_unref(Edje_File *edf, Edje_Part_Collection *edc);
diff --git a/src/lib/edje/edje_smart.c b/src/lib/edje/edje_smart.c
index e4590fb..b692a5a 100644
--- a/src/lib/edje/edje_smart.c
+++ b/src/lib/edje/edje_smart.c
@@ -333,12 +333,37 @@ _edje_smart_file_set(Eo *obj, void *_pd EINA_UNUSED, 
va_list *list)
    const char *file = va_arg(*list, const char *);
    const char *group = va_arg(*list, const char *);
    Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+   Eina_File *f;
    Eina_Array *nested;
+
    if (ret) *ret = EINA_FALSE;
 
+   f = eina_file_open(file, EINA_FALSE);
    nested = eina_array_new(8);
-   if (_edje_object_file_set_internal(obj, file, group, NULL, NULL, nested))
+
+   if (_edje_object_file_set_internal(obj, f, group, NULL, NULL, nested))
      if (ret) *ret = EINA_TRUE;
+
+   eina_array_free(nested);
+   eina_file_close(f);
+   _edje_object_orientation_inform(obj);
+}
+
+static void
+_edje_smart_mmap_set(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
+{
+   Eina_File *f = va_arg(*list, Eina_File *);
+   const char *group = va_arg(*list, const char *);
+   Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+   Eina_Array *nested;
+
+   if (ret) *ret = EINA_FALSE;
+
+   nested = eina_array_new(8);
+
+   if (_edje_object_file_set_internal(obj, f, group, NULL, NULL, nested))
+     if (ret) *ret = EINA_TRUE;
+
    eina_array_free(nested);
    _edje_object_orientation_inform(obj);
 }
@@ -481,6 +506,7 @@ _edje_smart_class_constructor(Eo_Class *klass)
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PART_EXTERNAL_CONTENT_GET), 
_part_external_content_get),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_PART_EXTERNAL_PARAM_TYPE_GET), 
_part_external_param_type_get),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_FILE_SET), 
_edje_smart_file_set),
+        EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MMAP_SET), 
_edje_smart_mmap_set),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_FILE_GET), _file_get),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_LOAD_ERROR_GET), 
_load_error_get),
         EO_OP_FUNC(EDJE_OBJ_ID(EDJE_OBJ_SUB_ID_MESSAGE_SEND), _message_send),
@@ -626,6 +652,7 @@ static const Eo_Op_Description op_desc[] = {
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PART_EXTERNAL_CONTENT_GET, "Get an 
object contained in an part of type EXTERNAL"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_PART_EXTERNAL_PARAM_TYPE_GET, "Facility 
to query the type of the given parameter of the given part."),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_FILE_SET, "Sets the @b EDJ file (and 
group within it) to load an Edje"),
+     EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MMAP_SET, "Sets the @b EDJ file (and 
group within it) to load an Edje"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_FILE_GET, "Get the file and group name 
that a given Edje object is bound to"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_LOAD_ERROR_GET, "Gets the (last) file 
loading error for a given Edje object"),
      EO_OP_DESCRIPTION(EDJE_OBJ_SUB_ID_MESSAGE_SEND, "Send an (Edje) message 
to a given Edje object"),

-- 

------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead. 
Download for free and get started troubleshooting in minutes. 
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk

Reply via email to