LCOV - code coverage report
Current view: top level - libreoffice/vcl/source/app - timer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 139 163 85.3 %
Date: 2012-12-27 Functions: 14 15 93.3 %
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             : 
      21             : #include <tools/time.hxx>
      22             : 
      23             : #include <vcl/svapp.hxx>
      24             : #include <vcl/timer.hxx>
      25             : 
      26             : #include <saltimer.hxx>
      27             : #include <svdata.hxx>
      28             : #include <salinst.hxx>
      29             : 
      30             : 
      31             : // =======================================================================
      32             : 
      33             : #define MAX_TIMER_PERIOD    ((sal_uLong)0xFFFFFFFF)
      34             : 
      35             : // ---------------------
      36             : // - TimeManager-Types -
      37             : // ---------------------
      38             : 
      39             : struct ImplTimerData
      40             : {
      41             :     ImplTimerData*  mpNext;         // Pointer to the next Instance
      42             :     Timer*          mpSVTimer;      // Pointer to SV Timer instance
      43             :     sal_uLong           mnUpdateTime;   // Last Update Time
      44             :     sal_uLong           mnTimerUpdate;  // TimerCallbackProcs on stack
      45             :     sal_Bool            mbDelete;       // Was timer deleted during Update()?
      46             :     sal_Bool            mbInTimeout;    // Are we in a timeout handler?
      47             : };
      48             : 
      49             : // =======================================================================
      50             : 
      51           0 : void Timer::ImplDeInitTimer()
      52             : {
      53           0 :     ImplSVData*     pSVData = ImplGetSVData();
      54           0 :     ImplTimerData*  pTimerData = pSVData->mpFirstTimerData;
      55             : 
      56           0 :     if ( pTimerData )
      57             :     {
      58           0 :         do
      59             :         {
      60           0 :             ImplTimerData* pTempTimerData = pTimerData;
      61           0 :             if ( pTimerData->mpSVTimer )
      62             :             {
      63           0 :                 pTimerData->mpSVTimer->mbActive = sal_False;
      64           0 :                 pTimerData->mpSVTimer->mpTimerData = NULL;
      65             :             }
      66           0 :             pTimerData = pTimerData->mpNext;
      67           0 :             delete pTempTimerData;
      68             :         }
      69             :         while ( pTimerData );
      70             : 
      71           0 :         pSVData->mpFirstTimerData   = NULL;
      72           0 :         pSVData->mnTimerPeriod      = 0;
      73           0 :         delete pSVData->mpSalTimer;
      74           0 :         pSVData->mpSalTimer = NULL;
      75             :     }
      76           0 : }
      77             : 
      78             : // -----------------------------------------------------------------------
      79             : 
      80         973 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
      81             : {
      82         973 :     if ( !nMS )
      83         237 :         nMS = 1;
      84             : 
      85         973 :     if ( nMS != pSVData->mnTimerPeriod )
      86             :     {
      87         593 :         pSVData->mnTimerPeriod = nMS;
      88         593 :         pSVData->mpSalTimer->Start( nMS );
      89             :     }
      90         973 : }
      91             : 
      92             : // -----------------------------------------------------------------------
      93             : 
      94         473 : void Timer::ImplTimerCallbackProc()
      95             : {
      96         473 :     ImplSVData*     pSVData = ImplGetSVData();
      97             :     ImplTimerData*  pTimerData;
      98             :     ImplTimerData*  pPrevTimerData;
      99         473 :     sal_uLong           nMinPeriod = MAX_TIMER_PERIOD;
     100             :     sal_uLong           nDeltaTime;
     101         473 :     sal_uLong           nTime = Time::GetSystemTicks();
     102             : 
     103         473 :     if ( pSVData->mbNoCallTimer )
     104         473 :         return;
     105             : 
     106         473 :     pSVData->mnTimerUpdate++;
     107         473 :     pSVData->mbNotAllTimerCalled = sal_True;
     108             : 
     109             :     // find timer where the timer handler needs to be called
     110         473 :     pTimerData = pSVData->mpFirstTimerData;
     111        6437 :     while ( pTimerData )
     112             :     {
     113             :         // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
     114             :         // call the handler as soon as the time is up.
     115       15373 :         if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
     116        9882 :              !pTimerData->mbDelete && !pTimerData->mbInTimeout )
     117             :         {
     118             :             // time has expired
     119        4505 :             if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
     120             :             {
     121             :                 // set new update time
     122        1857 :                 pTimerData->mnUpdateTime = nTime;
     123             : 
     124             :                 // if no AutoTimer than stop
     125        1857 :                 if ( !pTimerData->mpSVTimer->mbAuto )
     126             :                 {
     127        1640 :                     pTimerData->mpSVTimer->mbActive = sal_False;
     128        1640 :                     pTimerData->mbDelete = sal_True;
     129             :                 }
     130             : 
     131             :                 // call Timeout
     132        1857 :                 pTimerData->mbInTimeout = sal_True;
     133        1857 :                 pTimerData->mpSVTimer->Timeout();
     134        1857 :                 pTimerData->mbInTimeout = sal_False;
     135             :             }
     136             :         }
     137             : 
     138        5491 :         pTimerData = pTimerData->mpNext;
     139             :     }
     140             : 
     141             :     // determine new time
     142         473 :     sal_uLong nNewTime = Time::GetSystemTicks();
     143         473 :     pPrevTimerData = NULL;
     144         473 :     pTimerData = pSVData->mpFirstTimerData;
     145        6437 :     while ( pTimerData )
     146             :     {
     147             :         // ignore if timer is still in timeout handler
     148        5491 :         if ( pTimerData->mbInTimeout )
     149             :         {
     150           0 :             pPrevTimerData = pTimerData;
     151           0 :             pTimerData = pTimerData->mpNext;
     152             :         }
     153             :         // Was timer destroyed in the meantime?
     154        5491 :         else if ( pTimerData->mbDelete )
     155             :         {
     156        2109 :             if ( pPrevTimerData )
     157        2102 :                 pPrevTimerData->mpNext = pTimerData->mpNext;
     158             :             else
     159           7 :                 pSVData->mpFirstTimerData = pTimerData->mpNext;
     160        2109 :             if ( pTimerData->mpSVTimer )
     161        1494 :                 pTimerData->mpSVTimer->mpTimerData = NULL;
     162        2109 :             ImplTimerData* pTempTimerData = pTimerData;
     163        2109 :             pTimerData = pTimerData->mpNext;
     164        2109 :             delete pTempTimerData;
     165             :         }
     166             :         else
     167             :         {
     168        3382 :             pTimerData->mnTimerUpdate = 0;
     169             :             // determine smallest time slot
     170        3382 :             if ( pTimerData->mnUpdateTime == nTime )
     171             :             {
     172         201 :                 nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
     173         201 :                 if ( nDeltaTime < nMinPeriod )
     174          67 :                     nMinPeriod = nDeltaTime;
     175             :             }
     176             :             else
     177             :             {
     178        3181 :                 nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
     179        3181 :                 if ( nDeltaTime < nNewTime )
     180         637 :                     nMinPeriod = 1;
     181             :                 else
     182             :                 {
     183        2544 :                     nDeltaTime -= nNewTime;
     184        2544 :                     if ( nDeltaTime < nMinPeriod )
     185        1262 :                         nMinPeriod = nDeltaTime;
     186             :                 }
     187             :             }
     188        3382 :             pPrevTimerData = pTimerData;
     189        3382 :             pTimerData = pTimerData->mpNext;
     190             :         }
     191             :     }
     192             : 
     193             :     // delete clock if no more timers available
     194         473 :     if ( !pSVData->mpFirstTimerData )
     195             :     {
     196           0 :         pSVData->mpSalTimer->Stop();
     197           0 :         pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     198             :     }
     199             :     else
     200         473 :         ImplStartTimer( pSVData, nMinPeriod );
     201             : 
     202         473 :     pSVData->mnTimerUpdate--;
     203         473 :     pSVData->mbNotAllTimerCalled = sal_False;
     204             : }
     205             : 
     206             : // =======================================================================
     207             : 
     208       28666 : Timer::Timer()
     209             : {
     210       28666 :     mpTimerData     = NULL;
     211       28666 :     mnTimeout       = 1;
     212       28666 :     mbAuto          = sal_False;
     213       28666 :     mbActive        = sal_False;
     214       28666 : }
     215             : 
     216             : // -----------------------------------------------------------------------
     217             : 
     218           8 : Timer::Timer( const Timer& rTimer )
     219             : {
     220           8 :     mpTimerData     = NULL;
     221           8 :     mnTimeout       = rTimer.mnTimeout;
     222           8 :     mbAuto          = sal_False;
     223           8 :     mbActive        = sal_False;
     224           8 :     maTimeoutHdl    = rTimer.maTimeoutHdl;
     225             : 
     226           8 :     if ( rTimer.IsActive() )
     227           0 :         Start();
     228           8 : }
     229             : 
     230             : // -----------------------------------------------------------------------
     231             : 
     232       19920 : Timer::~Timer()
     233             : {
     234       19669 :     if ( mpTimerData )
     235             :     {
     236         924 :         mpTimerData->mbDelete = sal_True;
     237         924 :         mpTimerData->mpSVTimer = NULL;
     238             :     }
     239       19920 : }
     240             : 
     241             : // -----------------------------------------------------------------------
     242             : 
     243        1855 : void Timer::Timeout()
     244             : {
     245        1855 :     maTimeoutHdl.Call( this );
     246        1855 : }
     247             : 
     248             : // -----------------------------------------------------------------------
     249             : 
     250       32593 : void Timer::SetTimeout( sal_uLong nNewTimeout )
     251             : {
     252       32593 :     mnTimeout = nNewTimeout;
     253             : 
     254             :     // if timer is active then renew clock
     255       32593 :     if ( mbActive )
     256             :     {
     257        1512 :         ImplSVData* pSVData = ImplGetSVData();
     258        1512 :         if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
     259           0 :             ImplStartTimer( pSVData, mnTimeout );
     260             :     }
     261       32593 : }
     262             : 
     263             : // -----------------------------------------------------------------------
     264             : 
     265       24405 : void Timer::Start()
     266             : {
     267       24405 :     mbActive = sal_True;
     268             : 
     269       24405 :     ImplSVData* pSVData = ImplGetSVData();
     270       24405 :     if ( !mpTimerData )
     271             :     {
     272        2966 :         if ( !pSVData->mpFirstTimerData )
     273             :         {
     274          19 :             pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     275          19 :             if( ! pSVData->mpSalTimer )
     276             :             {
     277          19 :                 pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
     278          19 :                 pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
     279             :             }
     280             :         }
     281             : 
     282             :         // insert timer and start
     283        2966 :         mpTimerData                 = new ImplTimerData;
     284        2966 :         mpTimerData->mpSVTimer      = this;
     285        2966 :         mpTimerData->mnUpdateTime   = Time::GetSystemTicks();
     286        2966 :         mpTimerData->mnTimerUpdate  = pSVData->mnTimerUpdate;
     287        2966 :         mpTimerData->mbDelete       = sal_False;
     288        2966 :         mpTimerData->mbInTimeout    = sal_False;
     289             : 
     290             :         // insert last due to SFX!
     291        2966 :         ImplTimerData* pPrev = NULL;
     292        2966 :         ImplTimerData* pData = pSVData->mpFirstTimerData;
     293      191471 :         while ( pData )
     294             :         {
     295      185539 :             pPrev = pData;
     296      185539 :             pData = pData->mpNext;
     297             :         }
     298        2966 :         mpTimerData->mpNext = NULL;
     299        2966 :         if ( pPrev )
     300        2947 :             pPrev->mpNext = mpTimerData;
     301             :         else
     302          19 :             pSVData->mpFirstTimerData = mpTimerData;
     303             : 
     304        2966 :         if ( mnTimeout < pSVData->mnTimerPeriod )
     305         500 :             ImplStartTimer( pSVData, mnTimeout );
     306             :     }
     307       21439 :     else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
     308             :     {
     309             :         OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
     310             :     }
     311             :     else
     312             :     {
     313       21439 :         mpTimerData->mnUpdateTime    = Time::GetSystemTicks();
     314       21439 :         mpTimerData->mnTimerUpdate   = pSVData->mnTimerUpdate;
     315       21439 :         mpTimerData->mbDelete        = sal_False;
     316             :     }
     317       24405 : }
     318             : 
     319             : // -----------------------------------------------------------------------
     320             : 
     321       30567 : void Timer::Stop()
     322             : {
     323       30567 :     mbActive = sal_False;
     324             : 
     325       30567 :     if ( mpTimerData )
     326        9441 :         mpTimerData->mbDelete = sal_True;
     327       30567 : }
     328             : 
     329             : // -----------------------------------------------------------------------
     330             : 
     331           8 : Timer& Timer::operator=( const Timer& rTimer )
     332             : {
     333           8 :     if ( IsActive() )
     334           0 :         Stop();
     335             : 
     336           8 :     mbActive        = sal_False;
     337           8 :     mnTimeout       = rTimer.mnTimeout;
     338           8 :     maTimeoutHdl    = rTimer.maTimeoutHdl;
     339             : 
     340           8 :     if ( rTimer.IsActive() )
     341           0 :         Start();
     342             : 
     343           8 :     return *this;
     344             : }
     345             : 
     346             : // =======================================================================
     347             : 
     348        1413 : AutoTimer::AutoTimer()
     349             : {
     350        1413 :     mbAuto = sal_True;
     351        1413 : }
     352             : 
     353             : // -----------------------------------------------------------------------
     354             : 
     355           8 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
     356             : {
     357           8 :     mbAuto = sal_True;
     358           8 : }
     359             : 
     360             : // -----------------------------------------------------------------------
     361             : 
     362           8 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
     363             : {
     364           8 :     Timer::operator=( rTimer );
     365           8 :     return *this;
     366             : }
     367             : 
     368             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10