LCOV - code coverage report
Current view: top level - libreoffice/vcl/source/app - timer.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 157 163 96.3 %
Date: 2012-12-17 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             : 
      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           8 : void Timer::ImplDeInitTimer()
      52             : {
      53           8 :     ImplSVData*     pSVData = ImplGetSVData();
      54           8 :     ImplTimerData*  pTimerData = pSVData->mpFirstTimerData;
      55             : 
      56           8 :     if ( pTimerData )
      57             :     {
      58          14 :         do
      59             :         {
      60          14 :             ImplTimerData* pTempTimerData = pTimerData;
      61          14 :             if ( pTimerData->mpSVTimer )
      62             :             {
      63           5 :                 pTimerData->mpSVTimer->mbActive = sal_False;
      64           5 :                 pTimerData->mpSVTimer->mpTimerData = NULL;
      65             :             }
      66          14 :             pTimerData = pTimerData->mpNext;
      67          14 :             delete pTempTimerData;
      68             :         }
      69             :         while ( pTimerData );
      70             : 
      71           8 :         pSVData->mpFirstTimerData   = NULL;
      72           8 :         pSVData->mnTimerPeriod      = 0;
      73           8 :         delete pSVData->mpSalTimer;
      74           8 :         pSVData->mpSalTimer = NULL;
      75             :     }
      76           8 : }
      77             : 
      78             : // -----------------------------------------------------------------------
      79             : 
      80        2321 : static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
      81             : {
      82        2321 :     if ( !nMS )
      83         518 :         nMS = 1;
      84             : 
      85        2321 :     if ( nMS != pSVData->mnTimerPeriod )
      86             :     {
      87        1415 :         pSVData->mnTimerPeriod = nMS;
      88        1415 :         pSVData->mpSalTimer->Start( nMS );
      89             :     }
      90        2321 : }
      91             : 
      92             : // -----------------------------------------------------------------------
      93             : 
      94        1116 : void Timer::ImplTimerCallbackProc()
      95             : {
      96        1116 :     ImplSVData*     pSVData = ImplGetSVData();
      97             :     ImplTimerData*  pTimerData;
      98             :     ImplTimerData*  pPrevTimerData;
      99        1116 :     sal_uLong           nMinPeriod = MAX_TIMER_PERIOD;
     100             :     sal_uLong           nDeltaTime;
     101        1116 :     sal_uLong           nTime = Time::GetSystemTicks();
     102             : 
     103        1116 :     if ( pSVData->mbNoCallTimer )
     104        1116 :         return;
     105             : 
     106        1116 :     pSVData->mnTimerUpdate++;
     107        1116 :     pSVData->mbNotAllTimerCalled = sal_True;
     108             : 
     109             :     // find timer where the timer handler needs to be called
     110        1116 :     pTimerData = pSVData->mpFirstTimerData;
     111       38638 :     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      107147 :         if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) &&
     116       70741 :              !pTimerData->mbDelete && !pTimerData->mbInTimeout )
     117             :         {
     118             :             // time has expired
     119       34624 :             if ( (pTimerData->mnUpdateTime+pTimerData->mpSVTimer->mnTimeout) <= nTime )
     120             :             {
     121             :                 // set new update time
     122       12191 :                 pTimerData->mnUpdateTime = nTime;
     123             : 
     124             :                 // if no AutoTimer than stop
     125       12191 :                 if ( !pTimerData->mpSVTimer->mbAuto )
     126             :                 {
     127       11619 :                     pTimerData->mpSVTimer->mbActive = sal_False;
     128       11619 :                     pTimerData->mbDelete = sal_True;
     129             :                 }
     130             : 
     131             :                 // call Timeout
     132       12191 :                 pTimerData->mbInTimeout = sal_True;
     133       12191 :                 pTimerData->mpSVTimer->Timeout();
     134       12191 :                 pTimerData->mbInTimeout = sal_False;
     135             :             }
     136             :         }
     137             : 
     138       36406 :         pTimerData = pTimerData->mpNext;
     139             :     }
     140             : 
     141             :     // determine new time
     142        1116 :     sal_uLong nNewTime = Time::GetSystemTicks();
     143        1116 :     pPrevTimerData = NULL;
     144        1116 :     pTimerData = pSVData->mpFirstTimerData;
     145       38638 :     while ( pTimerData )
     146             :     {
     147             :         // ignore if timer is still in timeout handler
     148       36406 :         if ( pTimerData->mbInTimeout )
     149             :         {
     150           0 :             pPrevTimerData = pTimerData;
     151           0 :             pTimerData = pTimerData->mpNext;
     152             :         }
     153             :         // Was timer destroyed in the meantime?
     154       36406 :         else if ( pTimerData->mbDelete )
     155             :         {
     156        4340 :             if ( pPrevTimerData )
     157        4285 :                 pPrevTimerData->mpNext = pTimerData->mpNext;
     158             :             else
     159          55 :                 pSVData->mpFirstTimerData = pTimerData->mpNext;
     160        4340 :             if ( pTimerData->mpSVTimer )
     161        3474 :                 pTimerData->mpSVTimer->mpTimerData = NULL;
     162        4340 :             ImplTimerData* pTempTimerData = pTimerData;
     163        4340 :             pTimerData = pTimerData->mpNext;
     164        4340 :             delete pTempTimerData;
     165             :         }
     166             :         else
     167             :         {
     168       32066 :             pTimerData->mnTimerUpdate = 0;
     169             :             // determine smallest time slot
     170       32066 :             if ( pTimerData->mnUpdateTime == nTime )
     171             :             {
     172         975 :                 nDeltaTime = pTimerData->mpSVTimer->mnTimeout;
     173         975 :                 if ( nDeltaTime < nMinPeriod )
     174         273 :                     nMinPeriod = nDeltaTime;
     175             :             }
     176             :             else
     177             :             {
     178       31091 :                 nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpSVTimer->mnTimeout;
     179       31091 :                 if ( nDeltaTime < nNewTime )
     180        4159 :                     nMinPeriod = 1;
     181             :                 else
     182             :                 {
     183       26932 :                     nDeltaTime -= nNewTime;
     184       26932 :                     if ( nDeltaTime < nMinPeriod )
     185        2945 :                         nMinPeriod = nDeltaTime;
     186             :                 }
     187             :             }
     188       32066 :             pPrevTimerData = pTimerData;
     189       32066 :             pTimerData = pTimerData->mpNext;
     190             :         }
     191             :     }
     192             : 
     193             :     // delete clock if no more timers available
     194        1116 :     if ( !pSVData->mpFirstTimerData )
     195             :     {
     196           6 :         pSVData->mpSalTimer->Stop();
     197           6 :         pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     198             :     }
     199             :     else
     200        1110 :         ImplStartTimer( pSVData, nMinPeriod );
     201             : 
     202        1116 :     pSVData->mnTimerUpdate--;
     203        1116 :     pSVData->mbNotAllTimerCalled = sal_False;
     204             : }
     205             : 
     206             : // =======================================================================
     207             : 
     208       64811 : Timer::Timer()
     209             : {
     210       64811 :     mpTimerData     = NULL;
     211       64811 :     mnTimeout       = 1;
     212       64811 :     mbAuto          = sal_False;
     213       64811 :     mbActive        = sal_False;
     214       64811 : }
     215             : 
     216             : // -----------------------------------------------------------------------
     217             : 
     218          60 : Timer::Timer( const Timer& rTimer )
     219             : {
     220          60 :     mpTimerData     = NULL;
     221          60 :     mnTimeout       = rTimer.mnTimeout;
     222          60 :     mbAuto          = sal_False;
     223          60 :     mbActive        = sal_False;
     224          60 :     maTimeoutHdl    = rTimer.maTimeoutHdl;
     225             : 
     226          60 :     if ( rTimer.IsActive() )
     227           0 :         Start();
     228          60 : }
     229             : 
     230             : // -----------------------------------------------------------------------
     231             : 
     232       44012 : Timer::~Timer()
     233             : {
     234       43446 :     if ( mpTimerData )
     235             :     {
     236        1663 :         mpTimerData->mbDelete = sal_True;
     237        1663 :         mpTimerData->mpSVTimer = NULL;
     238             :     }
     239       44012 : }
     240             : 
     241             : // -----------------------------------------------------------------------
     242             : 
     243       12187 : void Timer::Timeout()
     244             : {
     245       12187 :     maTimeoutHdl.Call( this );
     246       12187 : }
     247             : 
     248             : // -----------------------------------------------------------------------
     249             : 
     250       73323 : void Timer::SetTimeout( sal_uLong nNewTimeout )
     251             : {
     252       73323 :     mnTimeout = nNewTimeout;
     253             : 
     254             :     // if timer is active then renew clock
     255       73323 :     if ( mbActive )
     256             :     {
     257        3222 :         ImplSVData* pSVData = ImplGetSVData();
     258        3222 :         if ( !pSVData->mnTimerUpdate && (mnTimeout < pSVData->mnTimerPeriod) )
     259           0 :             ImplStartTimer( pSVData, mnTimeout );
     260             :     }
     261       73323 : }
     262             : 
     263             : // -----------------------------------------------------------------------
     264             : 
     265       43962 : void Timer::Start()
     266             : {
     267       43962 :     mbActive = sal_True;
     268             : 
     269       43962 :     ImplSVData* pSVData = ImplGetSVData();
     270       43962 :     if ( !mpTimerData )
     271             :     {
     272        6570 :         if ( !pSVData->mpFirstTimerData )
     273             :         {
     274          78 :             pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
     275          78 :             if( ! pSVData->mpSalTimer )
     276             :             {
     277          72 :                 pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
     278          72 :                 pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc );
     279             :             }
     280             :         }
     281             : 
     282             :         // insert timer and start
     283        6570 :         mpTimerData                 = new ImplTimerData;
     284        6570 :         mpTimerData->mpSVTimer      = this;
     285        6570 :         mpTimerData->mnUpdateTime   = Time::GetSystemTicks();
     286        6570 :         mpTimerData->mnTimerUpdate  = pSVData->mnTimerUpdate;
     287        6570 :         mpTimerData->mbDelete       = sal_False;
     288        6570 :         mpTimerData->mbInTimeout    = sal_False;
     289             : 
     290             :         // insert last due to SFX!
     291        6570 :         ImplTimerData* pPrev = NULL;
     292        6570 :         ImplTimerData* pData = pSVData->mpFirstTimerData;
     293      463833 :         while ( pData )
     294             :         {
     295      450693 :             pPrev = pData;
     296      450693 :             pData = pData->mpNext;
     297             :         }
     298        6570 :         mpTimerData->mpNext = NULL;
     299        6570 :         if ( pPrev )
     300        6492 :             pPrev->mpNext = mpTimerData;
     301             :         else
     302          78 :             pSVData->mpFirstTimerData = mpTimerData;
     303             : 
     304        6570 :         if ( mnTimeout < pSVData->mnTimerPeriod )
     305        1211 :             ImplStartTimer( pSVData, mnTimeout );
     306             :     }
     307       37392 :     else if( !mpTimerData->mpSVTimer ) // TODO: remove when guilty found
     308             :     {
     309             :         OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
     310             :     }
     311             :     else
     312             :     {
     313       37392 :         mpTimerData->mnUpdateTime    = Time::GetSystemTicks();
     314       37392 :         mpTimerData->mnTimerUpdate   = pSVData->mnTimerUpdate;
     315       37392 :         mpTimerData->mbDelete        = sal_False;
     316             :     }
     317       43962 : }
     318             : 
     319             : // -----------------------------------------------------------------------
     320             : 
     321       68611 : void Timer::Stop()
     322             : {
     323       68611 :     mbActive = sal_False;
     324             : 
     325       68611 :     if ( mpTimerData )
     326       19871 :         mpTimerData->mbDelete = sal_True;
     327       68611 : }
     328             : 
     329             : // -----------------------------------------------------------------------
     330             : 
     331          18 : Timer& Timer::operator=( const Timer& rTimer )
     332             : {
     333          18 :     if ( IsActive() )
     334           0 :         Stop();
     335             : 
     336          18 :     mbActive        = sal_False;
     337          18 :     mnTimeout       = rTimer.mnTimeout;
     338          18 :     maTimeoutHdl    = rTimer.maTimeoutHdl;
     339             : 
     340          18 :     if ( rTimer.IsActive() )
     341           0 :         Start();
     342             : 
     343          18 :     return *this;
     344             : }
     345             : 
     346             : // =======================================================================
     347             : 
     348        3222 : AutoTimer::AutoTimer()
     349             : {
     350        3222 :     mbAuto = sal_True;
     351        3222 : }
     352             : 
     353             : // -----------------------------------------------------------------------
     354             : 
     355          60 : AutoTimer::AutoTimer( const AutoTimer& rTimer ) : Timer( rTimer )
     356             : {
     357          60 :     mbAuto = sal_True;
     358          60 : }
     359             : 
     360             : // -----------------------------------------------------------------------
     361             : 
     362          18 : AutoTimer& AutoTimer::operator=( const AutoTimer& rTimer )
     363             : {
     364          18 :     Timer::operator=( rTimer );
     365          18 :     return *this;
     366             : }
     367             : 
     368             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10