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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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; _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
