event: cache events
This speeds up Calendar a little bit, and more importantly, allows me to sleep well at night now.
This commit is contained in:
+62
-6
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+6
-9
@@ -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);
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
Reference in New Issue
Block a user