Kaydet (Commit) d0bd1880 authored tarafından Jan-Marek Glogowski's avatar Jan-Marek Glogowski

Scheduler: add per-priority Task lists

This way we don't have to search the whole list for a higher
priority event, if an immediate Task is found. This probably
helps bugs like tdf#119724 and tdf#119428.

Change-Id: Ic5685193d1bedb6996cf46f0ee2cba42190ff7cc
Reviewed-on: https://gerrit.libreoffice.org/60572
Tested-by: Jenkins
Reviewed-by: 's avatarJan-Marek Glogowski <glogow@fbihome.de>
üst d4f871a8
......@@ -21,6 +21,7 @@
#define INCLUDED_VCL_TASK_HXX
#include <vcl/dllapi.h>
#include <sal/log.hxx>
#include <memory>
class Scheduler;
......@@ -38,6 +39,8 @@ enum class TaskPriority
LOWEST ///< Low, very idle cleanup tasks
};
#define PRIO_COUNT (static_cast<int>(TaskPriority::LOWEST) + 1)
class VCL_DLLPUBLIC Task
{
friend class Scheduler;
......@@ -76,7 +79,7 @@ public:
virtual ~Task() COVERITY_NOEXCEPT_FALSE;
Task& operator=( const Task& rTask );
void SetPriority(TaskPriority ePriority) { mePriority = ePriority; }
inline void SetPriority(TaskPriority ePriority);
TaskPriority GetPriority() const { return mePriority; }
void SetDebugName( const sal_Char *pDebugName ) { mpDebugName = pDebugName; }
......@@ -100,6 +103,13 @@ public:
bool IsStatic() const { return mbStatic; }
};
inline void Task::SetPriority(TaskPriority ePriority)
{
SAL_WARN_IF(mpSchedulerData, "vcl.schedule",
"Priority will just change after next schedule!");
mePriority = ePriority;
}
#endif // INCLUDED_VCL_TASK_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -18,14 +18,15 @@ using namespace sfx2::sidebar;
PanelLayout::PanelLayout(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame)
: Control(pParent)
, m_aPanelLayoutIdle("svx sidebar PanelLayoutIdle")
, m_bInClose(false)
{
SetStyle(GetStyle() | WB_DIALOGCONTROL);
m_pUIBuilder.reset(new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame));
m_aPanelLayoutIdle.SetPriority(TaskPriority::RESIZE);
m_aPanelLayoutIdle.SetInvokeHandler( LINK( this, PanelLayout, ImplHandlePanelLayoutTimerHdl ) );
m_aPanelLayoutIdle.SetDebugName( "svx::PanelLayout m_aPanelLayoutIdle" );
m_aPanelLayoutIdle.SetDebugName("svx::PanelLayout m_aPanelLayoutIdle");
// VclBuilder will trigger resize and start Idle
m_pUIBuilder.reset(new VclBuilder(this, getUIRootDir(), rUIXMLDescription, rID, rFrame));
if (GetSettings().GetStyleSettings().GetAutoMnemonic())
Accelerator::GenerateAutoMnemonicsOnHierarchy(this);
}
......
......@@ -26,6 +26,7 @@
#include <unotools/options.hxx>
#include <vcl/svapp.hxx>
#include <vcl/window.hxx>
#include <vcl/task.hxx>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/i18n/XCharacterClassification.hpp>
......@@ -327,9 +328,10 @@ struct BlendFrameCache
struct ImplSchedulerContext
{
ImplSchedulerData* mpFirstSchedulerData = nullptr; ///< list of all active tasks
ImplSchedulerData* mpLastSchedulerData = nullptr; ///< last item of the mpFirstSchedulerData list
ImplSchedulerData* mpFirstSchedulerData[PRIO_COUNT] = { nullptr, }; ///< list of all active tasks per priority
ImplSchedulerData* mpLastSchedulerData[PRIO_COUNT] = { nullptr, }; ///< last item of each mpFirstSchedulerData list
ImplSchedulerData* mpSchedulerStack = nullptr; ///< stack of invoked tasks
ImplSchedulerData* mpSchedulerStackTop = nullptr; ///< top most stack entry to detect needed rescheduling during pop
SalTimer* mpSalTimer = nullptr; ///< interface to sal event loop / system timer
sal_uInt64 mnTimerStart = 0; ///< start time of the timer
sal_uInt64 mnTimerPeriod = SAL_MAX_UINT64; ///< current timer period
......
......@@ -453,12 +453,13 @@ class IdleSerializer : public Idle
sal_uInt32 const mnPosition;
sal_uInt32 &mrProcesed;
public:
IdleSerializer( const sal_Char *pDebugName,
sal_uInt32 nPosition, sal_uInt32 &rProcesed )
IdleSerializer(const sal_Char *pDebugName, TaskPriority ePrio,
sal_uInt32 nPosition, sal_uInt32 &rProcesed)
: Idle( pDebugName )
, mnPosition( nPosition )
, mrProcesed( rProcesed )
{
SetPriority(ePrio);
Start();
}
virtual void Invoke() override
......@@ -474,10 +475,10 @@ void TimerTest::testPriority()
{
// Start: 1st Idle low, 2nd high
sal_uInt32 nProcessed = 0;
IdleSerializer aLowPrioIdle( "IdleSerializer LowPrio", 2, nProcessed );
aLowPrioIdle.SetPriority( TaskPriority::LOWEST );
IdleSerializer aHighPrioIdle( "IdleSerializer HighPrio", 1, nProcessed );
aHighPrioIdle.SetPriority( TaskPriority::HIGHEST );
IdleSerializer aLowPrioIdle("IdleSerializer LowPrio",
TaskPriority::LOWEST, 2, nProcessed);
IdleSerializer aHighPrioIdle("IdleSerializer HighPrio",
TaskPriority::HIGHEST, 1, nProcessed);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Not all idles processed", sal_uInt32(2), nProcessed );
}
......@@ -485,10 +486,10 @@ void TimerTest::testPriority()
{
// Start: 1st Idle high, 2nd low
sal_uInt32 nProcessed = 0;
IdleSerializer aHighPrioIdle( "IdleSerializer HighPrio", 1, nProcessed );
aHighPrioIdle.SetPriority( TaskPriority::HIGHEST );
IdleSerializer aLowPrioIdle( "IdleSerializer LowPrio", 2, nProcessed );
aLowPrioIdle.SetPriority( TaskPriority::LOWEST );
IdleSerializer aHighPrioIdle("IdleSerializer HighPrio",
TaskPriority::HIGHEST, 1, nProcessed);
IdleSerializer aLowPrioIdle("IdleSerializer LowPrio",
TaskPriority::LOWEST, 2, nProcessed);
Scheduler::ProcessEventsToIdle();
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Not all idles processed", sal_uInt32(2), nProcessed );
}
......
This diff is collapsed.
......@@ -503,21 +503,24 @@ void Scheduler::ProcessEventsToIdle()
// events were processed at some point, but our check can't prevent further
// processing in the main thread, which may add new events, so skip it.
const ImplSVData* pSVData = ImplGetSVData();
if ( !pSVData->mpDefInst->IsMainThread() )
if (!pSVData->mpDefInst->IsMainThread())
return;
const ImplSchedulerData* pSchedulerData = pSVData->maSchedCtx.mpFirstSchedulerData;
while ( pSchedulerData )
for (int nTaskPriority = 0; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
{
if ( pSchedulerData->mpTask && !pSchedulerData->mbInScheduler )
const ImplSchedulerData* pSchedulerData = pSVData->maSchedCtx.mpFirstSchedulerData[nTaskPriority];
while (pSchedulerData)
{
Idle *pIdle = dynamic_cast<Idle*>( pSchedulerData->mpTask );
if ( pIdle && pIdle->IsActive() )
if (pSchedulerData->mpTask && !pSchedulerData->mbInScheduler)
{
SAL_WARN( "vcl.schedule", "Unprocessed Idle: "
<< pIdle << " " << pIdle->GetDebugName() );
Idle *pIdle = dynamic_cast<Idle*>(pSchedulerData->mpTask);
if (pIdle && pIdle->IsActive())
{
SAL_WARN("vcl.schedule", "Unprocessed Idle: "
<< pIdle << " " << pIdle->GetDebugName());
}
}
pSchedulerData = pSchedulerData->mpNext;
}
pSchedulerData = pSchedulerData->mpNext;
}
#endif
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment