[Libreoffice-commits] core.git: vcl/inc vcl/osx

Jan-Marek Glogowski glogow at fbihome.de
Fri Sep 29 17:08:00 UTC 2017


 vcl/inc/osx/saltimer.h |   14 ++++--
 vcl/osx/salinst.cxx    |   23 ++++-------
 vcl/osx/salnstimer.mm  |   14 ++----
 vcl/osx/saltimer.cxx   |  101 +++++++++++++++++++++++++++++++------------------
 4 files changed, 90 insertions(+), 62 deletions(-)

New commits:
commit a60f687b5dd684260fc976c1216d65d30e77e5de
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Sep 26 19:06:51 2017 +0200

    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 <ci at libreoffice.org>
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>

diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h
index 86964115d648..f70bd65491b8 100644
--- a/vcl/inc/osx/saltimer.h
+++ b/vcl/inc/osx/saltimer.h
@@ -43,6 +43,12 @@ public:
 
 class AquaSalTimer : public SalTimer
 {
+    NSTimer    *m_pRunningTimer;
+    sal_Int32   m_nTimerStartTicks;  ///< system ticks at timer start % SAL_MAX_INT32
+
+    void queueDispatchTimerEvent( bool bAtStart );
+    void callTimerCallback();
+
 public:
     AquaSalTimer();
     virtual ~AquaSalTimer() override;
@@ -50,11 +56,11 @@ public:
     void Start( sal_uLong nMS ) override;
     void Stop() override;
 
-    static void handleStartTimerEvent( NSEvent* pEvent );
-    static void handleDispatchTimerEvent();
+    void handleStartTimerEvent( NSEvent* pEvent );
+    void handleDispatchTimerEvent( NSEvent* pEvent );
+    void handleTimerElapsed();
 
-    static NSTimer* pRunningTimer;
-    static bool bDispatchTimer;
+    bool IsTimerElapsed() const;
 };
 
 #endif // INCLUDED_VCL_INC_OSX_SALTIMER_H
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<AquaSalTimer*>( 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 <apple_remote/RemoteMainController.h>
@@ -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<AquaSalTimer*>( 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<AquaSalTimer*>( 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 <sal/config.h>
 
 #include <rtl/math.hxx>
+#include <tools/time.hxx>
 
 #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: */


More information about the Libreoffice-commits mailing list