From a60f687b5dd684260fc976c1216d65d30e77e5de Mon Sep 17 00:00:00 2001 From: Jan-Marek Glogowski Date: Tue, 26 Sep 2017 19:06:51 +0200 Subject: tdf#112605 OSX refactor SalAquaTimer Drops all the static calls and variables from SalAquaTimer and moves all timer handling logic inside the class. This also fixes the leak in timerElapsed. Change-Id: Ie7a1a8fffb70b8579ec6876eed10a275d2f06d27 Reviewed-on: https://gerrit.libreoffice.org/42913 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski --- vcl/osx/salinst.cxx | 23 +++++------- vcl/osx/salnstimer.mm | 14 +++---- vcl/osx/saltimer.cxx | 101 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 80 insertions(+), 58 deletions(-) (limited to 'vcl/osx') diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index 89e3ae6d4e82..8af988a1de77 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -426,11 +426,13 @@ bool AquaSalInstance::IsMainThread() const void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent ) { + AquaSalTimer *pTimer = static_cast( ImplGetSVData()->maSchedCtx.mpSalTimer ); int nSubtype = [pEvent subtype]; switch( nSubtype ) { case AppStartTimerEvent: - AquaSalTimer::handleStartTimerEvent( pEvent ); + if ( pTimer ) + pTimer->handleStartTimerEvent( pEvent ); break; case AppEndLoopEvent: [NSApp stop: NSApp]; @@ -450,7 +452,8 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent ) break; } case DispatchTimerEvent: - AquaSalTimer::handleDispatchTimerEvent(); + if ( pTimer ) + pTimer->handleDispatchTimerEvent( pEvent ); break; #if !HAVE_FEATURE_MACOSX_SANDBOX case AppleRemoteControlEvent: // Defined in @@ -566,7 +569,7 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents) { // handle available events NSEvent* pEvent = nil; - NSTimeInterval now = [[NSProcessInfo processInfo]systemUptime]; + NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime]; do { SolarMutexReleaser aReleaser; @@ -598,12 +601,11 @@ SAL_WNODEPRECATED_DECLARATIONS_POP { SolarMutexReleaser aReleaser; - NSDate* pDt = AquaSalTimer::pRunningTimer ? [AquaSalTimer::pRunningTimer fireDate] : [NSDate distantFuture]; SAL_WNODEPRECATED_DECLARATIONS_PUSH // 'NSAnyEventMask' is deprecated: first deprecated in macOS 10.12 pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask SAL_WNODEPRECATED_DECLARATIONS_POP - untilDate: pDt + untilDate: [NSDate distantFuture] inMode: NSDefaultRunLoopMode dequeue: YES]; if( pEvent ) @@ -682,14 +684,9 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType ) if( nType & VclInputFlags::TIMER ) { - if( AquaSalTimer::pRunningTimer ) - { - NSDate* pDt = [AquaSalTimer::pRunningTimer fireDate]; - if( pDt && [pDt timeIntervalSinceNow] < 0 ) - { - return true; - } - } + AquaSalTimer *pTimer = static_cast( ImplGetSVData()->maSchedCtx.mpSalTimer ); + if (pTimer && pTimer->IsTimerElapsed()) + return true; } unsigned/*NSUInteger*/ nEventMask = 0; diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm index c9b657dcd776..9647bb6b87c1 100644 --- a/vcl/osx/salnstimer.mm +++ b/vcl/osx/salnstimer.mm @@ -27,16 +27,12 @@ @implementation TimerCallbackCaller --(void)timerElapsed:(NSTimer*)pTimer +-(void)timerElapsed:(NSTimer*)pNSTimer { - (void)pTimer; - // nil the timer, as it is just invalidated after the firing function - AquaSalTimer::pRunningTimer = nil; - const AquaSalInstance *pInst = GetSalData()->mpFirstInstance; - if (pInst->mbIsLiveResize) - AquaSalTimer::handleDispatchTimerEvent(); - else - ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, YES ); + (void) pNSTimer; + AquaSalTimer *pTimer = static_cast( ImplGetSVData()->maSchedCtx.mpSalTimer ); + if (pTimer) + pTimer->handleTimerElapsed(); } @end diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx index 3667fd5dd3f5..4bc9706fc39d 100644 --- a/vcl/osx/saltimer.cxx +++ b/vcl/osx/saltimer.cxx @@ -20,6 +20,7 @@ #include #include +#include #include "osx/saltimer.h" #include "osx/salnstimer.h" @@ -27,9 +28,6 @@ #include "osx/salframe.h" #include "osx/salinst.h" -NSTimer* AquaSalTimer::pRunningTimer = nil; - -static void ImplSalStopTimer(); void ImplNSAppPostEvent( short nEventId, BOOL bAtStart, int nUserData ) { @@ -73,7 +71,16 @@ SAL_WNODEPRECATED_DECLARATIONS_POP [NSApp postEvent: pEvent atStart: bAtStart]; } -static void ImplSalStartTimer( sal_uLong nMS ) +void AquaSalTimer::queueDispatchTimerEvent( bool bAtStart ) +{ + Stop(); + m_nTimerStartTicks = tools::Time::GetMonotonicTicks() % SAL_MAX_INT32; + if ( 0 == m_nTimerStartTicks ) + m_nTimerStartTicks++; + ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, bAtStart, m_nTimerStartTicks ); +} + +void AquaSalTimer::Start( sal_uLong nMS ) { SalData* pSalData = GetSalData(); @@ -84,27 +91,26 @@ static void ImplSalStartTimer( sal_uLong nMS ) } if ( 0 == nMS && !pSalData->mpFirstInstance->mbIsLiveResize ) - { - ImplSalStopTimer(); - ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, NO ); - } + queueDispatchTimerEvent( NO ); else { NSTimeInterval aTI = double(nMS) / 1000.0; - if( AquaSalTimer::pRunningTimer != nil ) + if( m_pRunningTimer != nil ) { - if ([AquaSalTimer::pRunningTimer isValid] && rtl::math::approxEqual( - [AquaSalTimer::pRunningTimer timeInterval], aTI)) + if ([m_pRunningTimer isValid] && rtl::math::approxEqual( + [m_pRunningTimer timeInterval], aTI)) { // set new fire date - [AquaSalTimer::pRunningTimer setFireDate: [NSDate dateWithTimeIntervalSinceNow: aTI]]; + [m_pRunningTimer setFireDate: [NSDate dateWithTimeIntervalSinceNow: aTI]]; } else - ImplSalStopTimer(); + Stop(); } - if( AquaSalTimer::pRunningTimer == nil ) + else + Stop(); + if( m_pRunningTimer == nil ) { - AquaSalTimer::pRunningTimer = [[NSTimer scheduledTimerWithTimeInterval: aTI + m_pRunningTimer = [[NSTimer scheduledTimerWithTimeInterval: aTI target: [[[TimerCallbackCaller alloc] init] autorelease] selector: @selector(timerElapsed:) userInfo: nil @@ -113,22 +119,25 @@ static void ImplSalStartTimer( sal_uLong nMS ) /* #i84055# add timer to tracking run loop mode, so they also elapse while e.g. life resize */ - [[NSRunLoop currentRunLoop] addTimer: AquaSalTimer::pRunningTimer forMode: NSEventTrackingRunLoopMode]; + [[NSRunLoop currentRunLoop] addTimer: m_pRunningTimer forMode: NSEventTrackingRunLoopMode]; } } } -static void ImplSalStopTimer() +void AquaSalTimer::Stop() { - if( AquaSalTimer::pRunningTimer != nil ) + assert( GetSalData()->mpFirstInstance->IsMainThread() ); + + if( m_pRunningTimer != nil ) { - [AquaSalTimer::pRunningTimer invalidate]; - [AquaSalTimer::pRunningTimer release]; - AquaSalTimer::pRunningTimer = nil; + [m_pRunningTimer invalidate]; + [m_pRunningTimer release]; + m_pRunningTimer = nil; } + m_nTimerStartTicks = 0; } -void AquaSalTimer::handleDispatchTimerEvent() +void AquaSalTimer::callTimerCallback() { ImplSVData* pSVData = ImplGetSVData(); SolarMutexGuard aGuard; @@ -136,6 +145,23 @@ void AquaSalTimer::handleDispatchTimerEvent() pSVData->maSchedCtx.mpSalTimer->CallCallback(); } +void AquaSalTimer::handleTimerElapsed() +{ + // Stop the timer, as it is just invalidated after the firing function + Stop(); + + if ( GetSalData()->mpFirstInstance->mbIsLiveResize ) + callTimerCallback(); + else + queueDispatchTimerEvent( YES ); +} + +void AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent ) +{ + if (m_nTimerStartTicks == [pEvent data1]) + callTimerCallback(); +} + void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent ) { ImplSVData* pSVData = ImplGetSVData(); @@ -143,30 +169,33 @@ void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent ) { NSTimeInterval posted = [pEvent timestamp] + NSTimeInterval([pEvent data1])/1000.0; NSTimeInterval current = [NSDate timeIntervalSinceReferenceDate]; - if( (posted - current) <= 0.0 ) - handleDispatchTimerEvent(); - else - ImplSalStartTimer( sal_uLong( [pEvent data1] ) ); + sal_uLong nTimeoutMS = 0; + if( (posted - current) > 0.0 ) + nTimeoutMS = ceil( (posted - current) * 1000 ); + Start( nTimeoutMS ); } } -AquaSalTimer::AquaSalTimer( ) -{ -} - -AquaSalTimer::~AquaSalTimer() +bool AquaSalTimer::IsTimerElapsed() const { - ImplSalStopTimer(); + assert( !(m_nTimerStartTicks && m_pRunningTimer) ); + if ( 0 != m_nTimerStartTicks ) + return true; + if ( !m_pRunningTimer ) + return false; + NSDate* pDt = [m_pRunningTimer fireDate]; + return pDt && ([pDt timeIntervalSinceNow] < 0); } -void AquaSalTimer::Start( sal_uLong nMS ) +AquaSalTimer::AquaSalTimer( ) + : m_pRunningTimer( nil ) + , m_nTimerStartTicks( 0 ) { - ImplSalStartTimer( nMS ); } -void AquaSalTimer::Stop() +AquaSalTimer::~AquaSalTimer() { - ImplSalStopTimer(); + Stop(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit