LCOV - code coverage report
Current view: top level - vcl/source/app - timer.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 158 159 99.4 %
Date: 2014-11-03 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/time.hxx>
      21             : 
      22             : #include <vcl/svapp.hxx>
      23             : #include <vcl/timer.hxx>
      24             : 
      25             : #include <saltimer.hxx>
      26             : #include <svdata.hxx>
      27             : #include <salinst.hxx>
      28             : 
      29             : #define MAX_TIMER_PERIOD    ((sal_uLong)0xFFFFFFFF)
      30             : 
      31             : struct ImplTimerData
      32             : {
      33             :     ImplTimerData*  mpNext;         // Pointer to the next Instance
      34             :     Timer*          mpTimer;        // Pointer to VCL Timer instance
      35             :     sal_uLong       mnUpdateTime;   // Last Update Time
      36             :     sal_uLong       mnTimerUpdate;  // TimerCallbackProcs on stack
      37             :     bool            mbDelete;       // Was timer deleted during Update()?
      38             :     bool            mbInTimeout;    // Are we in a timeout handler?
      39             : };
      40             : 
      41         535 : void Timer::ImplDeInitTimer()
      42             : {
      43         535 :     ImplSVData*     pSVData = ImplGetSVData();
      44         535 :     ImplTimerData*  pTimerData = pSVData->mpFirstTimerData;
      45             : 
      46             :     // on WNT the timer queue thread needs killing
      47         535 :     if (pSVData->mpSalTimer)
      48             :     {
      49         469 :         pSVData->mpSalTimer->Stop();
      50             :     }
      51             : 
      52         535 :     if ( pTimerData )
      53             :     {
      54        7981 :         do
      55             :         {
      56        7981 :             ImplTimerData* pTempTimerData = pTimerData;
      57        7981 :             if ( pTimerData->mpTimer )
      58             :             {
      59         694 :                 pTimerData->mpTimer->mbActive = false;
      60         694 :                 pTimerData->mpTimer->mpTimerData = NULL;
      61             :             }
      62        7981 :             pTimerData = pTimerData->mpNext;
      63        7981 :             delete pTempTimerData;
      64             :         }
      65             :         while ( pTimerData );
      66             : 
      67         447 :         pSVData->mpFirstTimerData   = NULL;
      68         447 :         pSVData->mnTimerPeriod      = 0;
      69             :     }
      70             : 
      71         535 :     delete pSVData->mpSalTimer;
      72         535 :     pSVData->mpSalTimer = 0;
      73         535 : }
      74             : 
      75       66117 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
      76             : {
      77       66117 :     if ( !nMS )
      78        6500 :         nMS = 1;
      79             : 
      80             :     // Assume underlying timers are recurring timers, if same period - just wait.
      81       66117 :     if ( nMS != pSVData->mnTimerPeriod )
      82             :     {
      83       56784 :         pSVData->mnTimerPeriod = nMS;
      84       56784 :         pSVData->mpSalTimer->Start( nMS );
      85             :     }
      86       66117 : }
      87             : 
      88       38807 : void Timer::ImplTimerCallbackProc()
      89             : {
      90       38807 :     ImplSVData*     pSVData = ImplGetSVData();
      91             :     ImplTimerData*  pTimerData;
      92             :     ImplTimerData*  pPrevTimerData;
      93       38807 :     sal_uLong       nMinPeriod = MAX_TIMER_PERIOD;
      94             :     sal_uLong       nDeltaTime;
      95       38807 :     sal_uLong       nTime = tools::Time::GetSystemTicks();
      96             : 
      97       38807 :     if ( pSVData->mbNoCallTimer )
      98       38807 :         return;
      99             : 
     100       38807 :     pSVData->mnTimerUpdate++;
     101       38807 :     pSVData->mbNotAllTimerCalled = true;
     102             : 
     103             :     // find timer where the timer handler needs to be called
     104       38807 :     pTimerData = pSVData->mpFirstTimerData;
     105      397183 :     while ( pTimerData )
     106             :     {
     107             :         // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
     108             :         // call the handler as soon as the time is up.
     109      636412 :         if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
     110      571730 :              !pTimerData->mbDelete && !pTimerData->mbInTimeout )
     111             :         {
     112             :             // time has expired
     113      254887 :             if ( (pTimerData->mnUpdateTime+pTimerData->mpTimer->mnTimeout) <= nTime )
     114             :             {
     115             :                 // set new update time
     116       53005 :                 pTimerData->mnUpdateTime = nTime;
     117             : 
     118             :                 // if no AutoTimer than stop
     119       53005 :                 if ( !pTimerData->mpTimer->mbAuto )
     120             :                 {
     121       42202 :                     pTimerData->mpTimer->mbActive = false;
     122       42202 :                     pTimerData->mbDelete = true;
     123             :                 }
     124             : 
     125             :                 // call Timeout
     126       53005 :                 pTimerData->mbInTimeout = true;
     127       53005 :                 pTimerData->mpTimer->Timeout();
     128       53005 :                 pTimerData->mbInTimeout = false;
     129             :             }
     130             :         }
     131             : 
     132      319569 :         pTimerData = pTimerData->mpNext;
     133             :     }
     134             : 
     135             :     // determine new time
     136       38807 :     sal_uLong nNewTime = tools::Time::GetSystemTicks();
     137       38807 :     pPrevTimerData = NULL;
     138       38807 :     pTimerData = pSVData->mpFirstTimerData;
     139      397183 :     while ( pTimerData )
     140             :     {
     141             :         // ignore if timer is still in timeout handler
     142      319569 :         if ( pTimerData->mbInTimeout )
     143             :         {
     144         102 :             pPrevTimerData = pTimerData;
     145         102 :             pTimerData = pTimerData->mpNext;
     146             :         }
     147             :         // Was timer destroyed in the meantime?
     148      319467 :         else if ( pTimerData->mbDelete )
     149             :         {
     150       97308 :             if ( pPrevTimerData )
     151       96822 :                 pPrevTimerData->mpNext = pTimerData->mpNext;
     152             :             else
     153         486 :                 pSVData->mpFirstTimerData = pTimerData->mpNext;
     154       97308 :             if ( pTimerData->mpTimer )
     155       40596 :                 pTimerData->mpTimer->mpTimerData = NULL;
     156       97308 :             ImplTimerData* pTempTimerData = pTimerData;
     157       97308 :             pTimerData = pTimerData->mpNext;
     158       97308 :             delete pTempTimerData;
     159             :         }
     160             :         else
     161             :         {
     162      222159 :             pTimerData->mnTimerUpdate = 0;
     163             :             // determine smallest time slot
     164      222159 :             if ( pTimerData->mnUpdateTime == nTime )
     165             :             {
     166       24155 :                 nDeltaTime = pTimerData->mpTimer->mnTimeout;
     167       24155 :                 if ( nDeltaTime < nMinPeriod )
     168       18027 :                     nMinPeriod = nDeltaTime;
     169             :             }
     170             :             else
     171             :             {
     172      198004 :                 nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpTimer->mnTimeout;
     173      198004 :                 if ( nDeltaTime < nNewTime )
     174        6828 :                     nMinPeriod = 1;
     175             :                 else
     176             :                 {
     177      191176 :                     nDeltaTime -= nNewTime;
     178      191176 :                     if ( nDeltaTime < nMinPeriod )
     179       99466 :                         nMinPeriod = nDeltaTime;
     180             :                 }
     181             :             }
     182      222159 :             pPrevTimerData = pTimerData;
     183      222159 :             pTimerData = pTimerData->mpNext;
     184             :         }
     185             :     }
     186             : 
     187             :     // delete clock if no more timers available
     188       38807 :     if ( !pSVData->mpFirstTimerData )
     189             :     {
     190          85 :         pSVData->mpSalTimer->Stop();
     191          85 :         pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     192             :     }
     193             :     else
     194       38722 :         ImplStartTimer( pSVData, nMinPeriod );
     195             : 
     196       38807 :     pSVData->mnTimerUpdate--;
     197       38807 :     pSVData->mbNotAllTimerCalled = false;
     198             : }
     199             : 
     200      663156 : Timer::Timer():
     201             :     mpTimerData(NULL),
     202             :     mnTimeout(1),
     203             :     mbActive(false),
     204      663156 :     mbAuto(false)
     205             : {
     206      663156 : }
     207             : 
     208         842 : Timer::Timer( const Timer& rTimer ):
     209             :     mpTimerData(NULL),
     210             :     mnTimeout(rTimer.mnTimeout),
     211             :     mbActive(false),
     212             :     mbAuto(false),
     213         842 :     maTimeoutHdl(rTimer.maTimeoutHdl)
     214             : {
     215         842 :     if ( rTimer.IsActive() )
     216          82 :         Start();
     217         842 : }
     218             : 
     219      671246 : Timer::~Timer()
     220             : {
     221      661188 :     if ( mpTimerData )
     222             :     {
     223       64053 :         mpTimerData->mbDelete = true;
     224       64053 :         mpTimerData->mpTimer = NULL;
     225             :      }
     226      671246 : }
     227             : 
     228       46329 : void Timer::Timeout()
     229             : {
     230       46329 :     maTimeoutHdl.Call( this );
     231       46329 : }
     232             : 
     233      808762 : void Timer::SetTimeout( sal_uLong nNewTimeout )
     234             : {
     235      808762 :     mnTimeout = nNewTimeout;
     236             : 
     237             :     // if timer is active then renew clock
     238      808762 :     if ( mbActive )
     239             :     {
     240       38011 :         ImplSVData* pSVData = ImplGetSVData();
     241       38011 :         if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
     242           0 :             ImplStartTimer( pSVData, mnTimeout );
     243             :     }
     244      808762 : }
     245             : 
     246     1286797 : void Timer::Start()
     247             : {
     248     1286797 :     mbActive = true;
     249             : 
     250     1286797 :     ImplSVData* pSVData = ImplGetSVData();
     251     1286797 :     if ( !mpTimerData )
     252             :     {
     253      105363 :         if ( !pSVData->mpFirstTimerData )
     254             :         {
     255         538 :             pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     256         538 :             if( ! pSVData->mpSalTimer )
     257             :             {
     258         475 :                 pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
     259         475 :                 pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
     260             :             }
     261             :         }
     262             : 
     263             :         // insert timer and start
     264      105363 :         mpTimerData = new ImplTimerData;
     265      105363 :         mpTimerData->mpTimer        = this;
     266      105363 :         mpTimerData->mnUpdateTime   = tools::Time::GetSystemTicks();
     267      105363 :         mpTimerData->mnTimerUpdate  = pSVData->mnTimerUpdate;
     268      105363 :         mpTimerData->mbDelete       = false;
     269      105363 :         mpTimerData->mbInTimeout    = false;
     270             : 
     271             :         // insert last due to SFX!
     272      105363 :         ImplTimerData* pPrev = NULL;
     273      105363 :         ImplTimerData* pData = pSVData->mpFirstTimerData;
     274     2842366 :         while ( pData )
     275             :         {
     276     2631640 :             pPrev = pData;
     277     2631640 :             pData = pData->mpNext;
     278             :         }
     279      105363 :         mpTimerData->mpNext = NULL;
     280      105363 :         if ( pPrev )
     281      104825 :             pPrev->mpNext = mpTimerData;
     282             :         else
     283         538 :             pSVData->mpFirstTimerData = mpTimerData;
     284             : 
     285      105363 :         if ( mnTimeout < pSVData->mnTimerPeriod )
     286       27395 :             ImplStartTimer( pSVData, mnTimeout );
     287             :     }
     288     1181434 :     else if( !mpTimerData->mpTimer ) // TODO: remove when guilty found
     289             :     {
     290             :         OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
     291             :     }
     292             :     else
     293             :     {
     294     1181434 :         mpTimerData->mnUpdateTime    = tools::Time::GetSystemTicks();
     295     1181434 :         mpTimerData->mnTimerUpdate   = pSVData->mnTimerUpdate;
     296     1181434 :         mpTimerData->mbDelete        = false;
     297             :     }
     298     1286797 : }
     299             : 
     300     1035423 : void Timer::Stop()
     301             : {
     302     1035423 :     mbActive = false;
     303             : 
     304     1035423 :     if ( mpTimerData )
     305      442538 :         mpTimerData->mbDelete = true;
     306     1035423 : }
     307             : 
     308          98 : Timer& Timer::operator=( const Timer& rTimer )
     309             : {
     310          98 :     if ( IsActive() )
     311          26 :         Stop();
     312             : 
     313          98 :     mbActive        = false;
     314          98 :     mnTimeout       = rTimer.mnTimeout;
     315          98 :     maTimeoutHdl    = rTimer.maTimeoutHdl;
     316             : 
     317          98 :     if ( rTimer.IsActive() )
     318          30 :         Start();
     319             : 
     320          98 :     return *this;
     321             : }
     322             : 
     323       57035 : AutoTimer::AutoTimer()
     324             : {
     325       57035 :     mbAuto = true;
     326       57035 : }
     327             : 
     328         842 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
     329             : {
     330         842 :     mbAuto = true;
     331         842 : }
     332             : 
     333          98 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
     334             : {
     335          98 :     Timer::operator=( rTimer );
     336          98 :     return *this;
     337        1233 : }
     338             : 
     339             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10