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
