[Libreoffice-commits] core.git: Branch 'feature/perfwork4' - 3 commits - comphelper/Library_comphelper.mk comphelper/source include/comphelper sc/Library_scfilt.mk sc/source vcl/source

Michael Meeks michael.meeks at collabora.com
Thu Oct 30 15:16:42 PDT 2014


 comphelper/Library_comphelper.mk          |    1 
 comphelper/source/misc/threadpool.cxx     |  182 ++++++++++++++++++++++++++++++
 include/comphelper/threadpool.hxx         |   72 +++++++++++
 sc/Library_scfilt.mk                      |    1 
 sc/source/filter/oox/threadpool.cxx       |  164 ---------------------------
 sc/source/filter/oox/threadpool.hxx       |   53 --------
 sc/source/filter/oox/workbookfragment.cxx |   11 -
 vcl/source/bitmap/bitmapscalesuper.cxx    |   32 +----
 8 files changed, 273 insertions(+), 243 deletions(-)

New commits:
commit bc483c75571d7a46ab003857200cea8af91bedc7
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Thu Oct 30 22:17:04 2014 +0000

    Switch image scaling to use the shared thread pool.
    
    Change-Id: I7450e10b329247d972ef048f61b8ce1ca943aca8

diff --git a/include/comphelper/threadpool.hxx b/include/comphelper/threadpool.hxx
index 2e51719..1b49f87 100644
--- a/include/comphelper/threadpool.hxx
+++ b/include/comphelper/threadpool.hxx
@@ -45,6 +45,9 @@ public:
     /// wait until all queued tasks are completed
     void        waitUntilEmpty();
 
+    /// return the number of live worker threads
+    sal_Int32   getWorkerCount() { return maWorkers.size(); }
+
 private:
     class ThreadWorker;
     friend class ThreadWorker;
diff --git a/vcl/source/bitmap/bitmapscalesuper.cxx b/vcl/source/bitmap/bitmapscalesuper.cxx
index 4e734c4..2c01709 100644
--- a/vcl/source/bitmap/bitmapscalesuper.cxx
+++ b/vcl/source/bitmap/bitmapscalesuper.cxx
@@ -21,9 +21,8 @@
 #include <vcl/bitmapscalesuper.hxx>
 
 #include <algorithm>
-#include <thread>
-#include <osl/thread.hxx>
 #include <boost/scoped_array.hpp>
+#include <comphelper/threadpool.hxx>
 
 namespace {
 
@@ -85,15 +84,14 @@ struct ScaleRangeContext {
 
 typedef void (*ScaleRangeFn)(ScaleContext &rCtx, long nStartY, long nEndY);
 
-// FIXME: should really be pooled & managed intelligently etc.
-class ScaleThread : public osl::Thread
+class ScaleTask : public comphelper::ThreadTask
 {
     ScaleRangeFn mpFn;
     std::vector< ScaleRangeContext > maStrips;
 public:
-    ScaleThread( ScaleRangeFn pFn ) : mpFn( pFn ) {}
+    ScaleTask( ScaleRangeFn pFn ) : mpFn( pFn ) {}
     void push( ScaleRangeContext &aRC ) { maStrips.push_back( aRC ); }
-    virtual void SAL_CALL run() SAL_OVERRIDE
+    virtual void doWork() SAL_OVERRIDE
     {
         std::vector< ScaleRangeContext >::iterator it;
         for (it = maStrips.begin(); it != maStrips.end(); ++it)
@@ -1001,35 +999,29 @@ bool BitmapScaleSuper::filter(Bitmap& rBitmap)
         else
         {
             // partition and queue work
-            sal_uInt32 nThreads = std::max(std::thread::hardware_concurrency(), 1U);
+            comphelper::ThreadPool &rShared = comphelper::ThreadPool::getSharedOptimalPool();
+            sal_uInt32 nThreads = rShared.getWorkerCount();
+            assert( nThreads > 0 );
             sal_uInt32 nStrips = ((nEndY - nStartY) + SCALE_THREAD_STRIP - 1) / SCALE_THREAD_STRIP;
             sal_uInt32 nStripsPerThread = nStrips / nThreads;
             SAL_INFO("vcl.gdi", "Scale in " << nStrips << " strips " << nStripsPerThread << " per thread" << " we have " << nThreads << " CPU threads ");
             long nStripY = nStartY;
-            std::vector<ScaleThread *> aThreads;
             for ( sal_uInt32 t = 0; t < nThreads - 1; t++ )
             {
-                ScaleThread *pThread = new ScaleThread( pScaleRangeFn );
+                ScaleTask *pTask = new ScaleTask( pScaleRangeFn );
                 for ( sal_uInt32 j = 0; j < nStripsPerThread; j++ )
                 {
                     ScaleRangeContext aRC( aContext, nStripY );
-                    pThread->push( aRC );
+                    pTask->push( aRC );
                     nStripY += SCALE_THREAD_STRIP;
                 }
-                pThread->create(); // set it running
-                aThreads.push_back( pThread );
+                rShared.pushTask( pTask );
             }
             // finish any remaining bits here
             pScaleRangeFn( aContext, nStripY, nEndY );
 
-            // join threads...
-            for ( std::vector<ScaleThread *>::iterator it = aThreads.begin();
-                  it != aThreads.end(); ++it )
-            {
-                (*it)->join();
-                delete *it;
-            }
-            SAL_INFO("vcl.gdi", "Joined all scaling threads");
+            rShared.waitUntilEmpty();
+            SAL_INFO("vcl.gdi", "All threaded scaling tasks complete");
         }
 
         bRet = true;
commit a885c10d845101cb7459a582538d4f1b2557495e
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Thu Oct 30 21:58:36 2014 +0000

    thread-pool: re-work termination semantics to avoid problems.
    
    We want a pre-spun-up, shared thread-pool that doesn't get its
    workers created & joined frequently.
    
    Change-Id: I29081e3a3e3849ca30e63fd080ee3315d99cbe8d

diff --git a/comphelper/source/misc/threadpool.cxx b/comphelper/source/misc/threadpool.cxx
index d2101ad..236a314 100644
--- a/comphelper/source/misc/threadpool.cxx
+++ b/comphelper/source/misc/threadpool.cxx
@@ -92,7 +92,7 @@ ThreadPool::ThreadPool( sal_Int32 nWorkers ) :
 
 ThreadPool::~ThreadPool()
 {
-    waitUntilWorkersDone();
+    waitAndCleanupWorkers();
 }
 
 struct ThreadPoolStatic : public rtl::StaticWithInit< boost::shared_ptr< ThreadPool >,
@@ -109,9 +109,7 @@ ThreadPool& ThreadPool::getSharedOptimalPool()
     return *ThreadPoolStatic::get().get();
 }
 
-/// wait until all the workers have completed and
-/// terminate all threads
-void ThreadPool::waitUntilWorkersDone()
+void ThreadPool::waitAndCleanupWorkers()
 {
     waitUntilEmpty();
 
@@ -169,7 +167,6 @@ void ThreadPool::waitUntilEmpty()
             pTask->doWork();
             delete pTask;
         }
-        mbTerminate = true;
     }
     else
     {
diff --git a/include/comphelper/threadpool.hxx b/include/comphelper/threadpool.hxx
index ae103f1..2e51719 100644
--- a/include/comphelper/threadpool.hxx
+++ b/include/comphelper/threadpool.hxx
@@ -39,14 +39,19 @@ public:
                 ThreadPool( sal_Int32 nWorkers );
     virtual    ~ThreadPool();
 
+    /// push a new task onto the work queue
     void        pushTask( ThreadTask *pTask /* takes ownership */ );
+
+    /// wait until all queued tasks are completed
     void        waitUntilEmpty();
-    void        waitUntilWorkersDone();
 
 private:
     class ThreadWorker;
     friend class ThreadWorker;
 
+    /// wait until all work is completed, then join all threads
+    void        waitAndCleanupWorkers();
+
     ThreadTask *waitForWork( osl::Condition &rNewWork );
     ThreadTask *popWork();
 
diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx
index 7fb04fa..b4945b9 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -333,8 +333,9 @@ void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVect
             // bar updating.
             Application::Yield();
         }
-        // join all the threads:
-        aPool.waitUntilWorkersDone();
+        aPool.waitUntilEmpty();
+
+        // threads joined in ThreadPool destructor
     }
     else // single threaded iteration
     {
commit 2da34cd240fba5abb7de4c2a39a405d33d1b9a1c
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Thu Oct 30 18:37:42 2014 +0000

    Move thread-pool down into comphelper for re-use elsewhere.
    
    Change-Id: Ib27b8b1ccc07ff194035d6c2ef3d45c429e3cea1

diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index cfe48f6..84bf698 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -114,6 +114,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
     comphelper/source/misc/string \
     comphelper/source/misc/synchronousdispatch \
     comphelper/source/misc/syntaxhighlight \
+    comphelper/source/misc/threadpool \
     comphelper/source/misc/types \
     comphelper/source/misc/weak \
     comphelper/source/misc/weakeventlistener \
diff --git a/sc/source/filter/oox/threadpool.cxx b/comphelper/source/misc/threadpool.cxx
similarity index 84%
rename from sc/source/filter/oox/threadpool.cxx
rename to comphelper/source/misc/threadpool.cxx
index 3fcfa75..d2101ad 100644
--- a/sc/source/filter/oox/threadpool.cxx
+++ b/comphelper/source/misc/threadpool.cxx
@@ -7,17 +7,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include "threadpool.hxx"
+#include <comphelper/threadpool.hxx>
 
+#include <rtl/instance.hxx>
+#include <boost/shared_ptr.hpp>
+#include <thread>
 #include <algorithm>
 
+namespace comphelper {
+
 class ThreadPool::ThreadWorker : public salhelper::Thread
 {
     ThreadPool    *mpPool;
     osl::Condition maNewWork;
 public:
     ThreadWorker( ThreadPool *pPool ) :
-        salhelper::Thread("sheet-import-thread-pool"),
+        salhelper::Thread("thread-pool"),
         mpPool( pPool ) {}
 
     virtual void execute() SAL_OVERRIDE
@@ -90,6 +95,20 @@ ThreadPool::~ThreadPool()
     waitUntilWorkersDone();
 }
 
+struct ThreadPoolStatic : public rtl::StaticWithInit< boost::shared_ptr< ThreadPool >,
+                                                      ThreadPoolStatic >
+{
+    boost::shared_ptr< ThreadPool > operator () () {
+        sal_Int32 nThreads = std::max( std::thread::hardware_concurrency(), 1U );
+        return boost::shared_ptr< ThreadPool >( new ThreadPool( nThreads ) );
+    };
+};
+
+ThreadPool& ThreadPool::getSharedOptimalPool()
+{
+    return *ThreadPoolStatic::get().get();
+}
+
 /// wait until all the workers have completed and
 /// terminate all threads
 void ThreadPool::waitUntilWorkersDone()
@@ -161,4 +180,6 @@ void ThreadPool::waitUntilEmpty()
     assert( maTasks.empty() );
 }
 
+} // namespace comphelper
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/threadpool.hxx b/include/comphelper/threadpool.hxx
similarity index 73%
rename from sc/source/filter/oox/threadpool.hxx
rename to include/comphelper/threadpool.hxx
index 19b524c..ae103f1 100644
--- a/sc/source/filter/oox/threadpool.hxx
+++ b/include/comphelper/threadpool.hxx
@@ -7,8 +7,8 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#ifndef INCLUDED_SC_SOURCE_FILTER_OOX_THREADPOOL_HXX
-#define INCLUDED_SC_SOURCE_FILTER_OOX_THREADPOOL_HXX
+#ifndef INCLUDED_COMPHELPER_THREADPOOL_HXX
+#define INCLUDED_COMPHELPER_THREADPOOL_HXX
 
 #include <sal/config.h>
 #include <salhelper/thread.hxx>
@@ -16,8 +16,12 @@
 #include <osl/conditn.hxx>
 #include <rtl/ref.hxx>
 #include <vector>
+#include <comphelper/comphelperdllapi.h>
 
-class ThreadTask
+namespace comphelper
+{
+
+class COMPHELPER_DLLPUBLIC ThreadTask
 {
 public:
     virtual      ~ThreadTask() {}
@@ -25,11 +29,16 @@ public:
 };
 
 /// A very basic thread pool implementation
-class ThreadPool
+class COMPHELPER_DLLPUBLIC ThreadPool
 {
 public:
+    /// returns a pointer to a shared pool with optimal thread
+    /// count for the CPU
+    static      ThreadPool& getSharedOptimalPool();
+
                 ThreadPool( sal_Int32 nWorkers );
     virtual    ~ThreadPool();
+
     void        pushTask( ThreadTask *pTask /* takes ownership */ );
     void        waitUntilEmpty();
     void        waitUntilWorkersDone();
@@ -48,6 +57,8 @@ private:
     std::vector< ThreadTask * >   maTasks;
 };
 
-#endif // INCLUDED_SC_SOURCE_FILTER_OOX_THREADPOOL_HXX
+} // namespace comphelper
+
+#endif // INCLUDED_COMPHELPER_THREADPOOL_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index 00d32da..77c8486 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -214,7 +214,6 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
 	sc/source/filter/oox/tablebuffer \
 	sc/source/filter/oox/tablefragment \
 	sc/source/filter/oox/themebuffer \
-	sc/source/filter/oox/threadpool \
 	sc/source/filter/oox/unitconverter \
 	sc/source/filter/oox/viewsettings \
 	sc/source/filter/oox/workbookfragment \
diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx
index 1ce4376..7fb04fa 100644
--- a/sc/source/filter/oox/workbookfragment.cxx
+++ b/sc/source/filter/oox/workbookfragment.cxx
@@ -46,7 +46,6 @@
 #include "worksheethelper.hxx"
 #include "worksheetfragment.hxx"
 #include "sheetdatacontext.hxx"
-#include "threadpool.hxx"
 #include "officecfg/Office/Common.hxx"
 
 #include "document.hxx"
@@ -58,6 +57,7 @@
 
 #include <oox/core/fastparser.hxx>
 #include <salhelper/thread.hxx>
+#include <comphelper/threadpool.hxx>
 #include <osl/conditn.hxx>
 
 #include <queue>
@@ -205,7 +205,7 @@ namespace {
 typedef std::pair<WorksheetGlobalsRef, FragmentHandlerRef> SheetFragmentHandler;
 typedef std::vector<SheetFragmentHandler> SheetFragmentVector;
 
-class WorkerThread : public ThreadTask
+class WorkerThread : public comphelper::ThreadTask
 {
     sal_Int32 &mrSheetsLeft;
     WorkbookFragment& mrWorkbookHandler;
@@ -309,7 +309,7 @@ void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVect
         // test sequential read in this mode
         if( nThreads < 0)
             nThreads = 0;
-        ThreadPool aPool( nThreads );
+        comphelper::ThreadPool aPool( nThreads );
 
         sal_Int32 nSheetsLeft = 0;
         ProgressBarTimer aProgressUpdater;


More information about the Libreoffice-commits mailing list