? compile
? gnome-vfs-zip
? imported/fnmatch/Makefile
? imported/fnmatch/Makefile.in
? imported/neon/Makefile
? imported/neon/Makefile.in
? libgnomevfs/.gnome-vfs-job-queue.c.swp
? libgnomevfs/.gnome-vfs-job-queue.h.swp
? libgnomevfs/.gnome-vfs-job-slave.c.swp
? test/.test-queue.c.swp
? test/test-parse-ls-lga
Index: libgnomevfs/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/Makefile.am,v
retrieving revision 1.143
diff -u -p -r1.143 Makefile.am
--- libgnomevfs/Makefile.am	22 Nov 2005 14:34:09 -0000	1.143
+++ libgnomevfs/Makefile.am	2 Dec 2005 17:18:11 -0000
@@ -158,7 +158,6 @@ noinst_HEADERS =				\
 	gnome-vfs-hal-mounts.h			\
 	gnome-vfs-iso9660.h			\
 	gnome-vfs-job-queue.h			\
-	gnome-vfs-job-slave.h			\
 	gnome-vfs-job.h				\
 	gnome-vfs-mime-magic.h			\
 	gnome-vfs-mime-private.h		\
@@ -169,7 +168,6 @@ noinst_HEADERS =				\
 	gnome-vfs-private-utils.h		\
 	gnome-vfs-private.h			\
 	gnome-vfs-ssl-private.h			\
-	gnome-vfs-thread-pool.h			\
 	gnome-vfs-unix-mounts.h 		\
 	gnome-vfs-volume-monitor-client.h	\
 	gnome-vfs-volume-monitor-daemon.h	\
@@ -284,7 +282,6 @@ libgnomevfs_2_la_SOURCES =			\
 	gnome-vfs-inet-connection.c		\
 	gnome-vfs-init.c			\
 	gnome-vfs-job-queue.c			\
-	gnome-vfs-job-slave.c			\
 	gnome-vfs-job.c				\
 	gnome-vfs-method.c			\
 	gnome-vfs-mime-handlers.c		\
@@ -310,7 +307,6 @@ libgnomevfs_2_la_SOURCES =			\
 	gnome-vfs-socket-buffer.c		\
 	gnome-vfs-socket.c			\
 	gnome-vfs-ssl.c				\
-	gnome-vfs-thread-pool.c			\
 	gnome-vfs-transform.c			\
 	gnome-vfs-uri.c				\
 	gnome-vfs-utils.c			\
Index: libgnomevfs/gnome-vfs-init.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-init.c,v
retrieving revision 1.38
diff -u -p -r1.38 gnome-vfs-init.c
--- libgnomevfs/gnome-vfs-init.c	14 Nov 2005 11:41:13 -0000	1.38
+++ libgnomevfs/gnome-vfs-init.c	2 Dec 2005 17:18:11 -0000
@@ -34,7 +34,6 @@
 #include "gnome-vfs-private-utils.h"
 
 #include "gnome-vfs-async-job-map.h"
-#include "gnome-vfs-thread-pool.h"
 #include "gnome-vfs-job-queue.h"
 #include "gnome-vfs-volume-monitor-private.h"
 
@@ -46,7 +45,6 @@
 #include <glib/gi18n-lib.h>
 #include <glib/gtypes.h>
 #include <glib/gstdio.h>
-#include <libgnomevfs/gnome-vfs-job-slave.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -89,7 +87,6 @@ gnome_vfs_thread_init (void)
 	_gnome_vfs_module_callback_private_init ();
 	
 	_gnome_vfs_async_job_map_init ();
-	_gnome_vfs_thread_pool_init ();
 	_gnome_vfs_job_queue_init ();
 }
 
@@ -182,7 +179,6 @@ gnome_vfs_initialized (void)
 void
 gnome_vfs_shutdown (void)
 {
-	_gnome_vfs_thread_backend_shutdown ();
 	gnome_vfs_mime_shutdown ();
 #ifndef G_OS_WIN32
 	_gnome_vfs_volume_monitor_shutdown ();
Index: libgnomevfs/gnome-vfs-job-queue.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-job-queue.c,v
retrieving revision 1.8
diff -u -p -r1.8 gnome-vfs-job-queue.c
--- libgnomevfs/gnome-vfs-job-queue.c	14 Nov 2005 11:41:13 -0000	1.8
+++ libgnomevfs/gnome-vfs-job-queue.c	2 Dec 2005 17:18:11 -0000
@@ -1,9 +1,8 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /* gnome-vfs-job-queue.c - Job queue for asynchronous GnomeVFSJobs
-   (version for POSIX threads).
-
-   Copyright (C) 2001 Free Software Foundation
-
+   
+   Copyright (C) 2005 Christian Kellner
+   
    The Gnome Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
    published by the Free Software Foundation; either version 2 of the
@@ -19,307 +18,112 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
 
-   Author: László Péter <laca@ireland.sun.com> */
+   Author: Christian Kellner <gicmo@gnome.org>
+*/
 
 #include <config.h>
 #include "gnome-vfs-job-queue.h"
-#include "gnome-vfs-job-slave.h"
+#include "gnome-vfs-async-job-map.h"
 #include <libgnomevfs/gnome-vfs-job-limit.h>
 
-#include <glib/gtree.h>
-#include <unistd.h>
-
-#undef QUEUE_DEBUG
-
-#ifdef QUEUE_DEBUG
-#define Q_DEBUG(x) g_print x
-#else
-#define Q_DEBUG(x)
-#endif
-
-/* See the comment at job_can_start () for 
-   an explanation of the following macros */
 #ifndef DEFAULT_THREAD_COUNT_LIMIT
 #define DEFAULT_THREAD_COUNT_LIMIT 10
 #endif
 
-#define LIMIT_FUNCTION_LOWER_BOUND 2 /* must NOT be more than DEFAULT_THREAD_COUNT_LIMIT */
-#define LIMIT_FUNCTION_SPEED 7       /* must be more than 0 */
-
-#if LIMIT_FUNCTION_LOWER_BOUND > DEFAULT_THREAD_COUNT_LIMIT
-#error LIMIT_FUNCTION_LOWER_BOUND must not be more than DEFAULT_THREAD_COUNT_LIMIT
-#endif
-
-#if LIMIT_FUNCTION_SPEED <= 0
-#error LIMIT_FUNCTION_SPEED must be more than 0
+#ifndef MIN_THREADS
+#define MIN_THREADS 2
 #endif
 
-/* The maximum number of threads to use for async ops */
-static int thread_count_limit;
-
-/* This is the maximum number of threads reserved for higher priority jobs */
-static float max_decrease;
-
-typedef GTree JobQueueType;
-
-/* This mutex protects these */
-static GStaticMutex job_queue_lock = G_STATIC_MUTEX_INIT;
-static JobQueueType *job_queue;
-static int running_job_count;
-static int job_id;
-#ifdef QUEUE_DEBUG
-  static int job_queue_length;
-#endif
-/* end mutex guard */
-
-typedef struct JobQueueKey {
-	int job_id;
-	int priority;
-} JobQueueKey;
-
-static int
-key_compare (gconstpointer cast_to_key1, gconstpointer cast_to_key2, gpointer user_data)
-{
-	JobQueueKey *key1 = (JobQueueKey *)cast_to_key1;
-	JobQueueKey *key2 = (JobQueueKey *)cast_to_key2;
-
-	/* Lower priority job comes first */
-	if (key1->priority > key2->priority) {
-		return 1;
-	}
-
-	if (key1->priority < key2->priority) {
-		return -1;
-	}
-
-	/* If the 2 priorities are the same then the
-	   job with the lower job_id comes first.
-
-	   job_ids are positive so this won't overflow.
-	*/
-	return key1->job_id - key2->job_id;
-}
-
-static void
-value_destroy (gpointer cast_to_job)
-{
-	_gnome_vfs_job_destroy ((GnomeVFSJob *)cast_to_job);
-}
-
-static JobQueueType *
-job_queue_new (void)
-{
-	return g_tree_new_full (key_compare, NULL, g_free, value_destroy);
-}
+static GThreadPool *thread_pool = NULL;
 
-static void
-job_queue_destroy (void)
-{
-	g_tree_destroy (job_queue);
-	job_queue = NULL;
-}
+static volatile gboolean gnome_vfs_quitting = FALSE;
+static volatile gboolean gnome_vfs_done_quitting = FALSE;
 
 static void
-job_queue_add (GnomeVFSJob *job)
-{
-	JobQueueKey *key = g_new (JobQueueKey, 1);
-	key->job_id = ++job_id;
-	key->priority = job->priority;
-
-	g_tree_insert (job_queue, key, job);
-#ifdef QUEUE_DEBUG
-	job_queue_length++;
-#endif
-}
-
-static int
-find_first_value (gpointer key, gpointer value, gpointer data)
+thread_entry_point (gpointer data, gpointer user_data)
 {
-	*((GnomeVFSJob **)data) = value;
-	return TRUE;
-}
-
-static GnomeVFSJob *
-job_queue_get_first (void)
-{
-	GnomeVFSJob *job = NULL;
-
-	if (job_queue) {
-		g_tree_foreach (job_queue, find_first_value, &job);
+	guint id;
+	GnomeVFSJob *job;
+	GnomeVFSAsyncHandle *job_handle;
+	gboolean complete;
+
+	job_handle = (GnomeVFSAsyncHandle *) data;
+
+	id = GPOINTER_TO_UINT (job_handle);
+	/* job map must always be locked before the job_lock
+	 * if both locks are needed */
+	_gnome_vfs_async_job_map_lock ();
+	
+	job = _gnome_vfs_async_job_map_get_job (job_handle);
+	
+	if (job == NULL) {
+		JOB_DEBUG (("job already dead, bail %u", id));
+		_gnome_vfs_async_job_map_unlock ();
+		return;
+	}
+	
+	JOB_DEBUG (("locking job_lock %u", id));
+	g_mutex_lock (job->job_lock);
+	_gnome_vfs_async_job_map_unlock ();
+
+	_gnome_vfs_job_execute (job);
+	complete = _gnome_vfs_job_complete (job);
+	
+	JOB_DEBUG (("Unlocking access lock %u", id));
+	g_mutex_unlock (job->job_lock);
+
+	if (complete) {
+		_gnome_vfs_async_job_map_lock ();
+		JOB_DEBUG (("job %u done, removing from map and destroying", id));
+		_gnome_vfs_async_job_completed (job_handle);
+		_gnome_vfs_job_destroy (job);
+		_gnome_vfs_async_job_map_unlock ();
 	}
-
-	return job;
-}
-
-static int
-find_first_key (gpointer key, gpointer value, gpointer data)
-{
-	*((JobQueueKey **)data) = key;
-	return TRUE;
 }
 
-static void
-job_queue_delete_first (void)
-{
-	JobQueueKey *key = NULL;
-
-	g_tree_foreach (job_queue, find_first_key, &key);
-	g_tree_steal (job_queue, key);
-
-	g_free (key);
-#ifdef QUEUE_DEBUG
-	job_queue_length--;
-#endif
-}
 
 void 
 _gnome_vfs_job_queue_init (void)
 {
-	static gboolean queue_initialized = FALSE;
-
-	if (queue_initialized != TRUE) {
-		Q_DEBUG (("initializing the job queue (thread limit: %d)\n", DEFAULT_THREAD_COUNT_LIMIT));
-		thread_count_limit = DEFAULT_THREAD_COUNT_LIMIT;
-		max_decrease = (float)thread_count_limit - LIMIT_FUNCTION_LOWER_BOUND;
-		job_queue = job_queue_new ();
-		queue_initialized = TRUE;
-	}
+	thread_pool = g_thread_pool_new (thread_entry_point,
+					 NULL,
+					 DEFAULT_THREAD_COUNT_LIMIT,
+					 FALSE,
+					 NULL);
 }
 
-/* This function implements a scheduling policy where a certain number
-   of threads is reserved for high priority jobs so they can start
-   immediately if needed.  The lower the priority of the running jobs
-   the more threads are reserved.  So the actual limit on running jobs
-   is a function of the priority of the job to be started.
-   This function converges to LIMIT_FUNCTION_LOWER_BOUND (i.e. this
-   will be the limit belonging to the lowest priority jobs.)
-   The speed of convergence is determined by LIMIT_FUNCTION_SPEED.
-   For negative priority jobs the limit equals to thread_count_limit.
-
-   Note that thread_count_limit can be queried/set runtime using the
-   gnome_vfs_async_job_{get,set}_limit functions.
-
-   The formula is as follows:
-
-   max_decrease = thread_count_limit - LIMIT_FUNCTION_LOWER_BOUND
-
-   This is the maximum difference between the limit function and the
-   thread_count_limit.
-
-                                                max_decrease * p
-   max jobs = thread_count_limit  - floor (--------------------------)
-                                            LIMIT_FUNCTION_SPEED + p
-
-   This table shows some limits belonging to the default parameters:
-
-   priority of the  | max number
-   job to start     | of jobs
-   -----------------+-----------
-   <1               | 10
-   1                | 9
-   2                | 9
-   3                | 8
-   5                | 7
-   10               | 6
-   20               | 5
-   50               | 3
-   1000             | 3
 
-   For example a job with a priority of 3 will NOT be started if
-   there are at least 8 jobs already running.
-*/
-static gboolean
-job_can_start (int priority)
+gboolean
+_gnome_vfs_job_schedule (GnomeVFSJob *job)
 {
-	int transformed_priority;
-	int actual_limit;
-
-	/* Move the highest priority to the zero point */
-	transformed_priority = priority + GNOME_VFS_PRIORITY_MIN;
+	GError *err = NULL;
+	
+	if (G_UNLIKELY (gnome_vfs_quitting)) {
+		g_warning ("Starting of GnomeVFS async calls after quit.");
+	}
 
-	if (running_job_count >= thread_count_limit) {
-		/* Max number of jobs are already running */
+	if (G_UNLIKELY (gnome_vfs_done_quitting)) {
+		/* The application is quitting, we have already returned from
+		 * gnome_vfs_wait_for_slave_threads, we can't start any more threads
+		 * because they would potentially block indefinitely and prevent the
+		 * app from quitting.
+		 */
 		return FALSE;
-        } else if (transformed_priority >= 0) {
-		/* Let's not allow low (i.e. positive) priority jobs to use up all the threads.
-		   We reserve some threads for higher priority jobs.
-		   The lower the priority to more threads are reserved.
-
-		   The actual limit should the the thread count limit less a proportion
-		   of the maximum decrease.
-		*/
-
-		actual_limit = thread_count_limit - (int)(max_decrease * transformed_priority /
-							  (LIMIT_FUNCTION_SPEED + transformed_priority));
-		
-		if (actual_limit <= running_job_count) {
-			return FALSE;
-		}
 	}
-	return TRUE;
-}
 
-void
-_gnome_vfs_job_queue_run (void)
-{
-	GnomeVFSJob *job_to_run;
+	g_thread_pool_push (thread_pool, job->job_handle, &err);
 
-	g_static_mutex_lock (&job_queue_lock);
+	if (G_UNLIKELY (err != NULL)) {
+		g_warning ("Could not push thread %s into pool\n",
+			   err->message);
 
-	running_job_count--;
-	Q_DEBUG (("job finished;\t\t\t\t       %d jobs running, %d waiting\n",
-		 running_job_count,
-		 job_queue_length));
-
-	job_to_run = job_queue_get_first ();
-	if (job_to_run != NULL) {
-		/* The queue is not empty */
-		if (job_can_start (job_to_run->priority)) {
-			running_job_count++;
-			job_queue_delete_first ();
-			Q_DEBUG (("taking a %2d priority job from the queue;"
-				 "       %d jobs running, %d waiting\n",
-				 job_to_run->priority,
-				 running_job_count,
-				 job_queue_length));
-			g_static_mutex_unlock (&job_queue_lock);
-			_gnome_vfs_job_create_slave (job_to_run);
-		} else {
-			g_static_mutex_unlock (&job_queue_lock);
-			Q_DEBUG (("waiting job is too low priority (%2d) to start;"
-				 " %d jobs running, %d waiting\n",
-				 job_to_run->priority,
-				 running_job_count,
-				 job_queue_length));
-		}
-	} else {
-		g_static_mutex_unlock (&job_queue_lock);
-		Q_DEBUG (("the queue is empty;\t\t\t       %d jobs running\n", running_job_count));
+		/* thread did not start up, remove the job from the hash table */
+		_gnome_vfs_async_job_completed (job->job_handle);
+		
+		return FALSE;
 	}
-}
 
-gboolean
-_gnome_vfs_job_schedule (GnomeVFSJob *job)
-{
-	g_static_mutex_lock (&job_queue_lock);
-      	if (!job_can_start (job->priority)) {
-	  	job_queue_add (job);
-		Q_DEBUG (("adding a %2d priority job to the queue;"
-			 "\t       %d jobs running, %d waiting\n",
-			 job->priority,
-			 running_job_count,
-			 job_queue_length));
-		g_static_mutex_unlock (&job_queue_lock);
-	} else {
-		running_job_count++;
-		Q_DEBUG (("starting a %2d priority job;\t\t       %d jobs running, %d waiting\n",
-			job->priority,
-			running_job_count,
-			job_queue_length));
-		g_static_mutex_unlock (&job_queue_lock);
-		_gnome_vfs_job_create_slave (job);
-	}
-	return TRUE;
+	return TRUE;	
 }
 
 /**
@@ -332,16 +136,13 @@ _gnome_vfs_job_schedule (GnomeVFSJob *jo
 void
 gnome_vfs_async_set_job_limit (int limit)
 {
-	if (limit < LIMIT_FUNCTION_LOWER_BOUND) {
+	if (limit < MIN_THREADS) {
 		g_warning ("Attempt to set the thread_count_limit below %d", 
-			   LIMIT_FUNCTION_LOWER_BOUND);
+			   MIN_THREADS);
 		return;
 	}
-	g_static_mutex_lock (&job_queue_lock);
-	thread_count_limit = limit;
-	max_decrease = (float)thread_count_limit - LIMIT_FUNCTION_LOWER_BOUND;
-	Q_DEBUG (("changing the thread count limit to %d\n", limit));
-	g_static_mutex_unlock (&job_queue_lock);
+
+	g_thread_pool_set_max_threads (thread_pool, limit, NULL);
 }
 
 /**
@@ -355,15 +156,24 @@ gnome_vfs_async_set_job_limit (int limit
 int
 gnome_vfs_async_get_job_limit (void)
 {
-	return thread_count_limit;
+	return g_thread_pool_get_max_threads (thread_pool);
 }
 
 void
 _gnome_vfs_job_queue_shutdown (void)
 {
-	g_static_mutex_lock (&job_queue_lock);
+	g_thread_pool_free (thread_pool, FALSE, FALSE);
 
-	job_queue_destroy ();
+	gnome_vfs_quitting = TRUE;
 
-	g_static_mutex_unlock (&job_queue_lock);
+	while (gnome_vfs_job_get_count () != 0) {
+		
+		g_main_context_iteration (NULL, FALSE);
+		g_usleep (20000);
+
+	}
+
+	gnome_vfs_done_quitting = TRUE;	
+	_gnome_vfs_async_job_map_shutdown ();
 }
+
Index: libgnomevfs/gnome-vfs-job-queue.h
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-job-queue.h,v
retrieving revision 1.2
diff -u -p -r1.2 gnome-vfs-job-queue.h
--- libgnomevfs/gnome-vfs-job-queue.h	19 Dec 2002 17:57:19 -0000	1.2
+++ libgnomevfs/gnome-vfs-job-queue.h	2 Dec 2005 17:18:12 -0000
@@ -28,9 +28,8 @@
 
 #include "gnome-vfs-job.h"
 
-void          _gnome_vfs_job_queue_init       (void);
-void          _gnome_vfs_job_queue_shutdown   (void);
-gboolean      _gnome_vfs_job_schedule         (GnomeVFSJob       *job);
-void          _gnome_vfs_job_queue_run        (void);
+void          _gnome_vfs_job_queue_init       (void) G_GNUC_INTERNAL;
+void          _gnome_vfs_job_queue_shutdown   (void) G_GNUC_INTERNAL;
+gboolean      _gnome_vfs_job_schedule         (GnomeVFSJob       *job) G_GNUC_INTERNAL;
 
 #endif /* GNOME_VFS_JOB_QUEUE_H */
Index: libgnomevfs/gnome-vfs-job.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-job.c,v
retrieving revision 1.105
diff -u -p -r1.105 gnome-vfs-job.c
--- libgnomevfs/gnome-vfs-job.c	8 May 2005 13:04:05 -0000	1.105
+++ libgnomevfs/gnome-vfs-job.c	2 Dec 2005 17:18:12 -0000
@@ -31,7 +31,6 @@ System (version for POSIX threads).
 #include "gnome-vfs-job.h"
 
 #include "gnome-vfs-async-job-map.h"
-#include "gnome-vfs-job-slave.h"
 #include "gnome-vfs-job-queue.h"
 #include "gnome-vfs-private-utils.h"
 #include <errno.h>
Index: libgnomevfs/gnome-vfs-pthread.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/libgnomevfs/gnome-vfs-pthread.c,v
retrieving revision 1.5
diff -u -p -r1.5 gnome-vfs-pthread.c
--- libgnomevfs/gnome-vfs-pthread.c	19 Dec 2002 17:57:19 -0000	1.5
+++ libgnomevfs/gnome-vfs-pthread.c	2 Dec 2005 17:18:12 -0000
@@ -2,6 +2,7 @@
 #include "gnome-vfs-async-job-map.h"
 #include "gnome-vfs-thread-pool.h"
 #include "gnome-vfs-job-queue.h"
+#include "gnome-vfs-job-slave.h"
 
 gboolean
 gnome_vfs_pthread_init (gboolean init_deps)
@@ -11,7 +12,6 @@ gnome_vfs_pthread_init (gboolean init_de
 	}
 	
 	_gnome_vfs_async_job_map_init ();
-	_gnome_vfs_thread_pool_init ();
 	_gnome_vfs_job_queue_init ();
 	return TRUE;
 }
