Index: /branches/eam_branch_20080719/ppMerge/src/Makefile.am
===================================================================
--- /branches/eam_branch_20080719/ppMerge/src/Makefile.am	(revision 18821)
+++ /branches/eam_branch_20080719/ppMerge/src/Makefile.am	(revision 18822)
@@ -13,5 +13,5 @@
 	ppMergeReadChunk.c	\
 	ppMergeLoop_Threaded.c  \
-	ppMergeThreadLauncher.c	\
+	ppMergeSetThreads.c	\
 	ppMergeMask.c
 
Index: /branches/eam_branch_20080719/ppMerge/src/ppMerge.h
===================================================================
--- /branches/eam_branch_20080719/ppMerge/src/ppMerge.h	(revision 18821)
+++ /branches/eam_branch_20080719/ppMerge/src/ppMerge.h	(revision 18822)
@@ -105,3 +105,5 @@
 void *ppMergeThreadLauncher (void *data);
 
+bool ppMergeSetThreads ();
+
 #endif
Index: /branches/eam_branch_20080719/ppMerge/src/ppMergeArguments.c
===================================================================
--- /branches/eam_branch_20080719/ppMerge/src/ppMergeArguments.c	(revision 18821)
+++ /branches/eam_branch_20080719/ppMerge/src/ppMergeArguments.c	(revision 18822)
@@ -171,5 +171,4 @@
     }
 
-# if (THREADED)
     // Number of threads
     if ((argnum = psArgumentGet(argc, argv, "-threads"))) {
@@ -181,7 +180,7 @@
 	// create the thread pool with number of desired threads, supplying our thread launcher function
 	// XXX need to determine the number of threads from the config data
-	psThreadPoolInit (nThreads, &ppMergeThreadLauncher);
-    }
-# endif
+	psThreadPoolInit (nThreads);
+    }
+    ppMergeSetThreads();
 
     if (argc == 1 || !psArgumentParse(arguments, &argc, argv) || argc != 3) {
Index: /branches/eam_branch_20080719/ppMerge/src/ppMergeLoop_Threaded.c
===================================================================
--- /branches/eam_branch_20080719/ppMerge/src/ppMergeLoop_Threaded.c	(revision 18821)
+++ /branches/eam_branch_20080719/ppMerge/src/ppMergeLoop_Threaded.c	(revision 18822)
@@ -197,5 +197,5 @@
 
             // Read input data by chunks
-	    psTimerStart ("ppMergeLoop");
+	    // psTimerStart ("ppMergeLoop");
             for (int numChunk = 0; true; numChunk++) {
 
@@ -205,47 +205,41 @@
 		if (!fileGroup) break;
 
+		psThreadJob *job = NULL;
+
                 switch (type) {
                   case PPMERGE_TYPE_SHUTTER:
-		    if (nThreads) {
-			// allocate a job
-			psThreadJob *job = psThreadJobAlloc ("PPMERGE_SHUTTER_CORRECTION", 0);
-
-			// construct the arguments for this job
-			psArrayAdd (job->args, 1, outRO);
-			psArrayAdd (job->args, 1, fileGroup);
-			psArrayAdd (job->args, 1, psScalarAlloc(shutterRef, PS_TYPE_F32));
-			psArrayAdd (job->args, 1, shutters->data[cellNum]);
-			psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
-			psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
-			psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
-
-			psThreadJobAddPending (job);
-		    } else {
-			if (!pmShutterCorrectionGenerate(outRO, NULL, fileGroup->readouts, shutterRef, shutters->data[cellNum], iter, rej, maskVal)) {
-			    goto ERROR;
-			}
-			fileGroup->busy = false;
+		    // allocate a job
+		    job = psThreadJobAlloc ("PPMERGE_SHUTTER_CORRECTION");
+
+		    // construct the arguments for this job
+		    psArrayAdd (job->args, 1, outRO);
+		    psArrayAdd (job->args, 1, fileGroup);
+		    psArrayAdd (job->args, 1, psScalarAlloc(shutterRef, PS_TYPE_F32));
+		    psArrayAdd (job->args, 1, shutters->data[cellNum]);
+		    psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
+
+		    // call: pmShutterCorrectionGenerate(outRO, NULL, fileGroup->readouts, shutterRef, shutters->data[cellNum], iter, rej, maskVal)
+		    if (!psThreadJobAddPending (job)) {
+			goto ERROR;
 		    }
                     break;
                   case PPMERGE_TYPE_DARK:
-		    if (nThreads) {
-			// allocate a job
-			psThreadJob *job = psThreadJobAlloc ("PPMERGE_DARK_COMBINE", 0);
-
-			// construct the arguments for this job
-			psArrayAdd (job->args, 1, outCell);
-			psArrayAdd (job->args, 1, fileGroup);
-			psArrayAdd (job->args, 1, darkOrdinates);
-			psArrayAdd (job->args, 1, darkNorm);
-			psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
-			psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
-			psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
-
-			psThreadJobAddPending (job);
-		    } else {
-			if (!pmDarkCombine(outCell, fileGroup->readouts, darkOrdinates, darkNorm, iter, rej, maskVal)) {
-			    goto ERROR;
-			}
-			fileGroup->busy = false;
+		    // allocate a job
+		    job = psThreadJobAlloc ("PPMERGE_DARK_COMBINE");
+
+		    // construct the arguments for this job
+		    psArrayAdd (job->args, 1, outCell);
+		    psArrayAdd (job->args, 1, fileGroup);
+		    psArrayAdd (job->args, 1, darkOrdinates);
+		    psArrayAdd (job->args, 1, darkNorm);
+		    psArrayAdd (job->args, 1, psScalarAlloc(iter, PS_TYPE_S32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(rej, PS_TYPE_F32));
+		    psArrayAdd (job->args, 1, psScalarAlloc(maskVal, PS_TYPE_U8));
+
+		    // call: pmDarkCombine(outCell, fileGroup->readouts, darkOrdinates, darkNorm, iter, rej, maskVal);
+		    if (!psThreadJobAddPending (job)) {			
+			goto ERROR;
 		    }
                     break;
@@ -253,21 +247,17 @@
                   case PPMERGE_TYPE_FLAT:
                   case PPMERGE_TYPE_FRINGE:
-		    if (nThreads) {
-			// allocate a job
-			psThreadJob *job = psThreadJobAlloc ("PPMERGE_READOUT_COMBINE", 0);
-
-			// construct the arguments for this job
-			psArrayAdd (job->args, 1, outRO);
-			psArrayAdd (job->args, 1, fileGroup);
-			psArrayAdd (job->args, 1, zeros);
-			psArrayAdd (job->args, 1, scales);
-			psArrayAdd (job->args, 1, combination);
-
-			psThreadJobAddPending (job);
-		    } else {
-			if (!pmReadoutCombine(outRO, fileGroup->readouts, zeros, scales, combination)) {
-			    goto ERROR;
-			}
-			fileGroup->busy = false;
+		    // allocate a job
+		    job = psThreadJobAlloc ("PPMERGE_READOUT_COMBINE");
+
+		    // construct the arguments for this job
+		    psArrayAdd (job->args, 1, outRO);
+		    psArrayAdd (job->args, 1, fileGroup);
+		    psArrayAdd (job->args, 1, zeros);
+		    psArrayAdd (job->args, 1, scales);
+		    psArrayAdd (job->args, 1, combination);
+
+		    // call: pmReadoutCombine(outRO, fileGroup->readouts, zeros, scales, combination);
+		    if (!psThreadJobAddPending (job)) {
+			goto ERROR;
 		    }
                     break;
@@ -278,18 +268,15 @@
 
 	    // wait for the threads to finish and manage results
-	    if (nThreads) {
-		// wait here for the threaded jobs to finish
-		if (!psThreadPoolWait ()) {
-		    psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
-		    return false;
-		}
-		fprintf (stderr, "success for threaded jobs\n");
-
-		// we don't care about the results, just dump the done queue jobs
-		psThreadJob *job = NULL;
-		while ((job = psThreadJobGetDone()) != NULL) {
-		    psFree (job);
-		}
+	    if (!psThreadPoolWait ()) {
+		psError(PS_ERR_UNKNOWN, false, "Unable to combine images.");
+		return false;
 	    }
+
+	    // we don't care about the results, just dump the done queue jobs
+	    psThreadJob *job = NULL;
+	    while ((job = psThreadJobGetDone()) != NULL) {
+		psFree (job);
+	    }
+
             psFree(fileGroups);
 
@@ -308,5 +295,5 @@
             }
             psFree(inCells);
-	    fprintf (stdout, "done ppMergeLoop for cell : %f\n", psTimerMark ("ppMergeLoop"));
+	    // fprintf (stdout, "done ppMergeLoop for cell : %f\n", psTimerMark ("ppMergeLoop"));
 
             // Plug supplementary images into their own FPAs
Index: /branches/eam_branch_20080719/ppMerge/src/ppMergeSetThreads.c
===================================================================
--- /branches/eam_branch_20080719/ppMerge/src/ppMergeSetThreads.c	(revision 18822)
+++ /branches/eam_branch_20080719/ppMerge/src/ppMergeSetThreads.c	(revision 18822)
@@ -0,0 +1,70 @@
+# include "ppMerge.h"
+
+// "PPMERGE_READOUT_COMBINE", 5
+bool ppMergeThread_pmReadoutCombine (psThreadJob *job) {
+
+    pmReadout *output           = job->args->data[0];
+    ppMergeFileGroup *fileGroup = job->args->data[1];
+    psVector *zero              = job->args->data[2];
+    psVector *scale             = job->args->data[3];
+    pmCombineParams *params     = job->args->data[4];
+
+    bool status = pmReadoutCombine (output, fileGroup->readouts, zero, scale, params);
+
+    // after we are done, tell the I/O system that this file group is done
+    fileGroup->busy = false; 
+    return status;
+}
+
+bool ppMergeThread_pmDarkCombine (psThreadJob *job) {
+
+    pmCell *outCell             = job->args->data[0];
+    ppMergeFileGroup *fileGroup = job->args->data[1];
+    psArray *darkOrdinates      = job->args->data[2];
+    psString darkNorm           = job->args->data[3];
+    psScalar *iter     	        = job->args->data[4];
+    psScalar *rej     	        = job->args->data[5];
+    psScalar *maskVal     	= job->args->data[6];
+
+    bool status = pmDarkCombine(outCell, fileGroup->readouts, darkOrdinates, darkNorm, iter->data.S32, rej->data.F32, maskVal->data.U8);
+
+    // after we are done, tell the I/O system that this file group is done
+    fileGroup->busy = false;
+    return status;
+}
+
+bool ppMergeThread_pmShuttderCorrectionGenerate (psThreadJob *job) {
+
+    pmReadout *output             = job->args->data[0];
+    ppMergeFileGroup *fileGroup   = job->args->data[1];
+    psScalar *shutterRef          = job->args->data[2];
+    pmShutterCorrectionData *data = job->args->data[3];
+    psScalar *iter     	          = job->args->data[4];
+    psScalar *rej     	          = job->args->data[5];
+    psScalar *maskVal     	  = job->args->data[6];
+
+    bool status = pmShutterCorrectionGenerate(output, NULL, fileGroup->readouts, shutterRef->data.F32, data, iter->data.S32, rej->data.F32, maskVal->data.U8);
+
+    // after we are done, tell the I/O system that this file group is done
+    fileGroup->busy = false;
+    return status;
+}
+
+bool ppMergeSetThreads () {
+
+    psThreadTask *task = NULL;
+
+    task = psThreadTaskAlloc ("PPMERGE_READOUT_COMBINE", 5);
+    task->function = &ppMergeThread_pmReadoutCombine;
+    psThreadTaskAdd (task);
+
+    task = psThreadTaskAlloc ("PPMERGE_DARK_COMBINE", 7);
+    task->function = &ppMergeThread_pmReadoutCombine;
+    psThreadTaskAdd (task);
+
+    task = psThreadTaskAlloc ("PPMERGE_SHUTTER_CORRECTION", 7);
+    task->function = &ppMergeThread_pmReadoutCombine;
+    psThreadTaskAdd (task);
+
+    return true;
+}
Index: /branches/eam_branch_20080719/psLib/src/sys/psThread.c
===================================================================
--- /branches/eam_branch_20080719/psLib/src/sys/psThread.c	(revision 18821)
+++ /branches/eam_branch_20080719/psLib/src/sys/psThread.c	(revision 18822)
@@ -6,4 +6,5 @@
 #include <stdarg.h>
 #include <unistd.h>
+#include <string.h>
 
 #include "psAssert.h"
@@ -19,6 +20,8 @@
 static psList *pending = NULL;		// queue of pending jobs
 static psList *done = NULL;		// queue of done jobs
-
 static psArray *pool = NULL;		// array of defined threads
+static psArray *tasks = NULL;		// queue of tasks
+
+/***** basic thread functions *****/
 
 void psThreadLock () {
@@ -30,63 +33,4 @@
     pthread_mutex_unlock (&mutex);
     return;
-}
-
-void psThreadJobFree (psThreadJob *job) {
-
-    if (!job) return;
-
-    psFree (job->type);
-    psFree (job->args);
-    return;
-}
-
-// allocate a psThreadJob with nArgs arguments
-psThreadJob *psThreadJobAlloc (char *type, int nArgs) {
-    
-    psThreadJob *job = (psThreadJob *)psAlloc(sizeof(psThreadJob));
-    psMemSetDeallocator(job, (psFreeFunc)psThreadJobFree);
-
-    job->type = psStringCopy (type);
-    job->args = psArrayAllocEmpty (nArgs);
-    return job;
-}
-
-// add a job to the queue of pending jobs
-bool psThreadJobAddPending (psThreadJob *job) {
-
-    psThreadLock ();
-    if (pending == NULL) {
-	pending = psListAlloc(NULL);
-    }
-
-    psListAdd (pending, PS_LIST_TAIL, job);
-    psThreadUnlock ();
-    return true;
-}
-
-// this function is not locked -- see thread launder for example
-psThreadJob *psThreadJobGetPending () {
-
-    if (!pending) return NULL;
-
-    psThreadJob *job = psListGetAndRemove (pending, PS_LIST_HEAD);
-
-    // jobs we pull off the pending queue get placed on the done queue
-    if (job) {
-	if (done == NULL) {
-	    done = psListAlloc(NULL);
-	}
-	psListAdd (done, PS_LIST_TAIL, job);
-    }
-    return job;
-}
-
-// this function is not locked -- see thread launder for example
-psThreadJob *psThreadJobGetDone () {
-
-    if (!done) return NULL;
-
-    psThreadJob *job = psListGetAndRemove (done, PS_LIST_HEAD);
-    return job;
 }
 
@@ -106,6 +50,172 @@
 }
 
+/***** thread job functions *****/
+
+void psThreadJobFree (psThreadJob *job) {
+
+    if (!job) return;
+
+    psFree (job->type);
+    psFree (job->args);
+    return;
+}
+
+// allocate a psThreadJob of the given type
+psThreadJob *psThreadJobAlloc (char *type) {
+    
+    psThreadJob *job = (psThreadJob *)psAlloc(sizeof(psThreadJob));
+    psMemSetDeallocator(job, (psFreeFunc)psThreadJobFree);
+
+    job->type = psStringCopy (type);
+    job->args = psArrayAlloc (0);
+    return job;
+}
+
+// add a job to the queue of pending jobs
+bool psThreadJobAddPending (psThreadJob *job) {
+
+    // if we failed to call psThreadPoolInit, or we called it with nThreads == 0,
+    // find the matching function and just run it.
+    if (!pool || !pool->n) {
+
+	// in non-threaded operation, the job is placed on the done list and immediately run
+	if (done == NULL) {
+	    done = psListAlloc(NULL);
+	}
+	psListAdd (done, PS_LIST_TAIL, job);
+
+	// find the corresponding task and run it
+	for (int i = 0; i < tasks->n; i++) {
+	    psThreadTask *task = tasks->data[i];
+	    if (strcmp (job->type, task->type)) continue;
+
+	    psAssert (job->args->n == task->nArgs, "invalid number of arguments to %s", task->type);
+
+	    bool status = task->function(job);
+	    return status;
+	}
+	return false;
+    }
+
+    psThreadLock ();
+    if (pending == NULL) {
+	pending = psListAlloc(NULL);
+    }
+
+    psListAdd (pending, PS_LIST_TAIL, job);
+    psThreadUnlock ();
+    return true;
+}
+
+// this function is not locked -- see thread launder for example
+psThreadJob *psThreadJobGetPending () {
+
+    if (!pending) return NULL;
+
+    psThreadJob *job = psListGetAndRemove (pending, PS_LIST_HEAD);
+
+    // jobs we pull off the pending queue get placed on the done queue
+    if (job) {
+	if (done == NULL) {
+	    done = psListAlloc(NULL);
+	}
+	psListAdd (done, PS_LIST_TAIL, job);
+    }
+    return job;
+}
+
+// this function is not locked -- see thread launder for example
+psThreadJob *psThreadJobGetDone () {
+
+    if (!done) return NULL;
+
+    psThreadJob *job = psListGetAndRemove (done, PS_LIST_HEAD);
+    return job;
+}
+
+/***** thread task functions *****/
+
+void psThreadTaskFree (psThreadTask *task) {
+
+    if (!task) return;
+
+    psFree (task->type);
+    return;
+}
+
+// allocate a psThreadTask with nArgs arguments
+psThreadTask *psThreadTaskAlloc (char *type, int nArgs) {
+    
+    psThreadTask *task = (psThreadTask *)psAlloc(sizeof(psThreadTask));
+    psMemSetDeallocator(task, (psFreeFunc)psThreadTaskFree);
+
+    task->type = psStringCopy (type);
+    task->nArgs = nArgs;
+    task->function = NULL;
+    return task;
+}
+
+// add a task to the collection of tasks
+bool psThreadTaskAdd (psThreadTask *task) {
+
+    if (tasks == NULL) {
+	tasks = psArrayAllocEmpty(8);
+    }
+
+    psArrayAdd (tasks, 1, task);
+    return true;
+}
+
+// each thread runs this function to choose the task functions
+void *psThreadLauncher (void *data) {
+
+    psThread *self = data;
+    psThreadJob *job = NULL;
+
+    while (1) {
+
+	// if we get an error, just wait until we are cleared or killed
+	while (self->fault) {
+	    usleep (10000);
+	}
+
+	// if no tasks are assigned, just wait until they are
+	while (tasks == NULL) {
+	    usleep (10000);
+	}
+
+	// request a new job, if there are none available, sleep a bit
+	// we have to lock here so the job queue cannot be empty yet no threads busy
+	psThreadLock();
+	while ((job = psThreadJobGetPending ()) == NULL) {
+	    psThreadUnlock();
+	    usleep (10000);
+	    psThreadLock(); // XXX ???
+	}
+	self->busy = true;
+
+	for (int i = 0; i < tasks->n; i++) {
+	    psThreadTask *task = tasks->data[i];
+	    if (strcmp (job->type, task->type)) continue;
+
+	    psThreadUnlock();
+	    psAssert (job->args->n == task->nArgs, "invalid number of arguments to %s", task->type);
+
+	    bool status = task->function(job);
+	    if (!status) {
+		self->fault = true;
+	    }
+	    self->busy = false;  
+	    break;
+	}
+	psThreadUnlock();
+	// XXX what do we do if the job is unknown?
+    }
+}
+
+/***** thread pool functions *****/
+
 // create a pool of Nthreads, each running the user's job-launcher function
-bool psThreadPoolInit (int nThreads, psThreadLaunchJobsFunction function) {
+bool psThreadPoolInit (int nThreads) {
 
     if (pool) psAbort ("psThreadsInit already called"); 
@@ -114,5 +224,5 @@
     for (int i = 0; i < nThreads; i++) {
 	psThread *thread = psThreadAlloc();
-	pthread_create (&thread->pt, NULL, function, thread);
+	pthread_create (&thread->pt, NULL, psThreadLauncher, thread);
 	pool->data[i] = thread;
     }
@@ -126,4 +236,7 @@
     // an error is detected on one of the threads or until 
     // all threads are idle and no jobs are left on the queue
+
+    if (!pool) return true;
+    if (!pool->n) return true;
 
     while (1) {
@@ -169,5 +282,8 @@
     pool = NULL;
 
-    return true;
-}
-
+    psFree (tasks);
+    tasks = NULL;
+
+    return true;
+}
+
Index: /branches/eam_branch_20080719/psLib/src/sys/psThread.h
===================================================================
--- /branches/eam_branch_20080719/psLib/src/sys/psThread.h	(revision 18821)
+++ /branches/eam_branch_20080719/psLib/src/sys/psThread.h	(revision 18822)
@@ -4,6 +4,6 @@
  *
  *  @author EAM, IFA
- *  @version $Revision: 1.1.2.3 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2008-07-27 22:42:32 $
+ *  @version $Revision: 1.1.2.4 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2008-07-31 23:24:22 $
  *
  *  Copyright 2004-2005 Insitute for Astronomy, University of Hawaii
@@ -27,17 +27,29 @@
 } psThread;
 
-typedef void *(*psThreadLaunchJobsFunction)(void *data);
+typedef bool (*psThreadTaskFunction)(psThreadJob *job);
+
+typedef struct {
+    psString type;
+    int nArgs;
+    psThreadTaskFunction function;
+} psThreadTask;
+
+// typedef void *(*psThreadLaunchJobsFunction)(void *data);
 
 void psThreadLock ();
 void psThreadUnlock ();
 
-psThreadJob *psThreadJobAlloc (char *type, int nArgs);
+psThread *psThreadAlloc ();
+
+psThreadJob *psThreadJobAlloc (char *type);
 bool psThreadJobAddPending (psThreadJob *job);
 psThreadJob *psThreadJobGetPending ();
 psThreadJob *psThreadJobGetDone ();
 
-psThread *psThreadAlloc ();
+psThreadTask *psThreadTaskAlloc (char *type, int nArgs);
+bool psThreadTaskAdd (psThreadTask *task);
+void *psThreadLauncher (void *data);
 
-bool psThreadPoolInit (int nThreads, psThreadLaunchJobsFunction function);
+bool psThreadPoolInit (int nThreads);
 bool psThreadPoolWait ();
 bool psThreadPoolFinalize ();
Index: /branches/eam_branch_20080719/pswarp/src/Makefile.am
===================================================================
--- /branches/eam_branch_20080719/pswarp/src/Makefile.am	(revision 18821)
+++ /branches/eam_branch_20080719/pswarp/src/Makefile.am	(revision 18822)
@@ -16,5 +16,5 @@
 	pswarpPixelFraction.c		\
 	pswarpSetMaskBits.c		\
-	pswarpThreadLauncher.c	        \
+	pswarpSetThreads.c	        \
 	pswarpTransformReadout.c	\
 	pswarpTransformSources.c \
Index: /branches/eam_branch_20080719/pswarp/src/pswarp.h
===================================================================
--- /branches/eam_branch_20080719/pswarp/src/pswarp.h	(revision 18821)
+++ /branches/eam_branch_20080719/pswarp/src/pswarp.h	(revision 18822)
@@ -90,4 +90,4 @@
     );
 
-// thread launcher for this program
-void *pswarpThreadLauncher (void *data);
+// define threads for this program
+bool pswarpSetThreads ();
Index: /branches/eam_branch_20080719/pswarp/src/pswarpArguments.c
===================================================================
--- /branches/eam_branch_20080719/pswarp/src/pswarpArguments.c	(revision 18821)
+++ /branches/eam_branch_20080719/pswarp/src/pswarpArguments.c	(revision 18822)
@@ -50,6 +50,7 @@
 	// create the thread pool with number of desired threads, supplying our thread launcher function
 	// XXX need to determine the number of threads from the config data
-	psThreadPoolInit (nThreads, &pswarpThreadLauncher);
+	psThreadPoolInit (nThreads);
     }
+    pswarpSetThreads ();
 
     // PSF determination?
Index: /branches/eam_branch_20080719/pswarp/src/pswarpSetThreads.c
===================================================================
--- /branches/eam_branch_20080719/pswarp/src/pswarpSetThreads.c	(revision 18822)
+++ /branches/eam_branch_20080719/pswarp/src/pswarpSetThreads.c	(revision 18822)
@@ -0,0 +1,21 @@
+# include "pswarp.h"
+
+// each thread runs this function, starting a new job when it finished with an old one
+// it is called with a (void *) pointer to its own thread pointer
+bool pswarpThread_pswarpTransformTile (psThreadJob *job) {
+
+    pswarpTransformTileArgs *args = job->args->data[0];
+    bool status = pswarpTransformTile (args);
+    return status;
+}
+
+bool pswarpSetThreads () {
+
+    psThreadTask *task = NULL;
+
+    task = psThreadTaskAlloc ("PSWARP_TRANSFORM_TILE", 1);
+    task->function = &pswarpThread_pswarpTransformTile;
+    psThreadTaskAdd (task);
+
+    return true;
+}
Index: /branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout.c
===================================================================
--- /branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout.c	(revision 18821)
+++ /branches/eam_branch_20080719/pswarp/src/pswarpTransformReadout.c	(revision 18822)
@@ -71,16 +71,16 @@
 	    args->goodPixels = 0;
 
-	    if (nThreads) {
-		// allocate a job
-		psThreadJob *job = psThreadJobAlloc ("PSWARP_TRANSFORM_TILE", 0);
+	    // allocate a job
+	    psThreadJob *job = psThreadJobAlloc ("PSWARP_TRANSFORM_TILE");
 
-		// construct the arguments for this job
-		// job is pswarpTransformTile (gridX, gridY);
-		psArrayAdd (job->args, 1, args);
-		// fprintf (stderr, "adding job %d,%d, Nargs: %ld\n", gridX, gridY, job->args->n);
-		psThreadJobAddPending (job);
-	    } else {
-		pswarpTransformTile (args);
-		goodPixels += args->goodPixels;
+	    // construct the arguments for this job
+	    // job is pswarpTransformTile (gridX, gridY);
+	    psArrayAdd (job->args, 1, args);
+	    // fprintf (stderr, "adding job %d,%d, Nargs: %ld\n", gridX, gridY, job->args->n);
+
+	    // call: pswarpTransformTile (args);
+	    if (!psThreadJobAddPending (job)) {
+		psError(PS_ERR_UNKNOWN, false, "Unable to warp image.");
+		return false;
 	    }
 	    psFree (args);
@@ -89,25 +89,23 @@
 
     // wait for the threads to finish and manage results
-    if (nThreads) {
-	// wait here for the threaded jobs to finish
-	if (!psThreadPoolWait ()) {
-	    psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
-	    return false;
+    // wait here for the threaded jobs to finish
+    if (!psThreadPoolWait ()) {
+	psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image.");
+	return false;
+    }
+    fprintf (stderr, "success for threaded jobs\n");
+
+    // each job records its own goodPixel values; sum them here
+    // we have only supplied one type of job, so we can assume the types here
+    psThreadJob *job = NULL;
+    while ((job = psThreadJobGetDone()) != NULL) {
+	if (job->args->n < 1) {
+	    fprintf (stderr, "error with job\n");
+	} else {
+	    pswarpTransformTileArgs *args = job->args->data[0];
+	    // fprintf (stderr, "finished job %d,%d, Nargs: %ld\n", args->gridX, args->gridY, job->args->n);
+	    goodPixels += args->goodPixels;
 	}
-	fprintf (stderr, "success for threaded jobs\n");
-
-	// each job records its own goodPixel values; sum them here
-	// we have only supplied one type of job, so we can assume the types here
-	psThreadJob *job = NULL;
-	while ((job = psThreadJobGetDone()) != NULL) {
-	    if (job->args->n < 1) {
-		fprintf (stderr, "error with job\n");
-	    } else {
-		pswarpTransformTileArgs *args = job->args->data[0];
-		// fprintf (stderr, "finished job %d,%d, Nargs: %ld\n", args->gridX, args->gridY, job->args->n);
-		goodPixels += args->goodPixels;
-	    }
-	    psFree (job);
-	}
+	psFree (job);
     }
     psFree(interp);
