LCOV - code coverage report
Current view: top level - vcl/source/app - timer.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 153 156 98.1 %
Date: 2014-04-11 Functions: 15 15 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         174 : void Timer::ImplDeInitTimer()
      42             : {
      43         174 :     ImplSVData*     pSVData = ImplGetSVData();
      44         174 :     ImplTimerData*  pTimerData = pSVData->mpFirstTimerData;
      45             : 
      46         174 :     if ( pTimerData )
      47             :     {
      48        1184 :         do
      49             :         {
      50        1184 :             ImplTimerData* pTempTimerData = pTimerData;
      51        1184 :             if ( pTimerData->mpTimer )
      52             :             {
      53         146 :                 pTimerData->mpTimer->mbActive = false;
      54         146 :                 pTimerData->mpTimer->mpTimerData = NULL;
      55             :             }
      56        1184 :             pTimerData = pTimerData->mpNext;
      57        1184 :             delete pTempTimerData;
      58             :         }
      59             :         while ( pTimerData );
      60             : 
      61         159 :         pSVData->mpFirstTimerData   = NULL;
      62         159 :         pSVData->mnTimerPeriod      = 0;
      63         159 :         delete pSVData->mpSalTimer;
      64         159 :         pSVData->mpSalTimer = NULL;
      65             :     }
      66         174 : }
      67             : 
      68       36879 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
      69             : {
      70       36879 :     if ( !nMS )
      71        2570 :         nMS = 1;
      72             : 
      73       36879 :     if ( nMS != pSVData->mnTimerPeriod )
      74             :     {
      75       30755 :         pSVData->mnTimerPeriod = nMS;
      76       30755 :         pSVData->mpSalTimer->Start( nMS );
      77             :     }
      78       36879 : }
      79             : 
      80       21960 : void Timer::ImplTimerCallbackProc()
      81             : {
      82       21960 :     ImplSVData*     pSVData = ImplGetSVData();
      83             :     ImplTimerData*  pTimerData;
      84             :     ImplTimerData*  pPrevTimerData;
      85       21960 :     sal_uLong       nMinPeriod = MAX_TIMER_PERIOD;
      86             :     sal_uLong       nDeltaTime;
      87       21960 :     sal_uLong       nTime = Time::GetSystemTicks();
      88             : 
      89       21960 :     if ( pSVData->mbNoCallTimer )
      90       21960 :         return;
      91             : 
      92       21960 :     pSVData->mnTimerUpdate++;
      93       21960 :     pSVData->mbNotAllTimerCalled = true;
      94             : 
      95             :     // find timer where the timer handler needs to be called
      96       21960 :     pTimerData = pSVData->mpFirstTimerData;
      97      193015 :     while ( pTimerData )
      98             :     {
      99             :         // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
     100             :         // call the handler as soon as the time is up.
     101      295714 :         if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
     102      270663 :              !pTimerData->mbDelete && !pTimerData->mbInTimeout )
     103             :         {
     104             :             // time has expired
     105      124044 :             if ( (pTimerData->mnUpdateTime+pTimerData->mpTimer->mnTimeout) <= nTime )
     106             :             {
     107             :                 // set new update time
     108       33724 :                 pTimerData->mnUpdateTime = nTime;
     109             : 
     110             :                 // if no AutoTimer than stop
     111       33724 :                 if ( !pTimerData->mpTimer->mbAuto )
     112             :                 {
     113       26339 :                     pTimerData->mpTimer->mbActive = false;
     114       26339 :                     pTimerData->mbDelete = true;
     115             :                 }
     116             : 
     117             :                 // call Timeout
     118       33724 :                 pTimerData->mbInTimeout = true;
     119       33724 :                 pTimerData->mpTimer->Timeout();
     120       33724 :                 pTimerData->mbInTimeout = false;
     121             :             }
     122             :         }
     123             : 
     124      149095 :         pTimerData = pTimerData->mpNext;
     125             :     }
     126             : 
     127             :     // determine new time
     128       21960 :     sal_uLong nNewTime = Time::GetSystemTicks();
     129       21960 :     pPrevTimerData = NULL;
     130       21960 :     pTimerData = pSVData->mpFirstTimerData;
     131      193015 :     while ( pTimerData )
     132             :     {
     133             :         // ignore if timer is still in timeout handler
     134      149095 :         if ( pTimerData->mbInTimeout )
     135             :         {
     136           0 :             pPrevTimerData = pTimerData;
     137           0 :             pTimerData = pTimerData->mpNext;
     138             :         }
     139             :         // Was timer destroyed in the meantime?
     140      149095 :         else if ( pTimerData->mbDelete )
     141             :         {
     142       41962 :             if ( pPrevTimerData )
     143       41710 :                 pPrevTimerData->mpNext = pTimerData->mpNext;
     144             :             else
     145         252 :                 pSVData->mpFirstTimerData = pTimerData->mpNext;
     146       41962 :             if ( pTimerData->mpTimer )
     147       22774 :                 pTimerData->mpTimer->mpTimerData = NULL;
     148       41962 :             ImplTimerData* pTempTimerData = pTimerData;
     149       41962 :             pTimerData = pTimerData->mpNext;
     150       41962 :             delete pTempTimerData;
     151             :         }
     152             :         else
     153             :         {
     154      107133 :             pTimerData->mnTimerUpdate = 0;
     155             :             // determine smallest time slot
     156      107133 :             if ( pTimerData->mnUpdateTime == nTime )
     157             :             {
     158       12799 :                 nDeltaTime = pTimerData->mpTimer->mnTimeout;
     159       12799 :                 if ( nDeltaTime < nMinPeriod )
     160        8962 :                     nMinPeriod = nDeltaTime;
     161             :             }
     162             :             else
     163             :             {
     164       94334 :                 nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpTimer->mnTimeout;
     165       94334 :                 if ( nDeltaTime < nNewTime )
     166        9810 :                     nMinPeriod = 1;
     167             :                 else
     168             :                 {
     169       84524 :                     nDeltaTime -= nNewTime;
     170       84524 :                     if ( nDeltaTime < nMinPeriod )
     171       45545 :                         nMinPeriod = nDeltaTime;
     172             :                 }
     173             :             }
     174      107133 :             pPrevTimerData = pTimerData;
     175      107133 :             pTimerData = pTimerData->mpNext;
     176             :         }
     177             :     }
     178             : 
     179             :     // delete clock if no more timers available
     180       21960 :     if ( !pSVData->mpFirstTimerData )
     181             :     {
     182          61 :         pSVData->mpSalTimer->Stop();
     183          61 :         pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     184             :     }
     185             :     else
     186       21899 :         ImplStartTimer( pSVData, nMinPeriod );
     187             : 
     188       21960 :     pSVData->mnTimerUpdate--;
     189       21960 :     pSVData->mbNotAllTimerCalled = false;
     190             : }
     191             : 
     192      248729 : Timer::Timer():
     193             :     mpTimerData(NULL),
     194             :     mnTimeout(1),
     195             :     mbActive(false),
     196      248729 :     mbAuto(false)
     197             : {
     198      248729 : }
     199             : 
     200         417 : Timer::Timer( const Timer& rTimer ):
     201             :     mpTimerData(NULL),
     202             :     mnTimeout(rTimer.mnTimeout),
     203             :     mbActive(false),
     204             :     mbAuto(false),
     205         417 :     maTimeoutHdl(rTimer.maTimeoutHdl)
     206             : {
     207         417 :     if ( rTimer.IsActive() )
     208          38 :         Start();
     209         417 : }
     210             : 
     211      244365 : Timer::~Timer()
     212             : {
     213      240593 :     if ( mpTimerData )
     214             :     {
     215       21084 :         mpTimerData->mbDelete = true;
     216       21084 :         mpTimerData->mpTimer = NULL;
     217             :      }
     218      244365 : }
     219             : 
     220       30845 : void Timer::Timeout()
     221             : {
     222       30845 :     maTimeoutHdl.Call( this );
     223       30845 : }
     224             : 
     225      331518 : void Timer::SetTimeout( sal_uLong nNewTimeout )
     226             : {
     227      331518 :     mnTimeout = nNewTimeout;
     228             : 
     229             :     // if timer is active then renew clock
     230      331518 :     if ( mbActive )
     231             :     {
     232       14513 :         ImplSVData* pSVData = ImplGetSVData();
     233       14513 :         if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
     234           0 :             ImplStartTimer( pSVData, mnTimeout );
     235             :     }
     236      331518 : }
     237             : 
     238      539070 : void Timer::Start()
     239             : {
     240      539070 :     mbActive = true;
     241             : 
     242      539070 :     ImplSVData* pSVData = ImplGetSVData();
     243      539070 :     if ( !mpTimerData )
     244             :     {
     245       44386 :         if ( !pSVData->mpFirstTimerData )
     246             :         {
     247         272 :             pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     248         272 :             if( ! pSVData->mpSalTimer )
     249             :             {
     250         211 :                 pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
     251         211 :                 pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
     252             :             }
     253             :         }
     254             : 
     255             :         // insert timer and start
     256       44386 :         mpTimerData = new ImplTimerData;
     257       44386 :         mpTimerData->mpTimer        = this;
     258       44386 :         mpTimerData->mnUpdateTime   = Time::GetSystemTicks();
     259       44386 :         mpTimerData->mnTimerUpdate  = pSVData->mnTimerUpdate;
     260       44386 :         mpTimerData->mbDelete       = false;
     261       44386 :         mpTimerData->mbInTimeout    = false;
     262             : 
     263             :         // insert last due to SFX!
     264       44386 :         ImplTimerData* pPrev = NULL;
     265       44386 :         ImplTimerData* pData = pSVData->mpFirstTimerData;
     266      887347 :         while ( pData )
     267             :         {
     268      798575 :             pPrev = pData;
     269      798575 :             pData = pData->mpNext;
     270             :         }
     271       44386 :         mpTimerData->mpNext = NULL;
     272       44386 :         if ( pPrev )
     273       44114 :             pPrev->mpNext = mpTimerData;
     274             :         else
     275         272 :             pSVData->mpFirstTimerData = mpTimerData;
     276             : 
     277       44386 :         if ( mnTimeout < pSVData->mnTimerPeriod )
     278       14980 :             ImplStartTimer( pSVData, mnTimeout );
     279             :     }
     280      494684 :     else if( !mpTimerData->mpTimer ) // TODO: remove when guilty found
     281             :     {
     282             :         OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
     283             :     }
     284             :     else
     285             :     {
     286      494684 :         mpTimerData->mnUpdateTime    = Time::GetSystemTicks();
     287      494684 :         mpTimerData->mnTimerUpdate   = pSVData->mnTimerUpdate;
     288      494684 :         mpTimerData->mbDelete        = false;
     289             :     }
     290      539070 : }
     291             : 
     292      463864 : void Timer::Stop()
     293             : {
     294      463864 :     mbActive = false;
     295             : 
     296      463864 :     if ( mpTimerData )
     297      204789 :         mpTimerData->mbDelete = true;
     298      463864 : }
     299             : 
     300          49 : Timer& Timer::operator=( const Timer& rTimer )
     301             : {
     302          49 :     if ( IsActive() )
     303          12 :         Stop();
     304             : 
     305          49 :     mbActive        = false;
     306          49 :     mnTimeout       = rTimer.mnTimeout;
     307          49 :     maTimeoutHdl    = rTimer.maTimeoutHdl;
     308             : 
     309          49 :     if ( rTimer.IsActive() )
     310          14 :         Start();
     311             : 
     312          49 :     return *this;
     313             : }
     314             : 
     315       18075 : AutoTimer::AutoTimer()
     316             : {
     317       18075 :     mbAuto = true;
     318       18075 : }
     319             : 
     320         417 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
     321             : {
     322         417 :     mbAuto = true;
     323         417 : }
     324             : 
     325          49 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
     326             : {
     327          49 :     Timer::operator=( rTimer );
     328          49 :     return *this;
     329             : }
     330             : 
     331             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10