diff options
-rw-r--r-- | comphelper/source/misc/threadpool.cxx | 149 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/sceneprimitive2d.cxx | 9 | ||||
-rw-r--r-- | include/comphelper/threadpool.hxx | 19 | ||||
-rw-r--r-- | package/inc/ZipOutputStream.hxx | 4 | ||||
-rw-r--r-- | package/source/zipapi/ZipOutputStream.cxx | 6 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackageStream.cxx | 7 | ||||
-rw-r--r-- | sc/source/filter/excel/xetable.cxx | 9 | ||||
-rw-r--r-- | sc/source/filter/oox/workbookfragment.cxx | 76 | ||||
-rw-r--r-- | sw/source/core/ole/ndole.cxx | 59 | ||||
-rw-r--r-- | vcl/source/bitmap/bitmapscalesuper.cxx | 8 |
10 files changed, 224 insertions, 122 deletions
diff --git a/comphelper/source/misc/threadpool.cxx b/comphelper/source/misc/threadpool.cxx index 8680e00e6e34..32170a1a0cd1 100644 --- a/comphelper/source/misc/threadpool.cxx +++ b/comphelper/source/misc/threadpool.cxx @@ -9,6 +9,7 @@ #include <comphelper/threadpool.hxx> +#include <com/sun/star/uno/Exception.hpp> #include <rtl/instance.hxx> #include <rtl/string.hxx> #include <algorithm> @@ -17,6 +18,26 @@ namespace comphelper { +/** prevent waiting for a task from inside a task */ +#if defined DBG_UTIL && defined LINUX +static thread_local bool gbIsWorkerThread; +#endif + +// used to group thread-tasks for waiting in waitTillDone() +class COMPHELPER_DLLPUBLIC ThreadTaskTag +{ + oslInterlockedCount mnTasksWorking; + osl::Condition maTasksComplete; + +public: + ThreadTaskTag(); + bool isDone(); + void waitUntilDone(); + void onTaskWorkerDone(); + void onTaskPushed(); +}; + + class ThreadPool::ThreadWorker : public salhelper::Thread { ThreadPool *mpPool; @@ -33,11 +54,36 @@ public: virtual void execute() override { +#if defined DBG_UTIL && defined LINUX + gbIsWorkerThread = true; +#endif ThreadTask *pTask; while ( ( pTask = waitForWork() ) ) { - pTask->doWork(); - delete pTask; + std::shared_ptr<ThreadTaskTag> pTag(pTask->getTag()); + try { + pTask->doWork(); + } + catch (const std::exception &e) + { + SAL_WARN("comphelper", "exception in thread worker while calling doWork(): " << e.what()); + } + catch (const css::uno::Exception &e) + { + SAL_WARN("comphelper", "exception in thread worker while calling doWork(): " << e.Message); + } + try { + delete pTask; + } + catch (const std::exception &e) + { + SAL_WARN("comphelper", "exception in thread worker while deleting task: " << e.what()); + } + catch (const css::uno::Exception &e) + { + SAL_WARN("comphelper", "exception in thread worker while deleting task: " << e.Message); + } + pTag->onTaskWorkerDone(); } } @@ -149,9 +195,27 @@ sal_Int32 ThreadPool::getPreferredConcurrency() void ThreadPool::waitAndCleanupWorkers() { - waitUntilEmpty(); - osl::ResettableMutexGuard aGuard( maGuard ); + + if( maWorkers.empty() ) + { // no threads at all -> execute the work in-line + ThreadTask *pTask; + while ( ( pTask = popWork() ) ) + { + std::shared_ptr<ThreadTaskTag> pTag(pTask->getTag()); + pTask->doWork(); + delete pTask; + pTag->onTaskWorkerDone(); + } + } + else + { + aGuard.clear(); + maTasksComplete.wait(); + aGuard.reset(); + } + assert( maTasks.empty() ); + mbTerminate = true; while( !maWorkers.empty() ) @@ -173,6 +237,7 @@ void ThreadPool::waitAndCleanupWorkers() void ThreadPool::pushTask( ThreadTask *pTask ) { osl::MutexGuard aGuard( maGuard ); + pTask->mpTag->onTaskPushed(); maTasks.insert( maTasks.begin(), pTask ); // horrible beyond belief: @@ -205,8 +270,11 @@ void ThreadPool::stopWork() maTasksComplete.set(); } -void ThreadPool::waitUntilEmpty() +void ThreadPool::waitUntilDone(const std::shared_ptr<ThreadTaskTag>& rTag) { +#if defined DBG_UTIL && defined LINUX + assert(!gbIsWorkerThread && "cannot wait for tasks from inside a task"); +#endif osl::ResettableMutexGuard aGuard( maGuard ); if( maWorkers.empty() ) @@ -214,17 +282,78 @@ void ThreadPool::waitUntilEmpty() ThreadTask *pTask; while ( ( pTask = popWork() ) ) { + std::shared_ptr<ThreadTaskTag> pTag(pTask->getTag()); pTask->doWork(); delete pTask; + pTag->onTaskWorkerDone(); } } - else + aGuard.clear(); + rTag->waitUntilDone(); +} + +std::shared_ptr<ThreadTaskTag> ThreadPool::createThreadTaskTag() +{ + return std::make_shared<ThreadTaskTag>(); +} + +bool ThreadPool::isTaskTagDone(const std::shared_ptr<ThreadTaskTag>& pTag) +{ + return pTag->isDone(); +} + + +ThreadTask::ThreadTask(const std::shared_ptr<ThreadTaskTag>& pTag) + : mpTag(pTag) +{ +} + +ThreadTaskTag::ThreadTaskTag() : mnTasksWorking(0) +{ + maTasksComplete.set(); +} + +void ThreadTaskTag::onTaskPushed() +{ + oslInterlockedCount n = osl_atomic_increment(&mnTasksWorking); + assert( n < 65536 ); // sanity checking + (void)n; // avoid -Wunused-variable in release build + maTasksComplete.reset(); +} + +void ThreadTaskTag::onTaskWorkerDone() +{ + sal_Int32 nCount = osl_atomic_decrement(&mnTasksWorking); + assert(nCount >= 0); + if (nCount == 0) + maTasksComplete.set(); +} + +void ThreadTaskTag::waitUntilDone() +{ +#if defined DBG_UTIL && defined LINUX + assert(!gbIsWorkerThread && "cannot wait for tasks from inside a task"); +#endif + +#ifdef DBG_UTIL + // 2 minute timeout in debug mode so our tests fail sooner rather than later + osl::Condition::Result rv = maTasksComplete.wait(TimeValue { 2*60, 0 }); + assert(rv != osl_cond_result_timeout); +#else + // 10 minute timeout in production so the app eventually throws some kind of error + if (maTasksComplete.wait(TimeValue { 10*60, 0 }) == osl_cond_result_timeout) { - aGuard.clear(); - maTasksComplete.wait(); - aGuard.reset(); + SAL_DEBUG_TRACE("comphelper::ThreadTaskTag::waitUntilDone() " + << "tasksWorking " << mnTasksWorking + << "noThreads " << ThreadPool::getPreferredConcurrency()); + throw std::runtime_error("timeout waiting for threadpool tasks"); } - assert( maTasks.empty() ); +#endif +} + +bool ThreadTaskTag::isDone() +{ + return mnTasksWorking == 0; } } // namespace comphelper diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx index 68acb57ff5d6..b87df2739280 100644 --- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx @@ -400,9 +400,11 @@ namespace drawinglayer public: explicit Executor( + std::shared_ptr<comphelper::ThreadTaskTag>& rTag, processor3d::ZBufferProcessor3D* pZBufferProcessor3D, const primitive3d::Primitive3DContainer& rChildren3D) - : mpZBufferProcessor3D(pZBufferProcessor3D), + : comphelper::ThreadTask(rTag), + mpZBufferProcessor3D(pZBufferProcessor3D), mrChildren3D(rChildren3D) { } @@ -417,6 +419,7 @@ namespace drawinglayer std::vector< processor3d::ZBufferProcessor3D* > aProcessors; const sal_uInt32 nLinesPerThread(aBZPixelRaster.getHeight() / nThreadCount); + std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag(); for(sal_Int32 a(0); a < nThreadCount; a++) { @@ -432,11 +435,11 @@ namespace drawinglayer nLinesPerThread * a, a + 1 == nThreadCount ? aBZPixelRaster.getHeight() : nLinesPerThread * (a + 1)); aProcessors.push_back(pNewZBufferProcessor3D); - Executor* pExecutor = new Executor(pNewZBufferProcessor3D, getChildren3D()); + Executor* pExecutor = new Executor(aTag, pNewZBufferProcessor3D, getChildren3D()); rThreadPool.pushTask(pExecutor); } - rThreadPool.waitUntilEmpty(); + rThreadPool.waitUntilDone(aTag); } else { diff --git a/include/comphelper/threadpool.hxx b/include/comphelper/threadpool.hxx index 2f726f0b406f..93f6b59ee9de 100644 --- a/include/comphelper/threadpool.hxx +++ b/include/comphelper/threadpool.hxx @@ -15,17 +15,24 @@ #include <osl/mutex.hxx> #include <osl/conditn.hxx> #include <rtl/ref.hxx> -#include <vector> #include <comphelper/comphelperdllapi.h> +#include <vector> +#include <memory> namespace comphelper { +class ThreadTaskTag; +class ThreadPool; class COMPHELPER_DLLPUBLIC ThreadTask { +friend class ThreadPool; + std::shared_ptr<ThreadTaskTag> mpTag; public: + ThreadTask(const std::shared_ptr<ThreadTaskTag>& pTag); virtual ~ThreadTask() {} virtual void doWork() = 0; + const std::shared_ptr<ThreadTaskTag>& getTag() { return mpTag; } }; /// A very basic thread pool implementation @@ -36,20 +43,24 @@ public: /// count for the CPU static ThreadPool& getSharedOptimalPool(); + static std::shared_ptr<ThreadTaskTag> createThreadTaskTag(); + + static bool isTaskTagDone(const std::shared_ptr<ThreadTaskTag>&); + /// returns a configurable max-concurrency /// limit to avoid spawning an unnecessarily /// large number of threads on high-core boxes. /// MAX_CONCURRENCY envar controls the cap. static sal_Int32 getPreferredConcurrency(); - ThreadPool( sal_Int32 nWorkers ); + 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(); + /// wait until all queued tasks associated with the tag are completed + void waitUntilDone(const std::shared_ptr<ThreadTaskTag>&); /// return the number of live worker threads sal_Int32 getWorkerCount() const { return maWorkers.size(); } diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx index 136bc72b249d..1fc41661d186 100644 --- a/package/inc/ZipOutputStream.hxx +++ b/package/inc/ZipOutputStream.hxx @@ -35,10 +35,10 @@ class ZipOutputStream { css::uno::Reference< css::io::XOutputStream > m_xStream; ::std::vector < ZipEntry * > m_aZipList; + std::shared_ptr<comphelper::ThreadTaskTag> mpThreadTaskTag; ByteChucker m_aChucker; ZipEntry *m_pCurrentEntry; - comphelper::ThreadPool &m_rSharedThreadPool; std::vector< ZipOutputEntry* > m_aEntries; ::css::uno::Any m_aDeflateException; @@ -80,6 +80,8 @@ public: void reduceScheduledThreadsToGivenNumberOrLess( sal_Int32 nThreads, sal_Int32 nWaitTimeInTenthSeconds); + + const std::shared_ptr<comphelper::ThreadTaskTag>& getThreadTaskTag() { return mpThreadTaskTag; } }; #endif diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx index 41f78b414879..7e9ffe5bfc1a 100644 --- a/package/source/zipapi/ZipOutputStream.cxx +++ b/package/source/zipapi/ZipOutputStream.cxx @@ -42,9 +42,9 @@ using namespace com::sun::star::packages::zip::ZipConstants; */ ZipOutputStream::ZipOutputStream( const uno::Reference < io::XOutputStream > &xOStream ) : m_xStream(xOStream) +, mpThreadTaskTag( comphelper::ThreadPool::createThreadTaskTag() ) , m_aChucker(xOStream) , m_pCurrentEntry(nullptr) -, m_rSharedThreadPool(comphelper::ThreadPool::getSharedOptimalPool()) { } @@ -70,7 +70,7 @@ void ZipOutputStream::setEntry( ZipEntry *pEntry ) void ZipOutputStream::addDeflatingThread( ZipOutputEntry *pEntry, comphelper::ThreadTask *pThread ) { - m_rSharedThreadPool.pushTask(pThread); + comphelper::ThreadPool::getSharedOptimalPool().pushTask(pThread); m_aEntries.push_back(pEntry); } @@ -178,7 +178,7 @@ void ZipOutputStream::finish() assert(!m_aZipList.empty() && "Zip file must have at least one entry!"); // Wait for all threads to finish & write - m_rSharedThreadPool.waitUntilEmpty(); + comphelper::ThreadPool::getSharedOptimalPool().waitUntilDone(mpThreadTaskTag); // consume all processed entries consumeAllScheduledThreadEntries(); diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx index 5efb145fd9f7..e72c3999c9f5 100644 --- a/package/source/zippackage/ZipPackageStream.cxx +++ b/package/source/zippackage/ZipPackageStream.cxx @@ -466,9 +466,10 @@ class DeflateThread: public comphelper::ThreadTask uno::Reference< io::XInputStream > mxInStream; public: - DeflateThread( ZipOutputEntry *pEntry, + DeflateThread( const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, ZipOutputEntry *pEntry, const uno::Reference< io::XInputStream >& xInStream ) - : mpEntry(pEntry) + : comphelper::ThreadTask(pTag) + , mpEntry(pEntry) , mxInStream(xInStream) {} @@ -849,7 +850,7 @@ bool ZipPackageStream::saveChild( // Start a new thread deflating this zip entry ZipOutputEntry *pZipEntry = new ZipOutputEntry( m_xContext, *pTempEntry, this, bToBeEncrypted); - rZipOut.addDeflatingThread( pZipEntry, new DeflateThread(pZipEntry, xStream) ); + rZipOut.addDeflatingThread( pZipEntry, new DeflateThread(rZipOut.getThreadTaskTag(), pZipEntry, xStream) ); } else { diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index 29f636ed75e0..f7cba244e577 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -2116,8 +2116,10 @@ class RowFinalizeTask : public comphelper::ThreadTask const ScfUInt16Vec& mrColXFIndexes; std::vector< XclExpRow * > maRows; public: - RowFinalizeTask( const ScfUInt16Vec& rColXFIndexes, + RowFinalizeTask( const std::shared_ptr<comphelper::ThreadTaskTag> pTag, + const ScfUInt16Vec& rColXFIndexes, bool bProgress ) : + comphelper::ThreadTask( pTag ), mbProgress( bProgress ), mrColXFIndexes( rColXFIndexes ) {} virtual ~RowFinalizeTask() {} @@ -2152,9 +2154,10 @@ void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt else { comphelper::ThreadPool &rPool = comphelper::ThreadPool::getSharedOptimalPool(); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); std::vector<RowFinalizeTask*> aTasks(nThreads, nullptr); for ( size_t i = 0; i < nThreads; i++ ) - aTasks[ i ] = new RowFinalizeTask( rColXFIndexes, i == 0 ); + aTasks[ i ] = new RowFinalizeTask( pTag, rColXFIndexes, i == 0 ); RowMap::iterator itr, itrBeg = maRowMap.begin(), itrEnd = maRowMap.end(); size_t nIdx = 0; @@ -2167,7 +2170,7 @@ void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt // Progress bar updates must be synchronous to avoid deadlock aTasks[0]->doWork(); - rPool.waitUntilEmpty(); + rPool.waitUntilDone(pTag); } // *** Default row format *** --------------------------------------------- diff --git a/sc/source/filter/oox/workbookfragment.cxx b/sc/source/filter/oox/workbookfragment.cxx index 6e6e101f0c48..88f694853e0a 100644 --- a/sc/source/filter/oox/workbookfragment.cxx +++ b/sc/source/filter/oox/workbookfragment.cxx @@ -225,9 +225,11 @@ class WorkerThread : public comphelper::ThreadTask rtl::Reference<FragmentHandler> mxHandler; public: - WorkerThread( WorkbookFragment& rWorkbookHandler, + WorkerThread( const std::shared_ptr<comphelper::ThreadTaskTag> pTag, + WorkbookFragment& rWorkbookHandler, const rtl::Reference<FragmentHandler>& xHandler, sal_Int32 &rSheetsLeft ) : + comphelper::ThreadTask( pTag ), mrSheetsLeft( rSheetsLeft ), mrWorkbookHandler( rWorkbookHandler ), mxHandler( xHandler ) @@ -309,54 +311,38 @@ public: void importSheetFragments( WorkbookFragment& rWorkbookHandler, SheetFragmentVector& rSheets ) { - sal_Int32 nThreads = std::min( rSheets.size(), (size_t) comphelper::ThreadPool::getPreferredConcurrency() ); - Reference< XComponentContext > xContext = comphelper::getProcessComponentContext(); - const char *pEnv; - if( ( pEnv = getenv( "SC_IMPORT_THREADS" ) ) ) - nThreads = rtl_str_toInt32( pEnv, 10 ); - - if( nThreads != 0 ) - { - // test sequential read in this mode - if( nThreads < 0) - nThreads = 0; - comphelper::ThreadPool aPool( nThreads ); - - sal_Int32 nSheetsLeft = 0; - ProgressBarTimer aProgressUpdater; - SheetFragmentVector::iterator it = rSheets.begin(), itEnd = rSheets.end(); - for( ; it != itEnd; ++it ) - { - // getting at the WorksheetGlobals is rather unpleasant - IWorksheetProgress *pProgress = WorksheetHelper::getWorksheetInterface( it->first ); - pProgress->setCustomRowProgress( - aProgressUpdater.wrapProgress( - pProgress->getRowProgress() ) ); - aPool.pushTask( new WorkerThread( rWorkbookHandler, it->second, - /* ref */ nSheetsLeft ) ); - nSheetsLeft++; - } - - // coverity[loop_top] - this isn't an infinite loop where nSheetsLeft gets decremented by the above threads - while( nSheetsLeft > 0) - { - // This is a much more controlled re-enterancy hazard than - // allowing a yield deeper inside the filter code for progress - // bar updating. - Application::Yield(); - } - aPool.waitUntilEmpty(); + // test sequential read in this mode + comphelper::ThreadPool &rSharedPool = comphelper::ThreadPool::getSharedOptimalPool(); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); - // threads joined in ThreadPool destructor - } - else // single threaded iteration + sal_Int32 nSheetsLeft = 0; + ProgressBarTimer aProgressUpdater; + SheetFragmentVector::iterator it = rSheets.begin(), itEnd = rSheets.end(); + for( ; it != itEnd; ++it ) { - SheetFragmentVector::iterator it = rSheets.begin(), itEnd = rSheets.end(); - for( ; it != itEnd; ++it ) - rWorkbookHandler.importOoxFragment( it->second ); - } + // getting at the WorksheetGlobals is rather unpleasant + IWorksheetProgress *pProgress = WorksheetHelper::getWorksheetInterface( it->first ); + pProgress->setCustomRowProgress( + aProgressUpdater.wrapProgress( + pProgress->getRowProgress() ) ); + rSharedPool.pushTask( new WorkerThread( pTag, rWorkbookHandler, it->second, + /* ref */ nSheetsLeft ) ); + nSheetsLeft++; + } + + // coverity[loop_top] - this isn't an infinite loop where nSheetsLeft gets decremented by the above threads + while( nSheetsLeft > 0) + { + // This is a much more controlled re-enterancy hazard than + // allowing a yield deeper inside the filter code for progress + // bar updating. + Application::Yield(); + } + rSharedPool.waitUntilDone(pTag); + + // threads joined in ThreadPool destructor } } diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx index 9863cc93f5a8..416089205b48 100644 --- a/sw/source/core/ole/ndole.cxx +++ b/sw/source/core/ole/ndole.cxx @@ -643,38 +643,9 @@ bool SwOLENode::IsChart() const return bIsChart; } -// due to some problems in test cases with the SharedOptimalPool, use -// an own instance of comphelper::ThreadPool. Problem is that other -// usages of getSharedOptimalPool() may interfere if more than one -// pool user calls waitUntilEmpty(). -// -// It gets created on-demand and will be available during LO's -// lifetime for loading chart models used in writer in parallel. It -// would be possible to add a usage count, then trigger a timer and -// clean it up (due to lifetime issues), but that's probably overkill. -// It gets created on demand, is ready for global reuse and makes no -// harm (not much ressources needed) -static comphelper::ThreadPool* pLocalPool = nullptr; - -comphelper::ThreadPool* getLocalThreadPool() -{ - if (pLocalPool) - { - return pLocalPool; - } - - if (0 == comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount()) - { - return nullptr; - } - - pLocalPool = new comphelper::ThreadPool(comphelper::ThreadPool::getSharedOptimalPool().getWorkerCount()); - return pLocalPool; -} - namespace { class DeflateThread; } -/// Holder for local data for a parallely-executed task to load a chart model +/// Holder for local data for a parallel-executed task to load a chart model class DeflateData { private: @@ -685,21 +656,20 @@ private: drawinglayer::primitive2d::Primitive2DContainer maPrimitive2DSequence; basegfx::B2DRange maRange; - // set from the WorkerThread when done - std::atomic< bool> mbFinished; - // evtl.set from the SwOLEObj destructor when a WorkerThread is still active // since it is not possible to kill it - let it terminate and delete the // data working on itself std::atomic< bool> mbKilled; + std::shared_ptr<comphelper::ThreadTaskTag> mpTag; + public: DeflateData(const uno::Reference< frame::XModel >& rXModel) : maXModel(rXModel), maPrimitive2DSequence(), maRange(), - mbFinished(false), - mbKilled(false) + mbKilled(false), + mpTag( comphelper::ThreadPool::createThreadTaskTag() ) { } @@ -715,12 +685,12 @@ public: bool isFinished() const { - return mbFinished; + return comphelper::ThreadPool::isTaskTagDone(mpTag); } void waitFinished() { - while(!mbFinished && !mbKilled) + while(!isFinished() && !mbKilled) { // need to wait until the load in progress is finished. // to do so, Application::Yield() is needed since the execution @@ -729,6 +699,7 @@ public: // the running import Application::Yield(); } + comphelper::ThreadPool::getSharedOptimalPool().waitUntilDone(mpTag); } }; @@ -742,7 +713,7 @@ class DeflateThread : public comphelper::ThreadTask public: DeflateThread(DeflateData& rDeflateData) - : mrDeflateData(rDeflateData) + : comphelper::ThreadTask(rDeflateData.mpTag), mrDeflateData(rDeflateData) { } @@ -758,7 +729,6 @@ private: // model no longer needed and done mrDeflateData.maXModel.clear(); - mrDeflateData.mbFinished = true; } catch (const uno::Exception&) { @@ -1081,16 +1051,11 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs if(aXModel.is()) { - // loaded using own instance of comphelper::ThreadPool, - // see getLocalThreadPool(). Disable via bool below if - // trouble surfaces somewhere - // disabled fro now, need to check deeper - static bool bAnynchronousLoadingAllowed = false; + static bool bAsynchronousLoadingAllowed = false; if(bSynchron || - !bAnynchronousLoadingAllowed || - nullptr == getLocalThreadPool()) + !bAsynchronousLoadingAllowed) { // load chart synchron in this Thread m_aPrimitive2DSequence = ChartHelper::tryToGetChartContentAsPrimitive2DSequence( @@ -1106,7 +1071,7 @@ drawinglayer::primitive2d::Primitive2DContainer SwOLEObj::tryToGetChartContentAs { m_pDeflateData = new DeflateData(aXModel); DeflateThread* pNew = new DeflateThread(*m_pDeflateData); - getLocalThreadPool()->pushTask(pNew); + comphelper::ThreadPool::getSharedOptimalPool().pushTask(pNew); } } } diff --git a/vcl/source/bitmap/bitmapscalesuper.cxx b/vcl/source/bitmap/bitmapscalesuper.cxx index 9fb1f44a0f9c..ff01aaebdab5 100644 --- a/vcl/source/bitmap/bitmapscalesuper.cxx +++ b/vcl/source/bitmap/bitmapscalesuper.cxx @@ -89,7 +89,8 @@ class ScaleTask : public comphelper::ThreadTask ScaleRangeFn mpFn; std::vector< ScaleRangeContext > maStrips; public: - explicit ScaleTask( ScaleRangeFn pFn ) : mpFn( pFn ) {} + explicit ScaleTask( const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, ScaleRangeFn pFn ) + : comphelper::ThreadTask(pTag), mpFn( pFn ) {} void push( ScaleRangeContext &aRC ) { maStrips.push_back( aRC ); } virtual void doWork() override { @@ -1000,6 +1001,7 @@ bool BitmapScaleSuper::filter(Bitmap& rBitmap) { // partition and queue work comphelper::ThreadPool &rShared = comphelper::ThreadPool::getSharedOptimalPool(); + std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag(); sal_uInt32 nThreads = rShared.getWorkerCount(); assert( nThreads > 0 ); sal_uInt32 nStrips = ((nEndY - nStartY) + SCALE_THREAD_STRIP - 1) / SCALE_THREAD_STRIP; @@ -1008,7 +1010,7 @@ bool BitmapScaleSuper::filter(Bitmap& rBitmap) long nStripY = nStartY; for ( sal_uInt32 t = 0; t < nThreads - 1; t++ ) { - ScaleTask *pTask = new ScaleTask( pScaleRangeFn ); + ScaleTask *pTask = new ScaleTask( pTag, pScaleRangeFn ); for ( sal_uInt32 j = 0; j < nStripsPerThread; j++ ) { ScaleRangeContext aRC( &aContext, nStripY ); @@ -1020,7 +1022,7 @@ bool BitmapScaleSuper::filter(Bitmap& rBitmap) // finish any remaining bits here pScaleRangeFn( aContext, nStripY, nEndY ); - rShared.waitUntilEmpty(); + rShared.waitUntilDone(pTag); SAL_INFO("vcl.gdi", "All threaded scaling tasks complete"); } |