From 0047de749f4917858aec111918e4f6d1fbc481ee Mon Sep 17 00:00:00 2001 From: cedric Date: Thu, 28 Apr 2011 17:00:13 +0000 Subject: [PATCH] ethumb: cache exists result. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ethumb@59017 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/Ethumb.c | 94 ++++++++++++++++++++++++++++++++++++++++-- src/lib/Ethumb.h | 4 ++ src/lib/client/Ethumb_Client.c | 85 ++++++++++++++++++++++++++++++-------- 3 files changed, 161 insertions(+), 22 deletions(-) diff --git a/src/lib/Ethumb.c b/src/lib/Ethumb.c index 953215a..ba445b7 100644 --- a/src/lib/Ethumb.c +++ b/src/lib/Ethumb.c @@ -1563,7 +1563,7 @@ ethumb_exists(Ethumb *e) return r; } -Evas * +EAPI Evas * ethumb_evas_get(const Ethumb *e) { EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); @@ -1571,7 +1571,7 @@ ethumb_evas_get(const Ethumb *e) return e->sub_e; } -Ecore_Evas * +EAPI Ecore_Evas * ethumb_ecore_evas_get(const Ethumb *e) { EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); @@ -1579,7 +1579,7 @@ ethumb_ecore_evas_get(const Ethumb *e) return e->sub_ee; } -Ethumb * +EAPI Ethumb * ethumb_dup(const Ethumb *e) { Ecore_Evas *ee; @@ -1659,7 +1659,7 @@ ethumb_dup(const Ethumb *e) if (e1->Param != e2->Param) \ return EINA_TRUE; -Eina_Bool +EAPI Eina_Bool ethumb_cmp(const Ethumb *e1, const Ethumb *e2) { CHECK_DELTA(thumb_dir); @@ -1684,3 +1684,89 @@ ethumb_cmp(const Ethumb *e1, const Ethumb *e2) return EINA_FALSE; } + +EAPI unsigned int +ethumb_length(__UNUSED__ const void *key) +{ + return sizeof (Ethumb); +} + +#define CMP_PARAM(Param) \ + if (e1->Param != e2->Param) \ + return e1->Param - e2->Param; + +EAPI int +ethumb_key_cmp(const void *key1, __UNUSED__ int key1_length, + const void *key2, __UNUSED__ int key2_length) +{ + const Ethumb *e1 = key1; + const Ethumb *e2 = key2; + + CMP_PARAM(thumb_dir); + CMP_PARAM(category); + CMP_PARAM(thumb_dir); + CMP_PARAM(category); + CMP_PARAM(tw); + CMP_PARAM(th); + CMP_PARAM(format); + CMP_PARAM(aspect); + CMP_PARAM(orientation); + CMP_PARAM(crop_x); + CMP_PARAM(crop_y); + CMP_PARAM(quality); + CMP_PARAM(compress); + CMP_PARAM(rw); + CMP_PARAM(rh); + CMP_PARAM(video.start); + CMP_PARAM(video.time); + CMP_PARAM(video.interval); + CMP_PARAM(video.ntimes); + CMP_PARAM(video.fps); + CMP_PARAM(document.page); + CMP_PARAM(src_path); + CMP_PARAM(src_key); + + return 0; +} + +#undef CMP_PARAM + +#define HASH_PARAM_I(Param) r ^= eina_hash_int32((unsigned int*) &e->Param, 0); +#ifdef __LP64__ +# define HASH_PARAM_P(Param) r ^= eina_hash_int64((unsigned long int*) &e->Param, 0); +#else +# define HASH_PARAM_P(Param) r ^= eina_hash_int32((unsigned int*) &e->Param, 0); +#endif +#define HASH_PARAM_D(Param) r ^= eina_hash_int64((unsigned long int*)&e->Param, 0); +#define HASH_PARAM_F(Param) r ^= eina_hash_int32((unsigned int*) &e->Param, 0); + +EAPI int +ethumb_hash(const void *key, int key_length) +{ + const Ethumb *e = key; + int r = 0; + + HASH_PARAM_P(thumb_dir); + HASH_PARAM_P(category); + HASH_PARAM_I(tw); + HASH_PARAM_I(th); + HASH_PARAM_I(format); + HASH_PARAM_I(aspect); + HASH_PARAM_I(orientation); + HASH_PARAM_F(crop_x); + HASH_PARAM_F(crop_y); + HASH_PARAM_I(quality); + HASH_PARAM_I(compress); + HASH_PARAM_P(src_path); + HASH_PARAM_P(src_key); + HASH_PARAM_I(rw); + HASH_PARAM_I(rh); + HASH_PARAM_D(video.start); + HASH_PARAM_D(video.time); + HASH_PARAM_D(video.interval); + HASH_PARAM_I(video.ntimes); + HASH_PARAM_I(video.fps); + HASH_PARAM_I(document.page); + + return r; +} diff --git a/src/lib/Ethumb.h b/src/lib/Ethumb.h index afa0220..dc7b133 100644 --- a/src/lib/Ethumb.h +++ b/src/lib/Ethumb.h @@ -186,6 +186,10 @@ EAPI Eina_Bool ethumb_exists(Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL EAPI Ethumb *ethumb_dup(const Ethumb *e) EINA_ARG_NONNULL(1); EAPI Eina_Bool ethumb_cmp(const Ethumb *e1, const Ethumb *e2) EINA_ARG_NONNULL(1, 2) EINA_WARN_UNUSED_RESULT EINA_PURE; +EAPI int ethumb_hash(const void *key, int key_length) EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT EINA_PURE; +EAPI int ethumb_key_cmp(const void *key1, int key1_length, + const void *key2, int key2_length) EINA_ARG_NONNULL(1, 3) EINA_WARN_UNUSED_RESULT EINA_PURE; +EAPI unsigned int ethumb_length(const void *key) EINA_PURE EINA_WARN_UNUSED_RESULT; /** * @} diff --git a/src/lib/client/Ethumb_Client.c b/src/lib/client/Ethumb_Client.c index 3e05fac..8572775 100644 --- a/src/lib/client/Ethumb_Client.c +++ b/src/lib/client/Ethumb_Client.c @@ -169,14 +169,14 @@ struct _ethumb_pending_gen }; typedef struct _Ethumb_Async_Exists Ethumb_Async_Exists; +typedef struct _Ethumb_Async_Exists_Cb Ethumb_Async_Exists_Cb; struct _Ethumb_Async_Exists { Ethumb *dup; Ethumb_Client *source; - Ethumb_Client_Thumb_Exists_Cb exists_cb; - const void *data; + Eina_List *callbacks; Ecore_Thread *thread; int refcount; @@ -184,6 +184,12 @@ struct _Ethumb_Async_Exists Eina_Bool exists : 1; }; +struct _Ethumb_Async_Exists_Cb +{ + Ethumb_Client_Thumb_Exists_Cb exists_cb; + const void *data; +}; + static const char _ethumb_dbus_bus_name[] = "org.enlightenment.Ethumb"; static const char _ethumb_dbus_interface[] = "org.enlightenment.Ethumb"; static const char _ethumb_dbus_objects_interface[] = "org.enlightenment.Ethumb.objects"; @@ -193,6 +199,7 @@ static const char fdo_bus_name[] = "org.freedesktop.DBus"; static const char fdo_path[] = "/org/freedesktop/DBus"; static int _initcount = 0; +static Eina_Hash *_exists_request = NULL; static void _ethumb_client_generated_cb(void *data, DBusMessage *msg); static void _ethumb_client_get_name_owner(void *data, DBusMessage *msg, DBusError *err); @@ -252,6 +259,20 @@ __dbus_iter_type_check(int type, int expected, const char *expected_name) while (0) static void +_ethumb_async_delete(void *data) +{ + Ethumb_Async_Exists *async = data; + + ethumb_free(async->dup); + async->source->refcount--; + + if (async->source->delete_me == EINA_TRUE) + ethumb_client_disconnect(async->source); + + free(async); +} + +static void _ethumb_client_name_owner_changed(void *data, DBusMessage *msg) { DBusError err; @@ -495,40 +516,38 @@ static void _ethumb_client_exists_end(void *data, Ecore_Thread *thread) { Ethumb_Async_Exists *async = data; + Ethumb_Async_Exists_Cb *cb; Ethumb *tmp = async->source->ethumb; async->source->ethumb = async->dup; async->source->ethumb_dirty = ethumb_cmp(tmp, async->dup); - async->exists_cb(async->source, (Ethumb_Exists*) async, async->exists, (void*) async->data); - async->source->ethumb = tmp; - ethumb_free(async->dup); - async->source->refcount--; + EINA_LIST_FREE(async->callbacks, cb) + cb->exists_cb(async->source, (Ethumb_Exists*) async, async->exists, (void*) cb->data); - if (async->source->delete_me == EINA_TRUE) - ethumb_client_disconnect(async->source); + async->source->ethumb = tmp; + async->thread = NULL; - free(async); + eina_hash_del(_exists_request, async->dup, async); } static void _ethumb_client_exists_cancel(void *data, Ecore_Thread *thread) { + Ethumb_Async_Exists_Cb *cb; Ethumb_Async_Exists *async = data; Ethumb *tmp = async->source->ethumb; async->source->ethumb = async->dup; async->source->ethumb_dirty = ethumb_cmp(tmp, async->dup); - async->exists_cb(async->source, (Ethumb_Exists*) async, EINA_FALSE, (void*) async->data); - async->source->ethumb = tmp; - ethumb_free(async->dup); - async->source->refcount--; + EINA_LIST_FREE(async->callbacks, cb) + cb->exists_cb(async->source, (Ethumb_Exists*) async, EINA_FALSE, (void*) cb->data); - if (async->source->delete_me == EINA_TRUE) - ethumb_client_disconnect(async->source); + async->source->ethumb = tmp; + async->thread = NULL; - free(async); + eina_hash_del(_exists_request, async->dup, async); } /** @@ -574,6 +593,12 @@ ethumb_client_init(void) ethumb_init(); e_dbus_init(); + _exists_request = eina_hash_new(ethumb_length, + ethumb_key_cmp, + ethumb_hash, + _ethumb_async_delete, + 3); + return ++_initcount; } @@ -600,6 +625,8 @@ ethumb_client_shutdown(void) if (_initcount > 0) return _initcount; + /* should find a non racy solution to closing all pending exists request */ + e_dbus_shutdown(); ethumb_shutdown(); eina_log_domain_unregister(_log_dom); @@ -2122,13 +2149,33 @@ ethumb_client_thumb_path_get(Ethumb_Client *client, const char **path, const cha EAPI Ethumb_Exists * ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb exists_cb, const void *data) { + Ethumb_Async_Exists_Cb *cb; Ethumb_Async_Exists *async; EINA_SAFETY_ON_NULL_RETURN_VAL(client, NULL); + cb = malloc(sizeof (Ethumb_Async_Exists_Cb)); + if (!cb) + { + exists_cb(client, NULL, EINA_FALSE, (void*) data); + return NULL; + } + + cb->exists_cb = exists_cb; + cb->data = data; + + async = eina_hash_find(_exists_request, client->ethumb); + if (async) + { + async->refcount++; + async->callbacks = eina_list_append(async->callbacks, cb); + return (Ethumb_Exists*) async; + } + async = malloc(sizeof (Ethumb_Async_Exists)); if (!async) { + free(cb); exists_cb(client, NULL, EINA_FALSE, (void*) data); return NULL; } @@ -2136,16 +2183,18 @@ ethumb_client_thumb_exists(Ethumb_Client *client, Ethumb_Client_Thumb_Exists_Cb async->dup = ethumb_dup(client->ethumb); async->source = client; async->source->refcount++; - async->exists_cb = exists_cb; - async->data = data; async->exists = EINA_FALSE; + async->callbacks = eina_list_append(NULL, cb); + async->refcount = 1; async->thread = ecore_thread_run(_ethumb_client_exists_heavy, _ethumb_client_exists_end, _ethumb_client_exists_cancel, async); + eina_hash_direct_add(_exists_request, async->dup, async); + return (Ethumb_Exists*) async; } -- 2.7.4