Hello again,

I was a bit in a rush at the first try. Sorry for that, I tidied it up
slightly.

Best regards, Adam.

Am 05.04.2013 19:27, schrieb Adam Reichold:
> Hello everyone,
> 
> To make it easier for us to test changes w.r.t. to threading, I would
> propose to commit a simple implementation of threading in 'pdftoppm' to
> master.
> 
> The attached patch contains a very simple implementation that is not
> focused on maximal performance but should suffice to stress the locking
> inside Poppler's core. I opted to implement only the POSIX approach
> since I suppose POSIX systems are where most of us test and the code is
> hopefully simple and short enough not become a maintenance burden.
> 
> What do you think?
> 
> Best regards, Adam.
> 
> 
> 
> _______________________________________________
> poppler mailing list
> [email protected]
> http://lists.freedesktop.org/mailman/listinfo/poppler
> 
>From a3529b40ebf01285a44bd88c868a8b55713b6b95 Mon Sep 17 00:00:00 2001
From: Adam Reichold <[email protected]>
Date: Fri, 5 Apr 2013 19:21:13 +0200
Subject: [PATCH 1/2] add optional threading support to pdftoppm util

---
 CMakeLists.txt    |   1 +
 configure.ac      |   4 ++
 utils/pdftoppm.cc | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4643ae0..96b768a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,6 +33,7 @@ option(ENABLE_LIBCURL "Build libcurl based HTTP support." OFF)
 option(ENABLE_ZLIB "Build with zlib (not totally safe)." OFF)
 option(USE_FIXEDPOINT "Use fixed point arithmetic in the Splash backend" OFF)
 option(USE_FLOAT "Use single precision arithmetic in the Splash backend" OFF)
+option(UTILS_USE_THREAD "Use threads in utils" OFF)
 if(WIN32)
   option(ENABLE_RELOCATABLE "Do not hardcode the poppler library location (on Windows)." ON)
 else(WIN32)
diff --git a/configure.ac b/configure.ac
index cd4645b..3b7700f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,6 +91,10 @@ AC_ARG_ENABLE(fixedpoint,
 [  --enable-fixedpoint     use fixed point (instead of double precision) arithmetic in the Splash backend],
 AC_DEFINE(USE_FIXEDPOINT, [1], [Use fixed point arithmetic in the Splash backend]))
 
+AC_ARG_ENABLE(utils-use-threads,
+[  --enable-utils-use-threads     use threads in utils (in those that can)],
+AC_DEFINE(UTILS_USE_THREADS, [1], [Use threads in utils]))
+
 dnl Relocation support
 AC_ARG_ENABLE(relocatable,
     AC_HELP_STRING([--disable-relocatable],
diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc
index cebb12a..54d8a7c 100644
--- a/utils/pdftoppm.cc
+++ b/utils/pdftoppm.cc
@@ -49,6 +49,12 @@
 #include "splash/Splash.h"
 #include "SplashOutputDev.h"
 
+#ifdef UTILS_USE_THREADS
+#include <errno.h>
+#include <pthread.h>
+#include <deque>
+#endif // UTILS_USE_THREADS
+
 static int firstPage = 1;
 static int lastPage = 0;
 static GBool printOnlyOdd = gFalse;
@@ -81,6 +87,9 @@ static char vectorAntialiasStr[16] = "";
 static char ownerPassword[33] = "";
 static char userPassword[33] = "";
 static char TiffCompressionStr[16] = "";
+#ifdef UTILS_USE_THREADS
+static int numberOfJobs = 1;
+#endif // UTILS_USE_THREADS
 static GBool quiet = gFalse;
 static GBool printVersion = gFalse;
 static GBool printHelp = gFalse;
@@ -164,6 +173,11 @@ static const ArgDesc argDesc[] = {
   {"-upw",    argString,   userPassword,   sizeof(userPassword),
    "user password (for encrypted files)"},
   
+#ifdef UTILS_USE_THREADS
+  {"-j",      argInt,      &numberOfJobs,  0,
+   "number of jobs to run concurrently"},
+#endif // UTILS_USE_THREADS
+
   {"-q",      argFlag,     &quiet,         0,
    "don't print any messages or errors"},
   {"-v",      argFlag,     &printVersion,  0,
@@ -226,6 +240,57 @@ static void savePageSlice(PDFDoc *doc,
   }
 }
 
+#ifdef UTILS_USE_THREADS
+
+struct PageJob {
+  PDFDoc *doc;
+  int pg;
+  
+  int x,y,w,h;
+  double pg_w, pg_h;
+  
+  SplashColor* paperColor;
+  
+  int pg_num_len;
+  char *ppmFile;
+};
+
+static std::deque<PageJob> pageJobQueue;
+static pthread_mutex_t pageJobMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void processPageJobs() {
+  while(true) {
+    // pop the next job or exit if queue is empty
+    pthread_mutex_lock(&pageJobMutex);
+    
+    if(pageJobQueue.empty()) {
+      pthread_mutex_unlock(&pageJobMutex);
+      return;
+    }
+    
+    PageJob pageJob = pageJobQueue.front();
+    pageJobQueue.pop_front();
+    
+    pthread_mutex_unlock(&pageJobMutex);
+    
+    // process the job    
+    SplashOutputDev *splashOut = new SplashOutputDev(mono ? splashModeMono1 :
+                  gray ? splashModeMono8 :
+#if SPLASH_CMYK
+        			    (jpegcmyk || overprint) ? splashModeDeviceN8 :
+#endif
+		              splashModeRGB8, 4, gFalse, *pageJob.paperColor);
+    splashOut->startDoc(pageJob.doc);
+    
+    savePageSlice(pageJob.doc, splashOut, pageJob.pg, pageJob.x, pageJob.y, pageJob.w, pageJob.h, pageJob.pg_w, pageJob.pg_h, pageJob.ppmFile);
+    
+    delete splashOut;
+    delete[] pageJob.ppmFile;
+  }
+}
+
+#endif // UTILS_USE_THREADS
+
 static int numberOfCharacters(unsigned int n)
 {
   int charNum = 0;
@@ -250,6 +315,9 @@ int main(int argc, char *argv[]) {
   int exitCode;
   int pg, pg_num_len;
   double pg_w, pg_h, tmp;
+#ifdef UTILS_USE_THREADS
+  pthread_t* jobs;
+#endif // UTILS_USE_THREADS
 
   exitCode = 99;
 
@@ -362,6 +430,9 @@ int main(int argc, char *argv[]) {
     paperColor[1] = 255;
     paperColor[2] = 255;
   }
+  
+#ifndef UTILS_USE_THREADS
+
   splashOut = new SplashOutputDev(mono ? splashModeMono1 :
 				    gray ? splashModeMono8 :
 #if SPLASH_CMYK
@@ -370,6 +441,11 @@ int main(int argc, char *argv[]) {
 				             splashModeRGB8, 4,
 				  gFalse, paperColor);
   splashOut->startDoc(doc);
+  
+#else
+  (void)splashOut; // silence warning about unused variable
+#endif // UTILS_USE_THREADS
+  
   if (sz != 0) w = h = sz;
   pg_num_len = numberOfCharacters(doc->getNumPages());
   for (pg = firstPage; pg <= lastPage; ++pg) {
@@ -414,13 +490,58 @@ int main(int argc, char *argv[]) {
         ppmFile = new char[strlen(ppmRoot) + 1 + pg_num_len + 1 + strlen(ext) + 1];
         sprintf(ppmFile, "%s-%0*d.%s", ppmRoot, pg_num_len, pg, ext);
       }
-      savePageSlice(doc, splashOut, pg, x, y, w, h, pg_w, pg_h, ppmFile);
-      delete[] ppmFile;
     } else {
-      savePageSlice(doc, splashOut, pg, x, y, w, h, pg_w, pg_h, NULL);
+      ppmFile = NULL;
     }
+#ifndef UTILS_USE_THREADS
+    // process job in main thread
+    savePageSlice(doc, splashOut, pg, x, y, w, h, pg_w, pg_h, ppmFile);
+    
+    delete[] ppmFile;
+#else
+    
+    // queue job for worker threads
+    PageJob pageJob = {
+      .doc = doc,
+      .pg = pg,
+      
+      .x = x, .y = y, .w = w, .h = h,
+      .pg_w = pg_w, .pg_h = pg_h,
+      
+      .paperColor = &paperColor,
+      
+      .pg_num_len = pg_num_len,
+      .ppmFile = ppmFile
+    };
+    
+    pageJobQueue.push_back(pageJob);
+    
+#endif // UTILS_USE_THREADS
   }
+#ifndef UTILS_USE_THREADS
   delete splashOut;
+#else
+  
+  // spawn worker threads and wait on them
+  jobs = (pthread_t*)malloc(numberOfJobs * sizeof(pthread_t));
+
+  for(int i=0; i < numberOfJobs; ++i) {
+    if(pthread_create(&jobs[i], NULL, (void* (*)(void*))processPageJobs, NULL) != 0) {
+	    fprintf(stderr, "pthread_create() failed with errno: %d\n", errno);
+	    exit(EXIT_FAILURE);
+    }
+  }
+  
+  for(int i=0; i < numberOfJobs; ++i) {
+    if(pthread_join(jobs[i], NULL) != 0) {
+      fprintf(stderr, "pthread_join() failed with errno: %d\n", errno);
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  free(jobs);
+  
+#endif // UTILS_USE_THREADS
 
   exitCode = 0;
 
-- 
1.8.2


>From 6cb2b27f05b95e3f81a565d12bd095a6142617be Mon Sep 17 00:00:00 2001
From: Adam Reichold <[email protected]>
Date: Fri, 5 Apr 2013 21:41:36 +0200
Subject: [PATCH 2/2] tidy the threading in pdftoppm up a bit

---
 utils/pdftoppm.cc | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc
index 54d8a7c..c92579f 100644
--- a/utils/pdftoppm.cc
+++ b/utils/pdftoppm.cc
@@ -246,12 +246,9 @@ struct PageJob {
   PDFDoc *doc;
   int pg;
   
-  int x,y,w,h;
   double pg_w, pg_h;
-  
   SplashColor* paperColor;
   
-  int pg_num_len;
   char *ppmFile;
 };
 
@@ -282,7 +279,7 @@ static void processPageJobs() {
 		              splashModeRGB8, 4, gFalse, *pageJob.paperColor);
     splashOut->startDoc(pageJob.doc);
     
-    savePageSlice(pageJob.doc, splashOut, pageJob.pg, pageJob.x, pageJob.y, pageJob.w, pageJob.h, pageJob.pg_w, pageJob.pg_h, pageJob.ppmFile);
+    savePageSlice(pageJob.doc, splashOut, pageJob.pg, x, y, w, h, pageJob.pg_w, pageJob.pg_h, pageJob.ppmFile);
     
     delete splashOut;
     delete[] pageJob.ppmFile;
@@ -310,14 +307,15 @@ int main(int argc, char *argv[]) {
   char *ppmFile;
   GooString *ownerPW, *userPW;
   SplashColor paperColor;
+#ifndef UTILS_USE_THREADS
   SplashOutputDev *splashOut;
+#else
+  pthread_t* jobs;
+#endif // UTILS_USE_THREADS
   GBool ok;
   int exitCode;
   int pg, pg_num_len;
   double pg_w, pg_h, tmp;
-#ifdef UTILS_USE_THREADS
-  pthread_t* jobs;
-#endif // UTILS_USE_THREADS
 
   exitCode = 99;
 
@@ -442,8 +440,6 @@ int main(int argc, char *argv[]) {
 				  gFalse, paperColor);
   splashOut->startDoc(doc);
 
-#else
-  (void)splashOut; // silence warning about unused variable
 #endif // UTILS_USE_THREADS
   
   if (sz != 0) w = h = sz;
@@ -505,12 +501,9 @@ int main(int argc, char *argv[]) {
       .doc = doc,
       .pg = pg,
 
-      .x = x, .y = y, .w = w, .h = h,
       .pg_w = pg_w, .pg_h = pg_h,      
-      
       .paperColor = &paperColor,
       
-      .pg_num_len = pg_num_len,
       .ppmFile = ppmFile
     };
     
-- 
1.8.2

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to