[Xfce4-commits] <tumbler:master> Quit tumbler after five minutes of inactivity.

Jannis Pohlmann noreply at xfce.org
Sun Feb 13 23:14:01 CET 2011


Updating branch refs/heads/master
         to ee0e466351457f1cc2e9856ec66c2f2fa798e363 (commit)
       from ac10985250530ecc04daf91081737a9d3bc763db (commit)

commit ee0e466351457f1cc2e9856ec66c2f2fa798e363
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Sun Feb 13 23:07:47 2011 +0100

    Quit tumbler after five minutes of inactivity.
    
    This is implemented via two new classes:
    
    TumblerLifecycleManager schedules a 300s timeout when tumblerd is
    started. When the timeout handler is executed, it emits a "shutdown"
    signal which is caught in main.c and asks the main loop to quit. The
    timeout is rescheduled whenever another component calls
    tumbler_lifecycle_manager_keep_alive() or when the timeout handler is
    called and one of the components is still busy processing requests from
    client applications.
    
    TumblerComponent is introduced as a new base class for the D-Bus service
    classes. Whenever a D-Bus method call is being processed, service
    objects increment the component use count by one and decrement it when
    the request is finished. They also call the keep alive method after a
    D-Bus method call is received to reschedule the timeout.
    
    A component use count of greather than 0 means that components are busy
    and the lifecycle manager needs to reschedule the shutdown timeout.

 NEWS                                 |    1 +
 tumbler/tumbler-error.h              |    3 +-
 tumblerd/Makefile.am                 |    6 +-
 tumblerd/main.c                      |   62 ++++++---
 tumblerd/tumbler-cache-service.c     |   59 +++++++-
 tumblerd/tumbler-cache-service.h     |   39 +++---
 tumblerd/tumbler-component.c         |  185 ++++++++++++++++++++++++
 tumblerd/tumbler-component.h         |   60 ++++++++
 tumblerd/tumbler-lifecycle-manager.c |  256 ++++++++++++++++++++++++++++++++++
 tumblerd/tumbler-lifecycle-manager.h |   49 +++++++
 tumblerd/tumbler-manager.c           |   21 ++-
 tumblerd/tumbler-manager.h           |   24 ++--
 tumblerd/tumbler-service.c           |   48 +++++--
 tumblerd/tumbler-service.h           |   44 +++---
 14 files changed, 764 insertions(+), 93 deletions(-)

diff --git a/NEWS b/NEWS
index 54164dd..032a7e9 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@
   specification where Cleanup() takes an array of base URIs instead
   of just one.
 - Get rid of the inherently broken GStrv type in function signatures.
+- Quit tumbler after at least 5 minutes of inactivity.
 
 0.1.20
 ======
diff --git a/tumbler/tumbler-error.h b/tumbler/tumbler-error.h
index c6a1573..63e8424 100644
--- a/tumbler/tumbler-error.h
+++ b/tumbler/tumbler-error.h
@@ -1,6 +1,6 @@
 /* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -47,6 +47,7 @@ typedef enum /*< enum >*/
   TUMBLER_ERROR_SAVE_FAILED,
   TUMBLER_ERROR_UNSUPPORTED_FLAVOR,
   TUMBLER_ERROR_NO_CONTENT,
+  TUMBLER_ERROR_SHUTTING_DOWN,
 } TumblerErrorEnum;
 
 G_END_DECLS
diff --git a/tumblerd/Makefile.am b/tumblerd/Makefile.am
index 26b61d6..0b26310 100644
--- a/tumblerd/Makefile.am
+++ b/tumblerd/Makefile.am
@@ -1,6 +1,6 @@
 # vi:set ts=8 sw=8 noet ai nocindent:
 #-
-# Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+# Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
 #
 # This program is free software; you can redistribute it and/or 
 # modify it under the terms of the GNU General Public License as
@@ -32,6 +32,10 @@ tumblerd_SOURCES =							\
 	main.c								\
 	tumbler-cache-service.c						\
 	tumbler-cache-service.h						\
+	tumbler-component.c						\
+	tumbler-component.h						\
+	tumbler-lifecycle-manager.c					\
+	tumbler-lifecycle-manager.h					\
 	tumbler-manager.c						\
 	tumbler-manager.h						\
 	tumbler-registry.c						\
diff --git a/tumblerd/main.c b/tumblerd/main.c
index 93ae340..f2de4f0 100644
--- a/tumblerd/main.c
+++ b/tumblerd/main.c
@@ -1,6 +1,6 @@
 /* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
  * This program is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU General Public License as
@@ -33,28 +33,43 @@
 #include <tumbler/tumbler.h>
 
 #include <tumblerd/tumbler-cache-service.h>
+#include <tumblerd/tumbler-lifecycle-manager.h>
 #include <tumblerd/tumbler-manager.h>
 #include <tumblerd/tumbler-registry.h>
 #include <tumblerd/tumbler-service.h>
 
 
 
+static void
+shutdown_tumbler (TumblerLifecycleManager *lifecycle_manager,
+                  GMainLoop               *main_loop)
+{
+  g_return_if_fail (TUMBLER_IS_LIFECYCLE_MANAGER (lifecycle_manager));
+  g_return_if_fail (main_loop != NULL);
+
+  /* exit the main loop */
+  g_main_loop_quit (main_loop);
+}
+
+
+
 int
 main (int    argc,
       char **argv)
 {
-  TumblerProviderFactory *provider_factory;
-  DBusGConnection        *connection;
-  TumblerRegistry        *registry;
-  TumblerManager         *manager;
-  TumblerService         *service;
-  TumblerCacheService    *cache_service;
-  GMainLoop              *main_loop;
-  GError                 *error = NULL;
-  GList                  *providers;
-  GList                  *thumbnailers;
-  GList                  *lp;
-  GList                  *tp;
+  TumblerLifecycleManager *lifecycle_manager;
+  TumblerProviderFactory  *provider_factory;
+  DBusGConnection         *connection;
+  TumblerRegistry         *registry;
+  TumblerManager          *manager;
+  TumblerService          *service;
+  TumblerCacheService     *cache_service;
+  GMainLoop               *main_loop;
+  GError                  *error = NULL;
+  GList                   *providers;
+  GList                   *thumbnailers;
+  GList                   *lp;
+  GList                   *tp;
 
   /* set the program name */
   g_set_prgname (G_LOG_DOMAIN);
@@ -81,8 +96,11 @@ main (int    argc,
       return EXIT_FAILURE;
     }
 
+  /* create the lifecycle manager */
+  lifecycle_manager = tumbler_lifecycle_manager_new ();
+
   /* create the thumbnail cache service */
-  cache_service = tumbler_cache_service_new (connection);
+  cache_service = tumbler_cache_service_new (connection, lifecycle_manager);
 
   /* try to start the service and exit if that fails */
   if (!tumbler_cache_service_start (cache_service, &error))
@@ -150,7 +168,7 @@ main (int    argc,
     }
 
   /* create the thumbnailer manager service */
-  manager = tumbler_manager_new (connection, registry);
+  manager = tumbler_manager_new (connection, lifecycle_manager, registry);
 
   /* try to start the service and exit if that fails */
   if (!tumbler_manager_start (manager, &error))
@@ -168,7 +186,7 @@ main (int    argc,
     }
 
   /* create the generic thumbnailer service */
-  service = tumbler_service_new (connection, registry);
+  service = tumbler_service_new (connection, lifecycle_manager, registry);
 
   /* try to start the service and exit if that fails */
   if (!tumbler_service_start (service, &error))
@@ -186,8 +204,17 @@ main (int    argc,
       return EXIT_FAILURE;
     }
 
-  /* create a new main loop and run it */
+  /* create a new main loop */
   main_loop = g_main_loop_new (NULL, FALSE);
+
+  /* quit the main loop when the lifecycle manager asks us to shut down */
+  g_signal_connect (lifecycle_manager, "shutdown", 
+                    G_CALLBACK (shutdown_tumbler), main_loop);
+
+  /* start the lifecycle manager */
+  tumbler_lifecycle_manager_start (lifecycle_manager);
+
+  /* enter the main loop, thereby making the tumbler service available */
   g_main_loop_run (main_loop);
 
   /* shut our services down and release all objects */
@@ -195,6 +222,7 @@ main (int    argc,
   g_object_unref (manager);
   g_object_unref (registry);
   g_object_unref (cache_service);
+  g_object_unref (lifecycle_manager);
 
   /* disconnect from the D-Bus session bus */
   dbus_g_connection_unref (connection);
diff --git a/tumblerd/tumbler-cache-service.c b/tumblerd/tumbler-cache-service.c
index dd74770..f13177c 100644
--- a/tumblerd/tumbler-cache-service.c
+++ b/tumblerd/tumbler-cache-service.c
@@ -32,6 +32,7 @@
 
 #include <tumbler/tumbler.h>
 
+#include <tumblerd/tumbler-component.h>
 #include <tumblerd/tumbler-cache-service.h>
 #include <tumblerd/tumbler-cache-service-dbus-bindings.h>
 #include <tumblerd/tumbler-utils.h>
@@ -77,12 +78,12 @@ static void tumbler_cache_service_cleanup_thread (gpointer      data,
 
 struct _TumblerCacheServiceClass
 {
-  GObjectClass __parent__;
+  TumblerComponentClass __parent__;
 };
 
 struct _TumblerCacheService
 {
-  GObject __parent__;
+  TumblerComponent __parent__;
 
   DBusGConnection *connection;
 
@@ -121,7 +122,7 @@ struct _CleanupRequest
 
 
 
-G_DEFINE_TYPE (TumblerCacheService, tumbler_cache_service, G_TYPE_OBJECT);
+G_DEFINE_TYPE (TumblerCacheService, tumbler_cache_service, TUMBLER_TYPE_COMPONENT);
 
 
 
@@ -264,6 +265,10 @@ tumbler_cache_service_move_thread (gpointer data,
   g_strfreev (request->to_uris);
   g_slice_free (MoveRequest, request);
 
+  /* allow the lifecycle manager to shut down tumbler again (unless
+   * other requests are still to be processed) */
+  tumbler_component_decrement_use_count (TUMBLER_COMPONENT (service));
+
   g_mutex_unlock (service->mutex);
 }
 
@@ -292,6 +297,10 @@ tumbler_cache_service_copy_thread (gpointer data,
   g_strfreev (request->to_uris);
   g_slice_free (CopyRequest, request);
 
+  /* allow the lifecycle manager to shut down tumbler again (unless
+   * other requests are still to be processed) */
+  tumbler_component_decrement_use_count (TUMBLER_COMPONENT (service));
+
   g_mutex_unlock (service->mutex);
 }
 
@@ -315,6 +324,10 @@ tumbler_cache_service_delete_thread (gpointer data,
   g_strfreev (request->uris);
   g_slice_free (DeleteRequest, request);
 
+  /* allow the lifecycle manager to shut down tumbler again (unless
+   * other requests are still to be processed) */
+  tumbler_component_decrement_use_count (TUMBLER_COMPONENT (service));
+
   g_mutex_unlock (service->mutex);
 }
 
@@ -342,15 +355,23 @@ tumbler_cache_service_cleanup_thread (gpointer data,
   g_strfreev (request->base_uris);
   g_slice_free (CleanupRequest, request);
 
+  /* allow the lifecycle manager to shut down tumbler again (unless
+   * other requests are still to be processed) */
+  tumbler_component_decrement_use_count (TUMBLER_COMPONENT (service));
+
   g_mutex_unlock (service->mutex);
 }
 
 
 
 TumblerCacheService *
-tumbler_cache_service_new (DBusGConnection *connection)
+tumbler_cache_service_new (DBusGConnection         *connection,
+                           TumblerLifecycleManager *lifecycle_manager)
 {
-  return g_object_new (TUMBLER_TYPE_CACHE_SERVICE, "connection", connection, NULL);
+  return g_object_new (TUMBLER_TYPE_CACHE_SERVICE, 
+                       "connection", connection, 
+                       "lifecycle-manager", lifecycle_manager,
+                       NULL);
 }
 
 
@@ -429,6 +450,10 @@ tumbler_cache_service_move (TumblerCacheService   *service,
   dbus_async_return_if_fail (to_uris != NULL, context);
   dbus_async_return_if_fail (g_strv_length ((gchar **)from_uris) == g_strv_length ((gchar **)to_uris), context);
 
+  /* prevent the lifecycle manager to shut tumbler down before the
+   * move request has been processed */
+  tumbler_component_increment_use_count (TUMBLER_COMPONENT (service));
+
   request = g_slice_new0 (MoveRequest);
   request->from_uris = g_strdupv ((gchar **)from_uris);
   request->to_uris = g_strdupv ((gchar **)to_uris);
@@ -436,6 +461,9 @@ tumbler_cache_service_move (TumblerCacheService   *service,
   g_thread_pool_push (service->move_pool, request, NULL);
 
   dbus_g_method_return (context);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -453,6 +481,10 @@ tumbler_cache_service_copy (TumblerCacheService   *service,
   dbus_async_return_if_fail (to_uris != NULL, context);
   dbus_async_return_if_fail (g_strv_length ((gchar **)from_uris) == g_strv_length ((gchar **)to_uris), context);
 
+  /* prevent the lifecycle manager to shut tumbler down before the
+   * copy request has been processed */
+  tumbler_component_increment_use_count (TUMBLER_COMPONENT (service));
+
   request = g_slice_new0 (CopyRequest);
   request->from_uris = g_strdupv ((gchar **)from_uris);
   request->to_uris = g_strdupv ((gchar **)to_uris);
@@ -460,6 +492,9 @@ tumbler_cache_service_copy (TumblerCacheService   *service,
   g_thread_pool_push (service->copy_pool, request, NULL);
 
   dbus_g_method_return (context);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -474,12 +509,19 @@ tumbler_cache_service_delete (TumblerCacheService   *service,
   dbus_async_return_if_fail (TUMBLER_IS_CACHE_SERVICE (service), context);
   dbus_async_return_if_fail (uris != NULL, context);
 
+  /* prevent the lifecycle manager to shut tumbler down before the
+   * delete request has been processed */
+  tumbler_component_increment_use_count (TUMBLER_COMPONENT (service));
+
   request = g_slice_new0 (DeleteRequest);
   request->uris = g_strdupv ((gchar **)uris);
 
   g_thread_pool_push (service->delete_pool, request, NULL);
 
   dbus_g_method_return (context);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -494,6 +536,10 @@ tumbler_cache_service_cleanup (TumblerCacheService   *service,
 
   dbus_async_return_if_fail (TUMBLER_IS_CACHE_SERVICE (service), context);
 
+  /* prevent the lifecycle manager to shut tumbler down before the
+   * cleanup request has been processed */
+  tumbler_component_increment_use_count (TUMBLER_COMPONENT (service));
+
   request = g_slice_new0 (CleanupRequest);
   request->base_uris = g_strdupv ((gchar **)base_uris);
   request->since = since;
@@ -501,4 +547,7 @@ tumbler_cache_service_cleanup (TumblerCacheService   *service,
   g_thread_pool_push (service->cleanup_pool, request, NULL);
 
   dbus_g_method_return (context);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
diff --git a/tumblerd/tumbler-cache-service.h b/tumblerd/tumbler-cache-service.h
index c325263..476781f 100644
--- a/tumblerd/tumbler-cache-service.h
+++ b/tumblerd/tumbler-cache-service.h
@@ -25,6 +25,8 @@
 
 #include <dbus/dbus-glib.h>
 
+#include <tumblerd/tumbler-lifecycle-manager.h>
+
 G_BEGIN_DECLS;
 
 #define TUMBLER_TYPE_CACHE_SERVICE            (tumbler_cache_service_get_type ())
@@ -39,24 +41,25 @@ typedef struct _TumblerCacheService      TumblerCacheService;
 
 GType                tumbler_cache_service_get_type   (void) G_GNUC_CONST;
 
-TumblerCacheService *tumbler_cache_service_new     (DBusGConnection       *connection) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-gboolean             tumbler_cache_service_start   (TumblerCacheService   *service,
-                                                    GError               **error);
-void                 tumbler_cache_service_move    (TumblerCacheService   *service,
-                                                    const gchar *const    *from_uris,
-                                                    const gchar *const    *to_uris,
-                                                    DBusGMethodInvocation *context);
-void                 tumbler_cache_service_copy    (TumblerCacheService   *service,
-                                                    const gchar *const    *from_uris,
-                                                    const gchar *const    *to_uris,
-                                                    DBusGMethodInvocation *context);
-void                 tumbler_cache_service_delete  (TumblerCacheService   *service,
-                                                    const gchar *const    *uris,
-                                                    DBusGMethodInvocation *context);
-void                 tumbler_cache_service_cleanup (TumblerCacheService   *service,
-                                                    const gchar *const    *uri_prefix,
-                                                    guint32                since,
-                                                    DBusGMethodInvocation *context);
+TumblerCacheService *tumbler_cache_service_new     (DBusGConnection         *connection,
+                                                    TumblerLifecycleManager *lifecycle_manager) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+gboolean             tumbler_cache_service_start   (TumblerCacheService     *service,
+                                                    GError                 **error);
+void                 tumbler_cache_service_move    (TumblerCacheService     *service,
+                                                    const gchar *const      *from_uris,
+                                                    const gchar *const      *to_uris,
+                                                    DBusGMethodInvocation   *context);
+void                 tumbler_cache_service_copy    (TumblerCacheService     *service,
+                                                    const gchar *const      *from_uris,
+                                                    const gchar *const      *to_uris,
+                                                    DBusGMethodInvocation   *context);
+void                 tumbler_cache_service_delete  (TumblerCacheService     *service,
+                                                    const gchar *const      *uris,
+                                                    DBusGMethodInvocation   *context);
+void                 tumbler_cache_service_cleanup (TumblerCacheService     *service,
+                                                    const gchar *const      *uri_prefix,
+                                                    guint32                  since,
+                                                    DBusGMethodInvocation   *context);
 
 
 G_END_DECLS;
diff --git a/tumblerd/tumbler-component.c b/tumblerd/tumbler-component.c
new file mode 100644
index 0000000..fdb0062
--- /dev/null
+++ b/tumblerd/tumbler-component.c
@@ -0,0 +1,185 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2011 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write to the Free 
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <tumblerd/tumbler-component.h>
+#include <tumblerd/tumbler-lifecycle-manager.h>
+
+
+
+#define TUMBLER_COMPONENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TUMBLER_TYPE_COMPONENT, TumblerComponentPrivate))
+
+
+
+/* property identifiers */
+enum
+{
+  PROP_0,
+  PROP_LIFECYCLE_MANAGER,
+};
+
+
+
+static void tumbler_component_finalize     (GObject      *object);
+static void tumbler_component_get_property (GObject      *object,
+                                            guint         prop_id,
+                                            GValue       *value,
+                                            GParamSpec   *pspec);
+static void tumbler_component_set_property (GObject      *object,
+                                            guint         prop_id,
+                                            const GValue *value,
+                                            GParamSpec   *pspec);
+
+
+
+struct _TumblerComponentPrivate
+{
+  TumblerLifecycleManager *lifecycle_manager;
+};
+
+
+
+G_DEFINE_TYPE (TumblerComponent, tumbler_component, G_TYPE_OBJECT)
+
+
+
+static void
+tumbler_component_class_init (TumblerComponentClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (TumblerComponentPrivate));
+
+  /* Determine the parent type class */
+  tumbler_component_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = tumbler_component_finalize; 
+  gobject_class->get_property = tumbler_component_get_property;
+  gobject_class->set_property = tumbler_component_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_LIFECYCLE_MANAGER,
+                                   g_param_spec_object ("lifecycle-manager",
+                                                        "lifecycle-manager",
+                                                        "lifecycle-manager",
+                                                        TUMBLER_TYPE_LIFECYCLE_MANAGER,
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT));
+}
+
+
+
+static void
+tumbler_component_init (TumblerComponent *component)
+{
+  component->priv = TUMBLER_COMPONENT_GET_PRIVATE (component);
+}
+
+
+
+static void
+tumbler_component_finalize (GObject *object)
+{
+  TumblerComponent *component = TUMBLER_COMPONENT (object);
+
+  g_object_unref (component->priv->lifecycle_manager);
+
+  (*G_OBJECT_CLASS (tumbler_component_parent_class)->finalize) (object);
+}
+
+
+
+static void
+tumbler_component_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  TumblerComponent *component = TUMBLER_COMPONENT (object);
+
+  switch (prop_id)
+    {
+    case PROP_LIFECYCLE_MANAGER:
+      g_value_set_object (value, component->priv->lifecycle_manager);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+tumbler_component_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  TumblerComponent *component = TUMBLER_COMPONENT (object);
+
+  switch (prop_id)
+    {
+    case PROP_LIFECYCLE_MANAGER:
+      component->priv->lifecycle_manager = g_value_dup_object(value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+gboolean
+tumbler_component_keep_alive (TumblerComponent *component,
+                              GError          **error)
+{
+  g_return_val_if_fail (TUMBLER_IS_COMPONENT (component), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  return tumbler_lifecycle_manager_keep_alive (component->priv->lifecycle_manager,
+                                               error);
+}
+
+
+
+void
+tumbler_component_increment_use_count (TumblerComponent *component)
+{
+  g_return_if_fail (TUMBLER_IS_COMPONENT (component));
+  tumbler_lifecycle_manager_increment_use_count (component->priv->lifecycle_manager);
+}
+
+
+
+void
+tumbler_component_decrement_use_count (TumblerComponent *component)
+{
+  g_return_if_fail (TUMBLER_IS_COMPONENT (component));
+  tumbler_lifecycle_manager_decrement_use_count (component->priv->lifecycle_manager);
+}
diff --git a/tumblerd/tumbler-component.h b/tumblerd/tumbler-component.h
new file mode 100644
index 0000000..2dc3dfa
--- /dev/null
+++ b/tumblerd/tumbler-component.h
@@ -0,0 +1,60 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2011 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write to the Free 
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __TUMBLER_COMPONENT_H__
+#define __TUMBLER_COMPONENT_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define TUMBLER_TYPE_COMPONENT            (tumbler_component_get_type ())
+#define TUMBLER_COMPONENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TUMBLER_TYPE_COMPONENT, TumblerComponent))
+#define TUMBLER_COMPONENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TUMBLER_TYPE_COMPONENT, TumblerComponentClass))
+#define TUMBLER_IS_COMPONENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TUMBLER_TYPE_COMPONENT))
+#define TUMBLER_IS_COMPONENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TUMBLER_TYPE_COMPONENT)
+#define TUMBLER_COMPONENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TUMBLER_TYPE_COMPONENT, TumblerComponentClass))
+
+typedef struct _TumblerComponentPrivate TumblerComponentPrivate;
+typedef struct _TumblerComponentClass   TumblerComponentClass;
+typedef struct _TumblerComponent        TumblerComponent;
+
+GType    tumbler_component_get_type            (void) G_GNUC_CONST;
+
+gboolean tumbler_component_keep_alive          (TumblerComponent *component,
+                                                GError          **error);
+void     tumbler_component_increment_use_count (TumblerComponent *component);
+void     tumbler_component_decrement_use_count (TumblerComponent *component);
+
+struct _TumblerComponentClass
+{
+  GObjectClass __parent__;
+};
+
+struct _TumblerComponent
+{
+  GObject                  __parent__;
+
+  TumblerComponentPrivate *priv;
+};
+
+G_END_DECLS
+
+#endif /* !__TUMBLER_COMPONENT_H__ */
diff --git a/tumblerd/tumbler-lifecycle-manager.c b/tumblerd/tumbler-lifecycle-manager.c
new file mode 100644
index 0000000..00a381c
--- /dev/null
+++ b/tumblerd/tumbler-lifecycle-manager.c
@@ -0,0 +1,256 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2011 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write to the Free 
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include <tumbler/tumbler.h>
+
+#include <tumblerd/tumbler-lifecycle-manager.h>
+
+
+
+#define SHUTDOWN_TIMEOUT_SECONDS 300
+
+
+
+/* signal identifiers */
+enum
+{
+  SIGNAL_SHUTDOWN,
+  LAST_SIGNAL,
+};
+
+
+
+static void tumbler_lifecycle_manager_finalize (GObject *object);
+
+
+
+struct _TumblerLifecycleManagerClass
+{
+  GObjectClass __parent__;
+};
+
+struct _TumblerLifecycleManager
+{
+  GObject __parent__;
+
+  GMutex *lock;
+
+  guint   timeout_id;
+  guint   component_use_count;
+  guint   shutdown_emitted : 1;
+};
+
+
+
+static guint lifecycle_manager_signals[LAST_SIGNAL];
+
+
+
+G_DEFINE_TYPE (TumblerLifecycleManager, tumbler_lifecycle_manager, G_TYPE_OBJECT)
+
+
+
+static void
+tumbler_lifecycle_manager_class_init (TumblerLifecycleManagerClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  /* Determine the parent type class */
+  tumbler_lifecycle_manager_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = tumbler_lifecycle_manager_finalize; 
+
+  lifecycle_manager_signals[SIGNAL_SHUTDOWN] =
+    g_signal_new ("shutdown",
+                  TUMBLER_TYPE_LIFECYCLE_MANAGER,
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL,
+                  NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE,
+                  0);
+}
+
+
+
+static void
+tumbler_lifecycle_manager_init (TumblerLifecycleManager *manager)
+{
+  manager->lock = g_mutex_new ();
+  manager->timeout_id = 0;
+  manager->component_use_count = 0;
+  manager->shutdown_emitted = FALSE;
+}
+
+
+
+static void
+tumbler_lifecycle_manager_finalize (GObject *object)
+{
+  TumblerLifecycleManager *manager = TUMBLER_LIFECYCLE_MANAGER (object);
+
+  g_mutex_free (manager->lock);
+
+  (*G_OBJECT_CLASS (tumbler_lifecycle_manager_parent_class)->finalize) (object);
+}
+
+
+
+static gboolean
+tumbler_lifecycle_manager_timeout (TumblerLifecycleManager *manager)
+{
+  g_return_val_if_fail (TUMBLER_IS_LIFECYCLE_MANAGER (manager), FALSE);
+
+  g_mutex_lock (manager->lock);
+
+  /* reschedule the timeout if one of the components is still in use */
+  if (manager->component_use_count > 0)
+    {
+      g_mutex_unlock (manager->lock);
+      return TRUE;
+    }
+
+  /* reset the timeout id */
+  manager->timeout_id = 0;
+
+  /* emit the shutdown signal */
+  g_signal_emit (manager, lifecycle_manager_signals[SIGNAL_SHUTDOWN], 0);
+
+  /* set the shutdown emitted flag to force other threads not to 
+   * reschedule the timeout */
+  manager->shutdown_emitted = TRUE;
+
+  g_mutex_unlock (manager->lock);
+
+  return FALSE;
+}
+
+
+
+TumblerLifecycleManager *
+tumbler_lifecycle_manager_new (void)
+{
+  return g_object_new (TUMBLER_TYPE_LIFECYCLE_MANAGER, NULL);
+}
+
+
+
+void
+tumbler_lifecycle_manager_start (TumblerLifecycleManager *manager)
+{
+  g_return_if_fail (TUMBLER_IS_LIFECYCLE_MANAGER (manager));
+
+  g_mutex_lock (manager->lock);
+
+  /* ignore if there already is a timeout scheduled */
+  if (manager->timeout_id > 0)
+    {
+      g_mutex_unlock (manager->lock);
+      return;
+    }
+
+  manager->timeout_id = 
+    g_timeout_add_seconds (SHUTDOWN_TIMEOUT_SECONDS, 
+                           (GSourceFunc) tumbler_lifecycle_manager_timeout, 
+                           manager);
+
+  g_mutex_unlock (manager->lock);
+}
+
+
+
+gboolean
+tumbler_lifecycle_manager_keep_alive (TumblerLifecycleManager *manager,
+                                      GError                 **error)
+{
+  g_return_val_if_fail (TUMBLER_IS_LIFECYCLE_MANAGER (manager), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  g_mutex_lock (manager->lock);
+
+  /* if the shutdown signal has been emitted, there's nothing 
+   * we can do to prevent a shutdown anymore */
+  if (manager->shutdown_emitted)
+    {
+      g_mutex_unlock (manager->lock);
+
+      if (error != NULL)
+        {
+          g_set_error (error, TUMBLER_ERROR, TUMBLER_ERROR_SHUTTING_DOWN,
+                       "%s", _("The thumbnailer service is shutting down"));
+        }
+      return FALSE;
+    }
+
+  /* if there is an existing timeout, drop it (we are going to 
+   * replace it with a new one) */
+  if (manager->timeout_id > 0)
+    g_source_remove (manager->timeout_id);
+
+  /* reschedule the shutdown timeout */
+  manager->timeout_id = 
+    g_timeout_add_seconds (SHUTDOWN_TIMEOUT_SECONDS, 
+                           (GSourceFunc) tumbler_lifecycle_manager_timeout, 
+                           manager);
+
+  g_mutex_unlock (manager->lock);
+
+  return TRUE;
+}
+
+
+
+void
+tumbler_lifecycle_manager_increment_use_count (TumblerLifecycleManager *manager)
+{
+  g_return_if_fail (TUMBLER_IS_LIFECYCLE_MANAGER (manager));
+
+  g_mutex_lock (manager->lock);
+
+  manager->component_use_count += 1;
+  
+  g_mutex_unlock (manager->lock);
+}
+
+
+
+void
+tumbler_lifecycle_manager_decrement_use_count (TumblerLifecycleManager *manager)
+{
+  g_return_if_fail (TUMBLER_IS_LIFECYCLE_MANAGER (manager));
+
+  g_mutex_lock (manager->lock);
+  
+  /* decrement the use count, make sure not to drop below zero */
+  if (manager->component_use_count > 0)
+    manager->component_use_count -= 1;
+  
+  g_mutex_unlock (manager->lock);
+}
diff --git a/tumblerd/tumbler-lifecycle-manager.h b/tumblerd/tumbler-lifecycle-manager.h
new file mode 100644
index 0000000..1f0c958
--- /dev/null
+++ b/tumblerd/tumbler-lifecycle-manager.h
@@ -0,0 +1,49 @@
+/* vi:set et ai sw=2 sts=2 ts=2: */
+/*-
+ * Copyright (c) 2011 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of 
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write to the Free 
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __TUMBLER_LIFECYCLE_MANAGER_H__
+#define __TUMBLER_LIFECYCLE_MANAGER_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define TUMBLER_TYPE_LIFECYCLE_MANAGER            (tumbler_lifecycle_manager_get_type ())
+#define TUMBLER_LIFECYCLE_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TUMBLER_TYPE_LIFECYCLE_MANAGER, TumblerLifecycleManager))
+#define TUMBLER_LIFECYCLE_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TUMBLER_TYPE_LIFECYCLE_MANAGER, TumblerLifecycleManagerClass))
+#define TUMBLER_IS_LIFECYCLE_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TUMBLER_TYPE_LIFECYCLE_MANAGER))
+#define TUMBLER_IS_LIFECYCLE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TUMBLER_TYPE_LIFECYCLE_MANAGER)
+#define TUMBLER_LIFECYCLE_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), TUMBLER_TYPE_LIFECYCLE_MANAGER, TumblerLifecycleManagerClass))
+
+typedef struct _TumblerLifecycleManagerClass   TumblerLifecycleManagerClass;
+typedef struct _TumblerLifecycleManager        TumblerLifecycleManager;
+
+GType                    tumbler_lifecycle_manager_get_type            (void) G_GNUC_CONST;
+
+TumblerLifecycleManager *tumbler_lifecycle_manager_new                 (void) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+void                     tumbler_lifecycle_manager_start               (TumblerLifecycleManager *manager);
+gboolean                 tumbler_lifecycle_manager_keep_alive          (TumblerLifecycleManager *manager,
+                                                                        GError                 **error);
+void                     tumbler_lifecycle_manager_increment_use_count (TumblerLifecycleManager *manager);
+void                     tumbler_lifecycle_manager_decrement_use_count (TumblerLifecycleManager *manager);
+
+G_END_DECLS
+
+#endif /* !__TUMBLER_LIFECYCLE_MANAGER_H__ */
diff --git a/tumblerd/tumbler-manager.c b/tumblerd/tumbler-manager.c
index 4485031..73e6778 100644
--- a/tumblerd/tumbler-manager.c
+++ b/tumblerd/tumbler-manager.c
@@ -40,6 +40,7 @@
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
+#include <tumblerd/tumbler-component.h>
 #include <tumblerd/tumbler-manager.h>
 #include <tumblerd/tumbler-manager-dbus-bindings.h>
 #include <tumblerd/tumbler-specialized-thumbnailer.h>
@@ -97,12 +98,12 @@ static void             dump_thumbnailers                 (TumblerManager   *man
 
 struct _TumblerManagerClass
 {
-  GObjectClass __parent__;
+  TumblerComponentClass __parent__;
 };
 
 struct _TumblerManager
 {
-  GObject __parent__;
+  TumblerComponent __parent__;
 
   DBusGConnection *connection;
   TumblerRegistry *registry;
@@ -147,7 +148,7 @@ struct _ThumbnailerInfo
 
 
 
-G_DEFINE_TYPE (TumblerManager, tumbler_manager, G_TYPE_OBJECT);
+G_DEFINE_TYPE (TumblerManager, tumbler_manager, TUMBLER_TYPE_COMPONENT);
 
 
 
@@ -1800,11 +1801,15 @@ dump_thumbnailers (TumblerManager *manager)
 
 
 TumblerManager *
-tumbler_manager_new (DBusGConnection *connection,
-                     TumblerRegistry *registry)
+tumbler_manager_new (DBusGConnection         *connection,
+                     TumblerLifecycleManager *lifecycle_manager,
+                     TumblerRegistry         *registry)
 {
-  return g_object_new (TUMBLER_TYPE_MANAGER, "connection", connection, 
-                       "registry", registry, NULL);
+  return g_object_new (TUMBLER_TYPE_MANAGER, 
+                       "connection", connection, 
+                       "registry", registry, 
+                       "lifecycle-manager", lifecycle_manager, 
+                       NULL);
 }
 
 
@@ -1869,7 +1874,7 @@ tumbler_manager_start (TumblerManager *manager,
   /* load thumbnailers installed into the system permanently */
   tumbler_manager_load (manager);
 
-  /* this is how I roll */
+  /* done initializing and loading all permanent thumbnailers */
   return TRUE;
 }
 
diff --git a/tumblerd/tumbler-manager.h b/tumblerd/tumbler-manager.h
index 0f79f6e..cc11bd1 100644
--- a/tumblerd/tumbler-manager.h
+++ b/tumblerd/tumbler-manager.h
@@ -1,6 +1,6 @@
 /* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
  * This program is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU General Public License as
@@ -23,6 +23,7 @@
 
 #include <dbus/dbus-glib.h>
 
+#include <tumblerd/tumbler-lifecycle-manager.h>
 #include <tumblerd/tumbler-registry.h>
 
 G_BEGIN_DECLS;
@@ -39,16 +40,17 @@ typedef struct _TumblerManager      TumblerManager;
 
 GType           tumbler_manager_get_type      (void) G_GNUC_CONST;
 
-TumblerManager *tumbler_manager_new           (DBusGConnection       *connection,
-                                               TumblerRegistry       *registry) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-gboolean        tumbler_manager_start         (TumblerManager        *manager,
-                                               GError               **error);
-void            tumbler_manager_register      (TumblerManager        *manager, 
-                                               const gchar *const    *uri_schemes, 
-                                               const gchar *const    *mime_types, 
-                                               DBusGMethodInvocation *context);
-void            tumbler_manager_get_supported (TumblerManager        *manager, 
-                                               DBusGMethodInvocation *context);
+TumblerManager *tumbler_manager_new           (DBusGConnection         *connection,
+                                               TumblerLifecycleManager *lifecycle_manager,
+                                               TumblerRegistry         *registry) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+gboolean        tumbler_manager_start         (TumblerManager          *manager,
+                                               GError                 **error);
+void            tumbler_manager_register      (TumblerManager          *manager, 
+                                               const gchar *const      *uri_schemes, 
+                                               const gchar *const      *mime_types, 
+                                               DBusGMethodInvocation   *context);
+void            tumbler_manager_get_supported (TumblerManager          *manager, 
+                                               DBusGMethodInvocation   *context);
 
 G_END_DECLS;
 
diff --git a/tumblerd/tumbler-service.c b/tumblerd/tumbler-service.c
index 6cf09a3..d00a477 100644
--- a/tumblerd/tumbler-service.c
+++ b/tumblerd/tumbler-service.c
@@ -34,6 +34,7 @@
 
 #include <tumbler/tumbler.h>
 
+#include <tumblerd/tumbler-component.h>
 #include <tumblerd/tumbler-scheduler.h>
 #include <tumblerd/tumbler-service.h>
 #include <tumblerd/tumbler-service-dbus-bindings.h>
@@ -112,12 +113,12 @@ static void scheduler_idle_info_free           (SchedulerIdleInfo  *info);
 
 struct _TumblerServiceClass
 {
-  GObjectClass __parent__;
+  TumblerComponentClass __parent__;
 };
 
 struct _TumblerService
 {
-  GObject __parent__;
+  TumblerComponent  __parent__;
 
   DBusGConnection  *connection;
   TumblerRegistry  *registry;
@@ -144,7 +145,7 @@ static guint tumbler_service_signals[LAST_SIGNAL];
 
 
 
-G_DEFINE_TYPE (TumblerService, tumbler_service, G_TYPE_OBJECT);
+G_DEFINE_TYPE (TumblerService, tumbler_service, TUMBLER_TYPE_COMPONENT);
 
 
 
@@ -491,6 +492,10 @@ tumbler_service_finished_idle (gpointer user_data)
   /* free the allocated D-Bus message */
   dbus_message_unref (message);
 
+  /* allow the lifecycle manager to shut down the service again (unless there
+   * are other requests still being processed) */
+  tumbler_component_decrement_use_count (TUMBLER_COMPONENT (info->service));
+
   scheduler_idle_info_free (info);
 
   return FALSE;
@@ -703,11 +708,15 @@ scheduler_idle_info_free (SchedulerIdleInfo *info)
 
 
 TumblerService *
-tumbler_service_new (DBusGConnection *connection,
-                     TumblerRegistry *registry)
+tumbler_service_new (DBusGConnection         *connection,
+                     TumblerLifecycleManager *lifecycle_manager,
+                     TumblerRegistry         *registry)
 {
-  return g_object_new (TUMBLER_TYPE_SERVICE, "connection", connection, 
-                       "registry", registry, NULL);
+  return g_object_new (TUMBLER_TYPE_SERVICE, 
+                       "connection", connection, 
+                       "lifecycle-manager", lifecycle_manager,
+                       "registry", registry, 
+                       NULL);
 }
 
 
@@ -797,18 +806,20 @@ tumbler_service_queue (TumblerService        *service,
   dbus_async_return_if_fail (uris != NULL, context);
   dbus_async_return_if_fail (mime_hints != NULL, context);
 
+  g_mutex_lock (service->mutex);
+
+  /* prevent the lifecycle manager to shut down the service as long
+   * as the request is still being processed */
+  tumbler_component_increment_use_count (TUMBLER_COMPONENT (service));
+
   /* if the scheduler is not defined, fall back to "default" */
   if (scheduler_name == NULL || *scheduler_name == '\0')
     scheduler_name = "default";
 
-  g_mutex_lock (service->mutex);
-
   cache = tumbler_cache_get_default ();
   flavor = tumbler_cache_get_flavor (cache, flavor_name);
   g_object_unref (cache);
 
-  g_assert (TUMBLER_IS_CACHE (cache));
-
   infos = tumbler_file_info_array_new_with_flavor (uris, mime_hints, flavor,
                                                    &length);
 
@@ -887,6 +898,9 @@ tumbler_service_queue (TumblerService        *service,
   g_mutex_unlock (service->mutex);
 
   dbus_g_method_return (context, handle);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -916,6 +930,9 @@ tumbler_service_dequeue (TumblerService        *service,
   g_mutex_unlock (service->mutex);
 
   dbus_g_method_return (context);
+
+  /* keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -938,6 +955,9 @@ tumbler_service_get_supported (TumblerService        *service,
 
   /* return the arrays to the caller */
   dbus_g_method_return (context, uri_schemes, mime_types);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -981,6 +1001,9 @@ tumbler_service_get_flavors (TumblerService        *service,
 
       g_free (flavor_strings);
     }
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
 
 
@@ -1019,4 +1042,7 @@ tumbler_service_get_schedulers (TumblerService        *service,
 
   /* free the array */
   g_strfreev (supported_schedulers);
+
+  /* try to keep tumbler alive */
+  tumbler_component_keep_alive (TUMBLER_COMPONENT (service), NULL);
 }
diff --git a/tumblerd/tumbler-service.h b/tumblerd/tumbler-service.h
index e4650ea..d2d4bed 100644
--- a/tumblerd/tumbler-service.h
+++ b/tumblerd/tumbler-service.h
@@ -1,6 +1,6 @@
 /* vi:set et ai sw=2 sts=2 ts=2: */
 /*-
- * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009-2011 Jannis Pohlmann <jannis at xfce.org>
  *
  * This program is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU General Public License as
@@ -23,6 +23,7 @@
 
 #include <dbus/dbus-glib.h>
 
+#include <tumblerd/tumbler-lifecycle-manager.h>
 #include <tumblerd/tumbler-registry.h>
 
 G_BEGIN_DECLS;
@@ -39,26 +40,27 @@ typedef struct _TumblerService      TumblerService;
 
 GType           tumbler_service_get_type (void) G_GNUC_CONST;
 
-TumblerService *tumbler_service_new            (DBusGConnection       *connection,
-                                                TumblerRegistry       *registry) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-gboolean        tumbler_service_start          (TumblerService        *service,
-                                                GError               **error);
-void            tumbler_service_queue          (TumblerService        *service,
-                                                const gchar *const    *uris,
-                                                const gchar *const    *mime_hints,
-                                                const gchar           *flavor_name,
-                                                const gchar           *scheduler_name,
-                                                guint                  handle_to_dequeue,
-                                                DBusGMethodInvocation *context);
-void            tumbler_service_dequeue        (TumblerService         *service,
-                                                guint                   handle,
-                                                DBusGMethodInvocation  *context);
-void            tumbler_service_get_schedulers (TumblerService        *service,
-                                                DBusGMethodInvocation *context);
-void            tumbler_service_get_supported  (TumblerService        *service,
-                                                DBusGMethodInvocation *context);
-void            tumbler_service_get_flavors    (TumblerService        *service,
-                                                DBusGMethodInvocation *context);
+TumblerService *tumbler_service_new            (DBusGConnection         *connection,
+                                                TumblerLifecycleManager *lifecycle_manager,
+                                                TumblerRegistry         *registry) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+gboolean        tumbler_service_start          (TumblerService          *service,
+                                                GError                 **error);
+void            tumbler_service_queue          (TumblerService          *service,
+                                                const gchar *const      *uris,
+                                                const gchar *const      *mime_hints,
+                                                const gchar             *flavor_name,
+                                                const gchar             *scheduler_name,
+                                                guint                    handle_to_dequeue,
+                                                DBusGMethodInvocation   *context);
+void            tumbler_service_dequeue        (TumblerService           *service,
+                                                guint                     handle,
+                                                DBusGMethodInvocation    *context);
+void            tumbler_service_get_schedulers (TumblerService          *service,
+                                                DBusGMethodInvocation   *context);
+void            tumbler_service_get_supported  (TumblerService          *service,
+                                                DBusGMethodInvocation   *context);
+void            tumbler_service_get_flavors    (TumblerService          *service,
+                                                DBusGMethodInvocation   *context);
 
 G_END_DECLS;
 



More information about the Xfce4-commits mailing list