2015-01-14 08:29:37 +01:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <vcl/svapp.hxx>
|
|
|
|
#include <vcl/idle.hxx>
|
2015-01-16 13:28:29 +00:00
|
|
|
#include <vcl/timer.hxx>
|
2015-01-14 08:29:37 +01:00
|
|
|
|
|
|
|
#include <svdata.hxx>
|
|
|
|
#include <salinst.hxx>
|
|
|
|
|
|
|
|
struct ImplIdleData
|
|
|
|
{
|
2015-01-20 12:42:43 +00:00
|
|
|
ImplIdleData* mpNext; // Pointer to the next Instance
|
|
|
|
Idle* mpIdle; // Pointer to VCL Idle instance
|
|
|
|
bool mbDelete; // Was Idle deleted during Update()?
|
2015-01-14 08:29:37 +01:00
|
|
|
bool mbInIdle; // Are we in a idle handler?
|
|
|
|
|
|
|
|
void Invoke()
|
|
|
|
{
|
|
|
|
if (mbDelete || mbInIdle )
|
|
|
|
return;
|
|
|
|
|
2015-01-16 13:28:29 +00:00
|
|
|
mpIdle->SetPriority(mpIdle->GetDefaultPriority());
|
2015-01-14 08:29:37 +01:00
|
|
|
mbDelete = true;
|
|
|
|
mpIdle->mbActive = false;
|
|
|
|
|
|
|
|
// invoke it
|
|
|
|
mbInIdle = true;
|
|
|
|
mpIdle->DoIdle();
|
|
|
|
mbInIdle = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ImplIdleData *GetFirstIdle()
|
|
|
|
{
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
ImplIdleData *pMostUrgent = NULL;
|
|
|
|
|
|
|
|
for ( ImplIdleData *p = pSVData->mpFirstIdleData; p; p = p->mpNext )
|
|
|
|
{
|
|
|
|
if ( !p->mpIdle || p->mbDelete )
|
|
|
|
continue;
|
|
|
|
if (!pMostUrgent)
|
|
|
|
pMostUrgent = p;
|
|
|
|
else
|
|
|
|
{
|
2015-01-19 16:30:23 +00:00
|
|
|
// Find the highest priority.
|
2015-01-20 12:42:43 +00:00
|
|
|
// If the priority of the current idle is higher (numerical value is lower) than
|
|
|
|
// the priority of the most urgent, the priority of most urgent is increased and
|
|
|
|
// the current is the new most urgent. So starving is impossible.
|
2015-01-14 08:29:37 +01:00
|
|
|
if ( p->mpIdle->GetPriority() < pMostUrgent->mpIdle->GetPriority() )
|
2015-01-16 13:28:29 +00:00
|
|
|
{
|
|
|
|
IncreasePriority(pMostUrgent->mpIdle);
|
2015-01-14 08:29:37 +01:00
|
|
|
pMostUrgent = p;
|
2015-01-16 13:28:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
IncreasePriority(p->mpIdle);
|
2015-01-14 08:29:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pMostUrgent;
|
|
|
|
}
|
2015-01-16 13:28:29 +00:00
|
|
|
|
|
|
|
static void IncreasePriority( Idle *pIdle )
|
|
|
|
{
|
|
|
|
switch(pIdle->GetPriority())
|
|
|
|
{
|
2015-01-20 12:42:43 +00:00
|
|
|
// Increase priority based on their current priority;
|
|
|
|
// (so don't use VCL_IDLE_PRIORITY_STARVATIONPROTECTION for default-priority!)
|
2015-01-16 13:28:29 +00:00
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_STARVATIONPROTECTION:
|
|
|
|
break;
|
2015-01-19 16:30:23 +00:00
|
|
|
// If already highest priority -> extra state for starving tasks
|
2015-01-16 13:28:29 +00:00
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_HIGHEST:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_STARVATIONPROTECTION);
|
|
|
|
break;
|
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_HIGH:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_HIGHEST);
|
|
|
|
break;
|
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_REPAINT:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_HIGH);
|
|
|
|
break;
|
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_MEDIUM:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_REPAINT);
|
|
|
|
break;
|
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_LOW:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_MEDIUM);
|
|
|
|
break;
|
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_LOWER:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_LOW);
|
|
|
|
break;
|
|
|
|
case IdlePriority::VCL_IDLE_PRIORITY_LOWEST:
|
|
|
|
pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_LOWER);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-01-14 08:29:37 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
void Idle::ImplDeInitIdle()
|
|
|
|
{
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
ImplIdleData* pIdleData = pSVData->mpFirstIdleData;
|
|
|
|
|
|
|
|
if ( pIdleData )
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ImplIdleData* pTempIdleData = pIdleData;
|
|
|
|
if ( pIdleData->mpIdle )
|
|
|
|
{
|
|
|
|
pIdleData->mpIdle->mbActive = false;
|
|
|
|
pIdleData->mpIdle->mpIdleData = NULL;
|
|
|
|
}
|
|
|
|
pIdleData = pIdleData->mpNext;
|
|
|
|
delete pTempIdleData;
|
|
|
|
}
|
|
|
|
while ( pIdleData );
|
|
|
|
|
|
|
|
pSVData->mpFirstIdleData = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Idle::ProcessAllIdleHandlers()
|
|
|
|
{
|
2015-01-20 12:42:43 +00:00
|
|
|
// process all pending idle
|
2015-01-14 13:11:28 +00:00
|
|
|
ImplIdleData* pIdleData = NULL;
|
|
|
|
ImplIdleData* pPrevIdleData = NULL;
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
2015-01-20 12:42:43 +00:00
|
|
|
// timer can interrupt idle
|
2015-01-16 13:28:29 +00:00
|
|
|
while (!Timer::TimerReady() && (pIdleData = ImplIdleData::GetFirstIdle()))
|
2015-01-14 08:29:37 +01:00
|
|
|
{
|
|
|
|
pIdleData->Invoke();
|
|
|
|
}
|
|
|
|
|
|
|
|
pIdleData = pSVData->mpFirstIdleData;
|
|
|
|
while ( pIdleData )
|
|
|
|
{
|
2015-01-20 12:42:43 +00:00
|
|
|
// Was idle destroyed in the meantime?
|
2015-01-14 08:29:37 +01:00
|
|
|
if ( pIdleData->mbDelete )
|
|
|
|
{
|
|
|
|
if ( pPrevIdleData )
|
|
|
|
pPrevIdleData->mpNext = pIdleData->mpNext;
|
|
|
|
else
|
|
|
|
pSVData->mpFirstIdleData = pIdleData->mpNext;
|
|
|
|
if ( pIdleData->mpIdle )
|
|
|
|
pIdleData->mpIdle->mpIdleData = NULL;
|
|
|
|
ImplIdleData* pTempIdleData = pIdleData;
|
|
|
|
pIdleData = pIdleData->mpNext;
|
|
|
|
delete pTempIdleData;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pPrevIdleData = pIdleData;
|
|
|
|
pIdleData = pIdleData->mpNext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-16 13:28:29 +00:00
|
|
|
void Idle::SetPriority( IdlePriority ePriority )
|
|
|
|
{
|
|
|
|
mePriority = ePriority;
|
2015-01-19 16:30:23 +00:00
|
|
|
// Was a new priority set before excecution?
|
|
|
|
// Then take it as default priority
|
2015-01-16 13:28:29 +00:00
|
|
|
if( !mbActive && meDefaultPriority == IdlePriority::VCL_IDLE_PRIORITY_DEFAULT )
|
|
|
|
meDefaultPriority = mePriority;
|
|
|
|
}
|
|
|
|
|
2015-01-14 08:29:37 +01:00
|
|
|
void Idle::DoIdle()
|
|
|
|
{
|
|
|
|
maIdleHdl.Call( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Idle::Start()
|
|
|
|
{
|
2015-01-19 16:30:23 +00:00
|
|
|
// Mark timer active
|
2015-01-14 08:29:37 +01:00
|
|
|
mbActive = true;
|
|
|
|
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
if ( !mpIdleData )
|
|
|
|
{
|
2015-01-19 16:30:23 +00:00
|
|
|
// insert Idle
|
2015-01-20 12:42:43 +00:00
|
|
|
mpIdleData = new ImplIdleData;
|
|
|
|
mpIdleData->mpIdle = this;
|
2015-01-14 08:29:37 +01:00
|
|
|
mpIdleData->mbInIdle = false;
|
|
|
|
|
|
|
|
// insert last due to SFX!
|
|
|
|
ImplIdleData* pPrev = NULL;
|
|
|
|
ImplIdleData* pData = pSVData->mpFirstIdleData;
|
|
|
|
while ( pData )
|
|
|
|
{
|
|
|
|
pPrev = pData;
|
|
|
|
pData = pData->mpNext;
|
|
|
|
}
|
|
|
|
mpIdleData->mpNext = NULL;
|
|
|
|
if ( pPrev )
|
|
|
|
pPrev->mpNext = mpIdleData;
|
|
|
|
else
|
|
|
|
pSVData->mpFirstIdleData = mpIdleData;
|
|
|
|
}
|
2015-01-19 13:08:26 +00:00
|
|
|
mpIdleData->mbDelete = false;
|
2015-01-14 08:29:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Idle::Stop()
|
|
|
|
{
|
|
|
|
mbActive = false;
|
|
|
|
|
|
|
|
if ( mpIdleData )
|
|
|
|
mpIdleData->mbDelete = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Idle& Idle::operator=( const Idle& rIdle )
|
|
|
|
{
|
|
|
|
if ( IsActive() )
|
|
|
|
Stop();
|
|
|
|
|
2015-01-20 12:42:43 +00:00
|
|
|
mbActive = false;
|
|
|
|
mePriority = rIdle.mePriority;
|
2015-01-16 13:28:29 +00:00
|
|
|
meDefaultPriority = rIdle.meDefaultPriority;
|
2015-01-20 12:42:43 +00:00
|
|
|
maIdleHdl = rIdle.maIdleHdl;
|
2015-01-14 08:29:37 +01:00
|
|
|
|
|
|
|
if ( rIdle.IsActive() )
|
|
|
|
Start();
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Idle::Idle():
|
|
|
|
mpIdleData(NULL),
|
2015-01-16 13:28:29 +00:00
|
|
|
mePriority(IdlePriority::VCL_IDLE_PRIORITY_DEFAULT),
|
|
|
|
meDefaultPriority(IdlePriority::VCL_IDLE_PRIORITY_DEFAULT),
|
2015-01-14 08:29:37 +01:00
|
|
|
mbActive(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Idle::Idle( const Idle& rIdle ):
|
|
|
|
mpIdleData(NULL),
|
|
|
|
mePriority(rIdle.mePriority),
|
2015-01-16 13:28:29 +00:00
|
|
|
meDefaultPriority(rIdle.meDefaultPriority),
|
2015-01-14 08:29:37 +01:00
|
|
|
mbActive(false),
|
|
|
|
maIdleHdl(rIdle.maIdleHdl)
|
|
|
|
{
|
|
|
|
if ( rIdle.IsActive() )
|
|
|
|
Start();
|
|
|
|
}
|
|
|
|
|
|
|
|
Idle::~Idle()
|
|
|
|
{
|
|
|
|
if ( mpIdleData )
|
|
|
|
{
|
|
|
|
mpIdleData->mbDelete = true;
|
|
|
|
mpIdleData->mpIdle = NULL;
|
|
|
|
}
|
|
|
|
}
|
2015-01-20 12:42:43 +00:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|