[gnome-calendar] event: cache events
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar] event: cache events
- Date: Thu, 7 Sep 2017 05:10:20 +0000 (UTC)
commit 941f3ee77d48f23fb2e63bb5c64e9e07c1b59fd5
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Thu Sep 7 02:09:09 2017 -0300
event: cache events
This speeds up Calendar a little bit, and more importantly,
allows me to sleep well at night now.
src/gcal-event.c | 68 +++++++++++++++++++++++++++---
src/gcal-event.h | 1 +
src/gcal-manager.c | 15 +++----
src/gconstructor.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 189 insertions(+), 15 deletions(-)
---
diff --git a/src/gcal-event.c b/src/gcal-event.c
index 41f8475..38cd464 100644
--- a/src/gcal-event.c
+++ b/src/gcal-event.c
@@ -18,6 +18,7 @@
#define G_LOG_DOMAIN "GcalEvent"
+#include "gconstructor.h"
#include "gcal-event.h"
#include "gcal-utils.h"
#include "gcal-recurrence.h"
@@ -134,6 +135,33 @@ enum {
N_PROPS
};
+
+/*
+ * GcalEvent cache
+ */
+
+static GHashTable *event_cache = NULL;
+
+G_DEFINE_CONSTRUCTOR (init_event_cache_map);
+
+static void
+init_event_cache_map (void)
+{
+ event_cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+}
+
+G_DEFINE_DESTRUCTOR (destroy_event_cache_map);
+
+static void
+destroy_event_cache_map (void)
+{
+ g_hash_table_destroy (event_cache);
+}
+
+/*
+ * Auxiliary methods
+ */
+
static GTimeZone*
get_timezone_from_ical (ECalComponentDateTime *comp)
{
@@ -428,6 +456,10 @@ gcal_event_finalize (GObject *object)
{
GcalEvent *self = (GcalEvent *)object;
+ g_debug ("Removing '%s' (%p) from cache", self->uid, self);
+
+ g_hash_table_remove (event_cache, self->uid);
+
g_clear_pointer (&self->dt_start, g_date_time_unref);
g_clear_pointer (&self->dt_end, g_date_time_unref);
g_clear_pointer (&self->timezone, g_time_zone_unref);
@@ -791,12 +823,36 @@ gcal_event_new (ESource *source,
ECalComponent *component,
GError **error)
{
- return g_initable_new (GCAL_TYPE_EVENT,
- NULL,
- error,
- "source", source,
- "component", component,
- NULL);
+ GcalEvent *event;
+ g_autofree gchar *uuid;
+
+ uuid = get_uuid_from_component (source, component);
+
+ if (g_hash_table_contains (event_cache, uuid))
+ {
+ g_debug ("Using cached value for %s", uuid);
+
+ event = g_hash_table_lookup (event_cache, uuid);
+ gcal_event_set_component_internal (event, component);
+ g_object_ref (event);
+ }
+ else
+ {
+ event = g_initable_new (GCAL_TYPE_EVENT,
+ NULL,
+ error,
+ "source", source,
+ "component", component,
+ NULL);
+
+ if (event)
+ {
+ g_debug ("Adding %s to the cache", event->uid);
+ g_hash_table_insert (event_cache, event->uid, event);
+ }
+ }
+
+ return event;
}
/**
diff --git a/src/gcal-event.h b/src/gcal-event.h
index 6a1b805..1621bfc 100644
--- a/src/gcal-event.h
+++ b/src/gcal-event.h
@@ -129,6 +129,7 @@ void gcal_event_set_recurrence (GcalEvent
GcalRecurrence* gcal_event_get_recurrence (GcalEvent *self);
+void gcal_event_remove_from_cache (GcalEvent *self);
G_END_DECLS
diff --git a/src/gcal-manager.c b/src/gcal-manager.c
index ac62d76..e1d727c 100644
--- a/src/gcal-manager.c
+++ b/src/gcal-manager.c
@@ -483,6 +483,7 @@ on_event_created (GObject *source_object,
}
else
{
+ g_object_ref (data->event);
gcal_manager_set_default_source (data->manager, gcal_event_get_source (data->event));
g_debug ("Event: %s created successfully", new_uid);
}
@@ -540,11 +541,13 @@ on_event_removed (GObject *source_object,
gpointer user_data)
{
ECalClient *client;
+ GcalEvent *event;
GError *error;
GCAL_ENTRY;
client = E_CAL_CLIENT (source_object);
+ event = user_data;
error = NULL;
e_cal_client_remove_object_finish (client, result, &error);
@@ -554,9 +557,10 @@ on_event_removed (GObject *source_object,
/* FIXME: Notify the user somehow */
g_warning ("Error removing event: %s", error->message);
g_error_free (error);
+ GCAL_RETURN ();
}
- g_object_unref (user_data);
+ g_object_unref (event);
GCAL_EXIT;
}
@@ -1828,20 +1832,13 @@ gcal_manager_remove_event (GcalManager *manager,
if (gcal_event_has_recurrence (event))
rid = e_cal_component_get_recurid_as_string (component);
- /*
- * While we're removing the event, we don't want the component
- * to be destroyed, so take a reference of the component while
- * we're deleting it.
- */
- g_object_ref (component);
-
e_cal_client_remove_object (unit->client,
uid,
mod == GCAL_RECURRENCE_MOD_ALL ? NULL : rid,
(ECalObjModType) mod,
manager->async_ops,
on_event_removed,
- component);
+ event);
g_free (rid);
diff --git a/src/gconstructor.h b/src/gconstructor.h
new file mode 100644
index 0000000..dccb031
--- /dev/null
+++ b/src/gconstructor.h
@@ -0,0 +1,120 @@
+/*
+ If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
+ destructors, in a sane way, including e.g. on library unload. If not you're on
+ your own.
+
+ Some compilers need #pragma to handle this, which does not work with macros,
+ so the way you need to use this is (for constructors):
+
+ #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+ #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
+ #endif
+ G_DEFINE_CONSTRUCTOR(my_constructor)
+ static void my_constructor(void) {
+ ...
+ }
+
+*/
+
+#ifndef __GTK_DOC_IGNORE__
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
+#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
+/* Visual studio 2008 and later has _Pragma */
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* We do some weird things to avoid the constructors being optimized
+ * away on VS2015 if WholeProgramOptimization is enabled. First we
+ * make a reference to the array from the wrapper to make sure its
+ * references. Then we use a pragma to make sure the wrapper function
+ * symbol is always included at the link stage. Also, the symbols
+ * need to be extern (but not dllexport), even though they are not
+ * really used from another object file.
+ */
+
+/* We need to account for differences between the mangling of symbols
+ * for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed
+ * with an underscore but symbols on x64 are not.
+ */
+#ifdef _WIN64
+#define G_MSVC_SYMBOL_PREFIX ""
+#else
+#define G_MSVC_SYMBOL_PREFIX "_"
+#endif
+
+#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
+#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
+
+#define G_MSVC_CTOR(_func,_sym_prefix) \
+ static void _func(void); \
+ extern int (* _array ## _func)(void); \
+ int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \
+ __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
+ __pragma(section(".CRT$XCU",read)) \
+ __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
+
+#define G_MSVC_DTOR(_func,_sym_prefix) \
+ static void _func(void); \
+ extern int (* _array ## _func)(void); \
+ int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \
+ __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
+ __pragma(section(".CRT$XCU",read)) \
+ __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined (_MSC_VER)
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* Pre Visual studio 2008 must use #pragma section */
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+ section(".CRT$XCU",read)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+ static void _func(void); \
+ static int _func ## _wrapper(void) { _func(); return 0; } \
+ __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+ section(".CRT$XCU",read)
+#define G_DEFINE_DESTRUCTOR(_func) \
+ static void _func(void); \
+ static int _func ## _constructor(void) { atexit (_func); return 0; } \
+ __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined(__SUNPRO_C)
+
+/* This is not tested, but i believe it should work, based on:
+ * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
+ */
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+ init(_func)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+ static void _func(void);
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+ fini(_func)
+#define G_DEFINE_DESTRUCTOR(_func) \
+ static void _func(void);
+
+#else
+
+/* constructors not supported for this compiler */
+
+#endif
+
+#endif /* __GTK_DOC_IGNORE__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]