[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 29 commits - autogen.sh avmedia/source basic/qa bin/lo-commit-stat bin/lo-pack-sources canvas/Library_canvastools.mk canvas/source chart2/source cli_ure/qa comphelper/source compilerplugins/clang configure.ac connectivity/source cui/source dbaccess/Module_dbaccess.mk dbaccess/source desktop/source drawinglayer/source editeng/source extensions/source filter/source fpicker/source framework/source i18npool/source include/comphelper include/oox include/osl include/sal include/svtools include/svx include/tools include/vcl lotuswordpro/source m4/libgcrypt.m4 odk/config odk/docs odk/examples offapi/com officecfg/registry oovbaapi/ooo oox/source qadevOOo/tests README.cross registry/source sal/Library_sal.mk sal/osl sal/test sal/textenc sal/util sc/inc sc/qa sc/source sdext/source sd/Module_sd.mk sd/qa sd/source sfx2/classification sfx2/doc sfx2/inc sfx2/source slideshow/source solenv/bin store/source svl/source svtools/source svx/sou rce sw/inc sw/qa sw/sdi sw/source sw/uiconfig toolkit/source toolkit/test tools/source ucb/qa ucb/source udkapi/com unotools/source vcl/android vcl/headless vcl/inc vcl/ios vcl/osx vcl/README.scheduler vcl/source vcl/unx vcl/win writerfilter/inc writerfilter/source writerperfect/Library_wpftwriter.mk writerperfect/source xmloff/source

Jan-Marek Glogowski glogow at fbihome.de
Fri Aug 18 15:51:50 UTC 2017


Rebased ref, commits from common ancestor:
commit 114e85200e654c11e5351454a87b40575a189c14
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Aug 18 17:49:23 2017 +0200

    Encapsulate SolarMutex
    
    Change-Id: Ib0bf474aa833ff4dd4266b5fd8553701a64f79c2

diff --git a/comphelper/source/misc/solarmutex.cxx b/comphelper/source/misc/solarmutex.cxx
index 4b573078dffd..b2a77bfbb637 100644
--- a/comphelper/source/misc/solarmutex.cxx
+++ b/comphelper/source/misc/solarmutex.cxx
@@ -42,6 +42,66 @@ SolarMutex *SolarMutex::get()
     return pSolarMutex;
 }
 
+GenericSolarMutex::GenericSolarMutex()
+    : m_nCount( 0 )
+    , m_nThreadId( 0 )
+    , m_aBeforeReleaseHandler( nullptr )
+{
+    setSolarMutex( this );
+}
+
+GenericSolarMutex::~GenericSolarMutex()
+{
+    setSolarMutex( nullptr );
+}
+
+void GenericSolarMutex::doAcquire( const sal_uInt32 nLockCount )
+{
+    assert ( nLockCount > 0 );
+    for ( sal_uInt32 n = nLockCount; n ; --n )
+        m_aMutex.acquire();
+    m_nThreadId = osl::Thread::getCurrentIdentifier();
+    m_nCount += nLockCount;
+}
+
+sal_uInt32 GenericSolarMutex::doRelease( bool bUnlockAll )
+{
+    assert( m_nCount >  0 );
+    assert( m_nThreadId == osl::Thread::getCurrentIdentifier() );
+
+    const sal_uInt32 nCount = bUnlockAll ? m_nCount : 1;
+    m_nCount -= nCount;
+
+    if ( 0 == m_nCount )
+    {
+        if ( m_aBeforeReleaseHandler )
+            m_aBeforeReleaseHandler();
+        m_nThreadId = 0;
+    }
+
+    for ( sal_uInt32 n = nCount ; n ; --n )
+        m_aMutex.release();
+
+    return nCount;
+}
+
+bool GenericSolarMutex::check()
+{
+    return m_nThreadId == osl::Thread::getCurrentIdentifier();
+}
+
+bool GenericSolarMutex::tryToAcquire()
+{
+    if ( m_aMutex.tryToAcquire() )
+    {
+        m_nThreadId = osl::Thread::getCurrentIdentifier();
+        m_nCount++;
+        return true;
+    }
+    else
+        return false;
+}
+
 } // namespace comphelper
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/dbaccess/Module_dbaccess.mk b/dbaccess/Module_dbaccess.mk
index d9f80fc11540..20a11fdc512d 100644
--- a/dbaccess/Module_dbaccess.mk
+++ b/dbaccess/Module_dbaccess.mk
@@ -43,9 +43,9 @@ $(eval $(call gb_Module_add_check_targets,dbaccess,\
 	CppunitTest_dbaccess_empty_stdlib_save \
 	CppunitTest_dbaccess_nolib_save \
 	CppunitTest_dbaccess_macros_test \
-	$(if $(ENABLE_JAVA), \
-		CppunitTest_dbaccess_RowSetClones) \
 ))
+#	$(if $(ENABLE_JAVA), \
+#		CppunitTest_dbaccess_RowSetClones) \
 
 ifeq ($(ENABLE_JAVA),TRUE)
 $(eval $(call gb_Module_add_check_targets,dbaccess,\
diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx
index bbbe69d5f52f..7086aac15478 100644
--- a/dbaccess/source/core/dataaccess/ModelImpl.cxx
+++ b/dbaccess/source/core/dataaccess/ModelImpl.cxx
@@ -92,14 +92,17 @@ VosMutexFacade::VosMutexFacade( ::osl::Mutex& _rMutex )
 {
 }
 
-void VosMutexFacade::acquire()
+void VosMutexFacade::doAcquire( sal_uInt32 nLockCount )
 {
+    assert( 1 == nLockCount ); (void) nLockCount;
     m_rMutex.acquire();
 }
 
-void VosMutexFacade::release()
+sal_uInt32 VosMutexFacade::doRelease( bool bUnlockAll )
 {
+    assert( !bUnlockAll ); (void) bUnlockAll;
     m_rMutex.release();
+    return 1;
 }
 
 bool VosMutexFacade::tryToAcquire()
@@ -107,6 +110,11 @@ bool VosMutexFacade::tryToAcquire()
     return m_rMutex.tryToAcquire();
 }
 
+bool VosMutexFacade::check()
+{
+    return true;
+}
+
 // DocumentStorageAccess
 class DocumentStorageAccess : public ::cppu::WeakImplHelper<   XDocumentSubStorageSupplier
                                                            ,   XTransactionListener >
diff --git a/dbaccess/source/core/dataaccess/ModelImpl.hxx b/dbaccess/source/core/dataaccess/ModelImpl.hxx
index 130bb5493a10..fc1dd0e4b162 100644
--- a/dbaccess/source/core/dataaccess/ModelImpl.hxx
+++ b/dbaccess/source/core/dataaccess/ModelImpl.hxx
@@ -118,7 +118,7 @@ class ODatabaseContext;
 class OSharedConnectionManager;
 
 // VosMutexFacade
-/** a class which provides an IMutex interface to an OSL-based mutex
+/** a class which provides an SolarMutex interface to an OSL-based mutex
 */
 class VosMutexFacade : public comphelper::SolarMutex
 {
@@ -128,9 +128,12 @@ public:
     */
     explicit VosMutexFacade( ::osl::Mutex& _rMutex );
 
-    virtual void acquire() override;
-    virtual void release() override;
     virtual bool tryToAcquire() override;
+    virtual bool check() override;
+
+protected:
+    virtual void doAcquire( sal_uInt32 nLockCount ) override;
+    virtual sal_uInt32 doRelease( bool bUnlockAll ) override;
 
 private:
     ::osl::Mutex&   m_rMutex;
diff --git a/include/comphelper/solarmutex.hxx b/include/comphelper/solarmutex.hxx
index 48453de915e4..ede845c666d2 100644
--- a/include/comphelper/solarmutex.hxx
+++ b/include/comphelper/solarmutex.hxx
@@ -22,10 +22,13 @@
 
 #include <sal/config.h>
 
+#include <osl/thread.hxx>
+#include <osl/mutex.hxx>
 #include <comphelper/comphelperdllapi.h>
 
 namespace comphelper {
 
+
 /**
  * Abstract SolarMutex interface, needed for VCL's
  * Application::GetSolarMutex().
@@ -37,29 +40,63 @@ namespace comphelper {
  */
 class COMPHELPER_DLLPUBLIC SolarMutex {
 public:
-    virtual void acquire() = 0;
+    typedef void (*BeforeReleaseHandler) ();
 
-    virtual void release() = 0;
+    void acquire( sal_uInt32 nLockCount = 1 ) { doAcquire( nLockCount ); }
+    sal_uInt32 release( bool bReleaseAll = false ) { return doRelease( bReleaseAll ); }
 
     virtual bool tryToAcquire() = 0;
 
+    virtual bool check() = 0;
+
     /// Help components to get the SolarMutex easily.
     static SolarMutex *get();
 
-    /// semi-private: allow VCL to push its one-big-lock down here.
-    static void setSolarMutex( SolarMutex *pMutex );
-
 protected:
     SolarMutex();
-
     virtual ~SolarMutex();
+
+    /// allow VCL to push its one-big-lock down here.
+    static void setSolarMutex( SolarMutex *pMutex );
+
+    virtual sal_uInt32 doRelease( bool bReleaseAll ) = 0;
+    virtual void doAcquire( sal_uInt32 nLockCount ) = 0;
+
 private:
     SolarMutex(const SolarMutex&) = delete;
     SolarMutex& operator=(const SolarMutex&) = delete;
 };
 
+class COMPHELPER_DLLPUBLIC GenericSolarMutex
+    : public SolarMutex
+{
+public:
+    void SetBeforeReleaseHandler( const BeforeReleaseHandler& rLink )
+         { m_aBeforeReleaseHandler = rLink; }
+
+    virtual bool tryToAcquire() override;
+    virtual bool check() override;
+
+    sal_uInt32 getCount() const { return m_nCount; }
+
+protected:
+    osl::Mutex           m_aMutex;
+    sal_uInt32           m_nCount;
+    oslThreadIdentifier  m_nThreadId;
+
+    virtual void doAcquire( sal_uInt32 nLockCount ) override;
+    virtual sal_uInt32 doRelease( bool bReleaseAll ) override;
+
+protected:
+    GenericSolarMutex();
+    virtual ~GenericSolarMutex() override;
+
+private:
+    BeforeReleaseHandler  m_aBeforeReleaseHandler;
+};
+
 }
 
-#endif
+#endif // INCLUDED_COMPHELPER_SOLARMUTEX_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index d5b81b2a20a4..b8f15df465bc 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -28,6 +28,7 @@
 #include <vector>
 
 #include <comphelper/solarmutex.hxx>
+#include <osl/mutex.hxx>
 #include <rtl/ustring.hxx>
 #include <osl/thread.hxx>
 #include <tools/gen.hxx>
@@ -1391,110 +1392,28 @@ private:
     DECL_STATIC_LINK( Application, PostEventHandler, void*, void );
 };
 
-
 class VCL_DLLPUBLIC SolarMutexGuard
+    : public osl::Guard<comphelper::SolarMutex>
 {
-private:
-    SolarMutexGuard( const SolarMutexGuard& ) = delete;
-    const SolarMutexGuard& operator = ( const SolarMutexGuard& ) = delete;
-    comphelper::SolarMutex& m_solarMutex;
-
 public:
-    /** Acquires the object specified as parameter.
-     */
-    SolarMutexGuard() :
-        m_solarMutex(Application::GetSolarMutex())
-    {
-        m_solarMutex.acquire();
-    }
-
-    /** Releases the mutex or interface. */
-    ~SolarMutexGuard()
-    {
-        m_solarMutex.release();
-    }
+    SolarMutexGuard()
+        : osl::Guard<comphelper::SolarMutex>( Application::GetSolarMutex() ) {}
 };
 
-class VCL_DLLPUBLIC SolarMutexClearableGuard final
+class VCL_DLLPUBLIC SolarMutexClearableGuard
+    : public osl::ClearableGuard<comphelper::SolarMutex>
 {
-    SolarMutexClearableGuard( const SolarMutexClearableGuard& ) = delete;
-    const SolarMutexClearableGuard& operator = ( const SolarMutexClearableGuard& ) = delete;
-    bool m_bCleared;
-    comphelper::SolarMutex& m_solarMutex;
 public:
-    /** Acquires mutex
-     */
     SolarMutexClearableGuard()
-        : m_bCleared(false)
-        , m_solarMutex( Application::GetSolarMutex() )
-    {
-        m_solarMutex.acquire();
-    }
-
-    /** Releases mutex. */
-    ~SolarMutexClearableGuard()
-    {
-        if( !m_bCleared )
-        {
-            m_solarMutex.release();
-        }
-    }
-
-    /** Releases mutex. */
-    void SAL_CALL clear()
-    {
-        if( !m_bCleared )
-        {
-            m_solarMutex.release();
-            m_bCleared = true;
-        }
-    }
+        : osl::ClearableGuard<comphelper::SolarMutex>( Application::GetSolarMutex() ) {}
 };
 
-class VCL_DLLPUBLIC SolarMutexResettableGuard final
+class VCL_DLLPUBLIC SolarMutexResettableGuard
+    : public osl::ResettableGuard<comphelper::SolarMutex>
 {
-    SolarMutexResettableGuard( const SolarMutexResettableGuard& ) = delete;
-    const SolarMutexResettableGuard& operator = ( const SolarMutexResettableGuard& ) = delete;
-    bool m_bCleared;
-    comphelper::SolarMutex& m_solarMutex;
 public:
-    /** Acquires mutex
-     */
     SolarMutexResettableGuard()
-        : m_bCleared(false)
-        , m_solarMutex( Application::GetSolarMutex() )
-    {
-        m_solarMutex.acquire();
-    }
-
-    /** Releases mutex. */
-    ~SolarMutexResettableGuard()
-    {
-        if( !m_bCleared )
-        {
-            m_solarMutex.release();
-        }
-    }
-
-    /** Releases mutex. */
-    void SAL_CALL clear()
-    {
-        if( !m_bCleared)
-        {
-            m_solarMutex.release();
-            m_bCleared = true;
-        }
-    }
-
-    /** Re-acquires mutex. */
-    void SAL_CALL reset()
-    {
-        if( m_bCleared)
-        {
-            m_solarMutex.acquire();
-            m_bCleared = false;
-        }
-    }
+        : osl::ResettableGuard<comphelper::SolarMutex>( Application::GetSolarMutex() ) {}
 };
 
 namespace vcl
diff --git a/vcl/android/androidinst.cxx b/vcl/android/androidinst.cxx
index a2cb49cb60aa..afb919a2e4e9 100644
--- a/vcl/android/androidinst.cxx
+++ b/vcl/android/androidinst.cxx
@@ -191,13 +191,13 @@ SalInstance *CreateSalInstance()
     LOGI("Android: CreateSalInstance!");
     AndroidSalInstance* pInstance = new AndroidSalInstance( new SalYieldMutex() );
     new AndroidSalData( pInstance );
-    pInstance->AcquireYieldMutex(1);
+    pInstance->AcquireYieldMutex();
     return pInstance;
 }
 
 void DestroySalInstance( SalInstance *pInst )
 {
-    pInst->ReleaseYieldMutex();
+    pInst->ReleaseYieldMutex( true );
     delete pInst;
 }
 
diff --git a/vcl/headless/headlessinst.cxx b/vcl/headless/headlessinst.cxx
index e6f5cf03f5b3..69027f3ccb3c 100644
--- a/vcl/headless/headlessinst.cxx
+++ b/vcl/headless/headlessinst.cxx
@@ -92,13 +92,13 @@ SalInstance *CreateSalInstance()
 {
     HeadlessSalInstance* pInstance = new HeadlessSalInstance( new SalYieldMutex() );
     new HeadlessSalData( pInstance );
-    pInstance->AcquireYieldMutex(1);
+    pInstance->AcquireYieldMutex();
     return pInstance;
 }
 
 void DestroySalInstance( SalInstance *pInst )
 {
-    pInst->ReleaseYieldMutex();
+    pInst->ReleaseYieldMutex( true );
     delete pInst;
 }
 
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index c9b10143e00c..5d9947a50f22 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -41,19 +41,20 @@ class ApplicationEvent;
 class Image;
 enum class SalEvent;
 
-class SalYieldMutex : public comphelper::SolarMutex
+class SalYieldMutex : public comphelper::GenericSolarMutex
 {
-    osl::Mutex m_mutex;
-    sal_uLong                                   mnCount;
-    oslThreadIdentifier                         mnThreadId;
+    bool                    mbInAquireWithTry;
+
+protected:
+    virtual void            doAcquire( sal_uInt32 nLockCount ) override;
+    virtual sal_uInt32      doRelease( bool bReleaseAll ) override;
 
 public:
-                                                SalYieldMutex();
-    virtual void                                acquire() override;
-    virtual void                                release() override;
-    virtual bool                                tryToAcquire() override;
-    sal_uLong                                   GetAcquireCount() const { return mnCount; }
-    oslThreadIdentifier                         GetThreadId() const { return mnThreadId; }
+    SalYieldMutex();
+
+    virtual bool            tryToAcquire() override;
+    sal_uInt32              GetAcquireCount() const { return mnCount; }
+    oslThreadIdentifier     GetThreadId() const { return mnThreadId; }
 };
 
 class AquaSalInstance : public SalInstance
@@ -112,8 +113,8 @@ public:
     virtual SalSystem*      CreateSalSystem() override;
     virtual SalBitmap*      CreateSalBitmap() override;
     virtual comphelper::SolarMutex* GetYieldMutex() override;
-    virtual sal_uLong       ReleaseYieldMutex( bool bUnlockAll = true ) override;
-    virtual void            AcquireYieldMutex( sal_uLong nCount ) override;
+    virtual sal_uInt32      ReleaseYieldMutex( bool bUnlockAll = false ) override;
+    virtual void            AcquireYieldMutex( sal_uInt32 nCount = 1 ) override;
     virtual bool            CheckYieldMutex() override;
     virtual bool            DoYield(bool bWait, bool bHandleAllCurrentEvents,
                                     sal_uLong nReleased) override;
@@ -168,8 +169,9 @@ public:
 // helper class: inverted solar guard
 class YieldMutexReleaser
 {
-    sal_uLong mnCount;
-    public:
+    sal_uInt32 mnCount;
+
+public:
     YieldMutexReleaser();
     ~YieldMutexReleaser();
 };
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index fc8febbf035f..b583d9189876 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -25,6 +25,7 @@
 #include <tools/solar.h>
 #include <vcl/dllapi.h>
 #include <vcl/salgtype.hxx>
+#include <osl/thread.hxx>
 
 #include "displayconnectiondispatch.hxx"
 
@@ -121,8 +122,8 @@ public:
     // YieldMutex
     virtual comphelper::SolarMutex*
                             GetYieldMutex() = 0;
-    virtual sal_uLong       ReleaseYieldMutex( bool bUnlockAll = true ) = 0;
-    virtual void            AcquireYieldMutex( sal_uLong nCount ) = 0;
+    virtual sal_uInt32      ReleaseYieldMutex( bool bReleaseAll = false ) = 0;
+    virtual void            AcquireYieldMutex( sal_uInt32 nCount = 1 ) = 0;
     // return true, if yield mutex is owned by this thread, else false
     virtual bool            CheckYieldMutex() = 0;
     virtual bool            IsMainThread() const = 0;
diff --git a/vcl/inc/unx/geninst.h b/vcl/inc/unx/geninst.h
index ef747fa323af..f6e390573014 100644
--- a/vcl/inc/unx/geninst.h
+++ b/vcl/inc/unx/geninst.h
@@ -30,7 +30,8 @@
 
 class VCL_DLLPUBLIC SalYieldMutexReleaser
 {
-    sal_uLong m_nYieldCount;
+    sal_uInt32 m_nYieldCount;
+
 public:
     inline SalYieldMutexReleaser();
     inline ~SalYieldMutexReleaser();
@@ -38,32 +39,20 @@ public:
 
 inline SalYieldMutexReleaser::SalYieldMutexReleaser()
 {
-    m_nYieldCount = GetSalData()->m_pInstance->ReleaseYieldMutex();
+    m_nYieldCount = GetSalData()->m_pInstance->ReleaseYieldMutex( true );
 }
 
 inline SalYieldMutexReleaser::~SalYieldMutexReleaser()
 {
-    GetSalData()->m_pInstance->AcquireYieldMutex( m_nYieldCount );
+    if ( m_nYieldCount )
+        GetSalData()->m_pInstance->AcquireYieldMutex( m_nYieldCount );
 }
 
-class VCL_DLLPUBLIC SalYieldMutex : public comphelper::SolarMutex
+class VCL_DLLPUBLIC SalYieldMutex : public comphelper::GenericSolarMutex
 {
-    osl::Mutex m_mutex;
-
-protected:
-    sal_uIntPtr         mnCount;
-    oslThreadIdentifier mnThreadId;
-
 public:
-                        SalYieldMutex();
-                        virtual ~SalYieldMutex() override;
-
-    virtual void        acquire() override;
-    virtual void        release() override;
-    virtual bool        tryToAcquire() override;
-
-    sal_uIntPtr GetAcquireCount() const { return mnCount; }
-    oslThreadIdentifier GetThreadId() const { return mnThreadId; }
+    SalYieldMutex();
+    virtual ~SalYieldMutex() override;
 };
 
 /*
@@ -84,9 +73,9 @@ public:
 
     // Yield mutex
     virtual comphelper::SolarMutex* GetYieldMutex() override;
-    virtual sal_uIntPtr         ReleaseYieldMutex( bool bUnlockAll = true ) override;
-    virtual void                AcquireYieldMutex( sal_uIntPtr nCount ) override;
-    virtual bool                CheckYieldMutex() override;
+    virtual sal_uInt32         ReleaseYieldMutex( bool bUnlockAll = false ) override;
+    virtual void               AcquireYieldMutex( sal_uInt32 nCount = 1 ) override;
+    virtual bool               CheckYieldMutex() override;
 
     // Printing
     virtual SalInfoPrinter*     CreateInfoPrinter      ( SalPrinterQueueInfo* pQueueInfo,
diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index 3683e9369cfa..321b76455df0 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -59,8 +59,8 @@ public:
     virtual SalSystem*          CreateSalSystem() override;
     virtual SalBitmap*          CreateSalBitmap() override;
     virtual comphelper::SolarMutex* GetYieldMutex() override;
-    virtual sal_uIntPtr         ReleaseYieldMutex( bool bUnlockAll = true ) override;
-    virtual void                AcquireYieldMutex( sal_uIntPtr nCount ) override;
+    virtual sal_uIntPtr         ReleaseYieldMutex( bool bUnlockAll = false ) override;
+    virtual void                AcquireYieldMutex( sal_uIntPtr nCount = 1 ) override;
     virtual bool                CheckYieldMutex() override;
     virtual bool                IsMainThread() const override;
 
diff --git a/vcl/ios/iosinst.cxx b/vcl/ios/iosinst.cxx
index b4b6f1f9f0bd..fb2d79b2fd59 100644
--- a/vcl/ios/iosinst.cxx
+++ b/vcl/ios/iosinst.cxx
@@ -172,13 +172,13 @@ SalInstance *CreateSalInstance()
 {
     IosSalInstance* pInstance = new IosSalInstance( new SalYieldMutex() );
     new IosSalData( pInstance );
-    pInstance->AcquireYieldMutex(1);
+    pInstance->AcquireYieldMutex();
     return pInstance;
 }
 
 void DestroySalInstance( SalInstance *pInst )
 {
-    pInst->ReleaseYieldMutex();
+    pInst->ReleaseYieldMutex( true );
     delete pInst;
 }
 
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index 99b48b2ee439..74d32761c9fd 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -223,9 +223,8 @@ static AquaSalFrame* getMouseContainerFrame()
 {
     if( GetSalData() && GetSalData()->mpFirstInstance )
     {
-        GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
+        SolarMutexGuard aGuard();
         [super displayIfNeeded];
-        GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
     }
 }
 
@@ -311,7 +310,7 @@ static AquaSalFrame* getMouseContainerFrame()
 
     bool bNoLock = GetSalData()->mpFirstInstance->mbNoNotificationLock;
     if ( !bNoLock )
-        GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
+        GetSalData()->mpFirstInstance->AcquireYieldMutex();
 
     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
     {
@@ -320,7 +319,7 @@ static AquaSalFrame* getMouseContainerFrame()
     }
 
     if ( !bNoLock )
-        GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
+        GetSalData()->mpFirstInstance->ReleaseYieldMutex();
 }
 
 -(void)windowDidResize: (NSNotification*)pNotification
@@ -329,7 +328,7 @@ static AquaSalFrame* getMouseContainerFrame()
 
     bool bNoLock = GetSalData()->mpFirstInstance->mbNoNotificationLock;
     if ( !bNoLock )
-        GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
+        GetSalData()->mpFirstInstance->AcquireYieldMutex();
 
     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
     {
@@ -339,7 +338,7 @@ static AquaSalFrame* getMouseContainerFrame()
     }
 
     if ( !bNoLock )
-        GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
+        GetSalData()->mpFirstInstance->ReleaseYieldMutex();
 }
 
 -(void)windowDidMiniaturize: (NSNotification*)pNotification
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 9ca0bae28c29..e3d58cd6c3cc 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -261,41 +261,63 @@ void InitSalMain()
 
 SalYieldMutex::SalYieldMutex()
 {
-    mnCount  = 0;
-    mnThreadId  = 0;
 }
 
-void SalYieldMutex::acquire()
+void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
 {
-    m_mutex.acquire();
-    mnThreadId = osl::Thread::getCurrentIdentifier();
-    mnCount++;
-}
+    assert( nLockCount > 0 );
 
-void SalYieldMutex::release()
-{
-    if ( mnThreadId == osl::Thread::getCurrentIdentifier() )
+    if ( IsMainThread() )
     {
-        if ( mnCount == 1 )
+        while ( !m_mutex.tryToAcquire() )
         {
-            // TODO: add OpenGLContext::prepareForYield with vcl OpenGL support
-            mnThreadId = 0;
+            mbInAquireWithTry = true;
+SAL_WNODEPRECATED_DECLARATIONS_PUSH
+            // 'NSApplicationDefinedMask' is deprecated: first deprecated in macOS 10.12
+            NSEvent* pPeekEvent = [NSApp nextEventMatchingMask: NSApplicationDefinedMask
+SAL_WNODEPRECATED_DECLARATIONS_POP
+                                   untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]
+                                   inMode: NSDefaultRunLoopMode
+                                   dequeue: YES];
+            if ( UnlockedYieldMutexEvent != (int) [pPeekEvent subtype] )
+                [NSApp postEvent: pPeekEvent atStart: YES];
         }
-        mnCount--;
+        mbInAquireWithTry = false;
     }
-    m_mutex.release();
+    else
+        m_mutex.acquire();
+    --nLockCount;
+
+    if ( nLockCount )
+        acquire( nLockCount );
+}
+
+sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
+{
+    sal_uInt32 nCount = release( bUnlockAll );
+
+    if ( mbInAquireWithTry && !IsMainThread() && 0 == getCount() )
+        dispatch_async(dispatch_get_main_queue(),^{
+            ImplNSAppPostEvent( AquaSalInstance::UnlockedYieldMutexEvent, NO );
+            });
+
+    return nCount;
 }
 
 bool SalYieldMutex::tryToAcquire()
 {
-    if ( m_mutex.tryToAcquire() )
+    bool bAquired = m_mutex.tryToAcquire();
+    if ( bAquired )
     {
         mnThreadId = osl::Thread::getCurrentIdentifier();
         mnCount++;
-        return true;
     }
-    else
-        return false;
+    return bAquired;
+}
+
+bool SalYieldMutex::check()
+{
+    return mnThreadId != osl::Thread::getCurrentIdentifier();
 }
 
 // some convenience functions regarding the yield mutex, aka solar mutex
@@ -386,70 +408,14 @@ comphelper::SolarMutex* AquaSalInstance::GetYieldMutex()
 
 sal_uLong AquaSalInstance::ReleaseYieldMutex( bool bUnlockAll )
 {
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex;
-    if ( pYieldMutex->GetThreadId() ==
-         osl::Thread::getCurrentIdentifier() )
-    {
-        const sal_uLong nCurCount = pYieldMutex->GetAcquireCount();
-        const sal_uLong nCount = bUnlockAll ? nCurCount : 1;
-        sal_uLong n = nCount;
-        while ( n )
-        {
-            pYieldMutex->release();
-            n--;
-        }
-
-        if ( mbTryToAcquireYield && !IsMainThread() && (0 == nCurCount - nCount) )
-            dispatch_async(dispatch_get_main_queue(),^{
-                ImplNSAppPostEvent( AquaSalInstance::UnlockedYieldMutexEvent, NO );
-            });
-        return nCount;
-    }
-    else
-        return 0;
 }
 
 void AquaSalInstance::AcquireYieldMutex( sal_uLong nCount )
 {
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex;
-
-    if ( nCount && IsMainThread() )
-    {
-        while ( !mpSalYieldMutex->tryToAcquire() )
-        {
-            mbTryToAcquireYield = true;
-SAL_WNODEPRECATED_DECLARATIONS_PUSH
-            // 'NSApplicationDefinedMask' is deprecated: first deprecated in macOS 10.12
-            NSEvent* pPeekEvent = [NSApp nextEventMatchingMask: NSApplicationDefinedMask
-SAL_WNODEPRECATED_DECLARATIONS_POP
-                                   untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]
-                                   inMode: NSDefaultRunLoopMode
-                                   dequeue: YES];
-            if ( UnlockedYieldMutexEvent != (int) [pPeekEvent subtype] )
-                [NSApp postEvent: pPeekEvent atStart: YES];
-        }
-        mbTryToAcquireYield = false;
-        --nCount;
-    }
-
-    while ( nCount )
-    {
-        pYieldMutex->acquire();
-        nCount--;
-    }
 }
 
 bool AquaSalInstance::CheckYieldMutex()
 {
-    bool bRet = true;
-
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex;
-    if ( pYieldMutex->GetThreadId() != osl::Thread::getCurrentIdentifier())
-    {
-        bRet = false;
-    }
-
-    return bRet;
 }
 
 bool AquaSalInstance::IsMainThread() const
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 23aa0f583707..e442fcf05335 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -131,10 +131,9 @@ static void ImplSalStopTimer()
 void AquaSalTimer::handleDispatchTimerEvent()
 {
     ImplSVData* pSVData = ImplGetSVData();
-    GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
+    SolarMutexGuard aGuard;
     if( pSVData->maSchedCtx.mpSalTimer )
         pSVData->maSchedCtx.mpSalTimer->CallCallback();
-    GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
 }
 
 void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 7bb2fbcce645..b03ff00fc536 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -414,7 +414,6 @@ next_entry:
         {
             SAL_WARN( "vcl.schedule",
                       "Uncaught exception during Task::Invoke()!" );
-            DBG_UNHANDLED_EXCEPTION();
             abort();
         }
         Lock( nLockCount );
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index c4b900754f6f..99fe2c70ea83 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -593,7 +593,7 @@ oslThreadIdentifier Application::GetMainThreadIdentifier()
 sal_uLong Application::ReleaseSolarMutex()
 {
     ImplSVData* pSVData = ImplGetSVData();
-    return pSVData->mpDefInst->ReleaseYieldMutex();
+    return pSVData->mpDefInst->ReleaseYieldMutex( true );
 }
 
 void Application::AcquireSolarMutex( sal_uLong nCount )
diff --git a/vcl/unx/generic/app/geninst.cxx b/vcl/unx/generic/app/geninst.cxx
index b5a954f591f3..917ed2992e72 100644
--- a/vcl/unx/generic/app/geninst.cxx
+++ b/vcl/unx/generic/app/geninst.cxx
@@ -39,48 +39,13 @@
 
 SalYieldMutex::SalYieldMutex()
 {
-    mnCount     = 0;
-    mnThreadId  = 0;
-    ::comphelper::SolarMutex::setSolarMutex( this );
-}
-
-SalYieldMutex::~SalYieldMutex()
-{
-    ::comphelper::SolarMutex::setSolarMutex( nullptr );
-}
-
-void SalYieldMutex::acquire()
-{
-    m_mutex.acquire();
-    mnThreadId = osl::Thread::getCurrentIdentifier();
-    mnCount++;
-}
-
-void SalYieldMutex::release()
-{
-    assert(mnCount != 0);
-    assert(mnThreadId == osl::Thread::getCurrentIdentifier());
-    if ( mnCount == 1 )
-    {
 #if HAVE_FEATURE_OPENGL
-        OpenGLContext::prepareForYield();
+    SetBeforeReleaseHandler( &OpenGLContext::prepareForYield );
 #endif
-        mnThreadId = 0;
-    }
-    mnCount--;
-    m_mutex.release();
 }
 
-bool SalYieldMutex::tryToAcquire()
+SalYieldMutex::~SalYieldMutex()
 {
-    if ( m_mutex.tryToAcquire() )
-    {
-        mnThreadId = osl::Thread::getCurrentIdentifier();
-        mnCount++;
-        return true;
-    }
-    else
-        return false;
 }
 
 comphelper::SolarMutex* SalGenericInstance::GetYieldMutex()
@@ -88,48 +53,19 @@ comphelper::SolarMutex* SalGenericInstance::GetYieldMutex()
     return mpSalYieldMutex.get();
 }
 
-sal_uLong SalGenericInstance::ReleaseYieldMutex( bool )
+sal_uInt32 SalGenericInstance::ReleaseYieldMutex( bool bUnlockAll )
 {
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex.get();
-    if ( pYieldMutex->GetThreadId() ==
-         osl::Thread::getCurrentIdentifier() )
-    {
-        sal_uLong nCount = pYieldMutex->GetAcquireCount();
-        sal_uLong n = nCount;
-        while ( n )
-        {
-            pYieldMutex->release();
-            n--;
-        }
-
-        return nCount;
-    }
-    else
-        return 0;
+    return mpSalYieldMutex.get()->release( bUnlockAll );
 }
 
-void SalGenericInstance::AcquireYieldMutex( sal_uLong nCount )
+void SalGenericInstance::AcquireYieldMutex( sal_uInt32 nCount )
 {
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex.get();
-    while ( nCount )
-    {
-        pYieldMutex->acquire();
-        nCount--;
-    }
+    mpSalYieldMutex.get()->acquire( nCount );
 }
 
 bool SalGenericInstance::CheckYieldMutex()
 {
-    bool bRet = true;
-
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex.get();
-    if ( pYieldMutex->GetThreadId() != osl::Thread::getCurrentIdentifier() )
-    {
-        SAL_WARN("vcl", "CheckYieldMutex: " << pYieldMutex->GetThreadId() << "!=" << osl::Thread::getCurrentIdentifier() );
-        bRet = false;
-    }
-
-    return bRet;
+    return mpSalYieldMutex.get()->check();
 }
 
 SalGenericInstance::~SalGenericInstance()
diff --git a/vcl/unx/generic/app/saldisp.cxx b/vcl/unx/generic/app/saldisp.cxx
index b73c5046a3d2..6e05f0cc3fae 100644
--- a/vcl/unx/generic/app/saldisp.cxx
+++ b/vcl/unx/generic/app/saldisp.cxx
@@ -1911,8 +1911,7 @@ void SalX11Display::Yield()
         return;
 
     XEvent aEvent;
-    DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
-                osl::Thread::getCurrentIdentifier(),
+    DBG_ASSERT( GetSalData()->m_pInstance->GetYieldMutex()->check(),
                 "will crash soon since solar mutex not locked in SalDisplay::Yield" );
 
     XNextEvent( pDisp_, &aEvent );
diff --git a/vcl/unx/generic/plugadapt/salplug.cxx b/vcl/unx/generic/plugadapt/salplug.cxx
index 71061742a7d7..441f16ddb113 100644
--- a/vcl/unx/generic/plugadapt/salplug.cxx
+++ b/vcl/unx/generic/plugadapt/salplug.cxx
@@ -256,7 +256,7 @@ SalInstance *CreateSalInstance()
     }
 
     // acquire SolarMutex
-    pInst->AcquireYieldMutex( 1 );
+    pInst->AcquireYieldMutex();
 
     return pInst;
 }
@@ -264,7 +264,7 @@ SalInstance *CreateSalInstance()
 void DestroySalInstance( SalInstance *pInst )
 {
     // release SolarMutex
-    pInst->ReleaseYieldMutex();
+    pInst->ReleaseYieldMutex( true );
 
     delete pInst;
     if( pCloseModule )
diff --git a/vcl/unx/gtk/gtkinst.cxx b/vcl/unx/gtk/gtkinst.cxx
index db0aa9b783e4..080b2a9c0345 100644
--- a/vcl/unx/gtk/gtkinst.cxx
+++ b/vcl/unx/gtk/gtkinst.cxx
@@ -316,8 +316,8 @@ void GtkYieldMutex::ThreadsEnter()
 
 void GtkYieldMutex::ThreadsLeave()
 {
-    assert(mnCount != 0);
-    auto n = mnCount - 1;
+    assert(m_nCount != 0);
+    auto n = m_nCount - 1;
     yieldCounts.push(n);
     for (sal_uIntPtr i = 0; i != n + 1; ++i) {
         release();
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx
index 7c30c7aa40c9..4f2f1d34a93a 100644
--- a/vcl/unx/kde4/KDESalDisplay.cxx
+++ b/vcl/unx/kde4/KDESalDisplay.cxx
@@ -54,8 +54,7 @@ void SalKDEDisplay::Yield()
     if (XEventsQueued( pDisp_, QueuedAfterReading ) == 0)
         return;
 
-    DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
-                osl::Thread::getCurrentIdentifier(),
+    DBG_ASSERT( GetSalData()->m_pInstance->GetYieldMutex()->check(),
                 "will crash soon since solar mutex not locked in SalKDEDisplay::Yield" );
 
     XEvent event;
commit e9cdb00db635859a58f6e61e70211a157dc961d7
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 22:16:49 2017 +0200

    Drop SystemTicks from scheduler logging
    
    If you want to see system ticks, add +SYSTEMTICKS to your SAL_LOG.
    
    Change-Id: I8d67fbc64873a800555866f34023ac83ddfb7f02

diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 4187af3f3e8b..7bb2fbcce645 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -332,15 +332,14 @@ bool Scheduler::ProcessTaskScheduling()
     {
         const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask );
         if ( timer )
-            SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                << pSchedulerData << " " << *pSchedulerData << " " << *timer );
+            SAL_INFO( "vcl.schedule", pSchedulerData << " "
+                << *pSchedulerData << " " << *timer );
         else if ( pSchedulerData->mpTask )
-            SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                << pSchedulerData << " " << *pSchedulerData
-                << " " << *pSchedulerData->mpTask );
+            SAL_INFO( "vcl.schedule", pSchedulerData << " "
+                << *pSchedulerData << " " << *pSchedulerData->mpTask );
         else
-            SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                << pSchedulerData << " " << *pSchedulerData << " (to be deleted)" );
+            SAL_INFO( "vcl.schedule", pSchedulerData << " "
+                << *pSchedulerData << " (to be deleted)" );
 
         // Should the Task be released from scheduling or stacked?
         if ( !pSchedulerData->mpTask || !pSchedulerData->mpTask->IsActive()
@@ -392,8 +391,8 @@ next_entry:
 
     if ( pMostUrgent )
     {
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                  << pMostUrgent << "  invoke-in  " << *pMostUrgent->mpTask );
+        SAL_INFO( "vcl.schedule", pMostUrgent
+            << "  invoke-in  " << *pMostUrgent->mpTask );
 
         Task *pTask = pMostUrgent->mpTask;
 
@@ -421,8 +420,7 @@ next_entry:
         Lock( nLockCount );
         pMostUrgent->mbInScheduler = false;
 
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
-                  << pMostUrgent << "  invoke-out" );
+        SAL_INFO( "vcl.schedule", pMostUrgent << "  invoke-out" );
 
         // eventually pop the scheduler stack
         // this just happens for nested calls, which renders all accounting
@@ -489,20 +487,20 @@ void Task::Start()
         mpSchedulerData = pSchedulerData;
 
         AppendSchedulerData( rSchedCtx, pSchedulerData );
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
-                  << " " << mpSchedulerData << "  added      " << *this );
+        SAL_INFO( "vcl.schedule",
+                  mpSchedulerData << "  added      " << *this );
     }
     else
-        SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
-                  << " " << mpSchedulerData << "  restarted  " << *this );
+        SAL_INFO( "vcl.schedule",
+                  mpSchedulerData << "  restarted  " << *this );
 
-    mpSchedulerData->mnUpdateTime  = tools::Time::GetSystemTicks();
+    mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
 }
 
 void Task::Stop()
 {
-    SAL_INFO_IF( mbActive, "vcl.schedule", tools::Time::GetSystemTicks()
-                  << " " << mpSchedulerData << "  stopped    " << *this );
+    SAL_INFO_IF( mbActive, "vcl.schedule",
+                 mpSchedulerData << "  stopped    " << *this );
     mbActive = false;
 }
 
commit 53efd6429a8ee6247b47a14ae2b09a6a95f40b9c
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 22:35:49 2017 +0200

    Add +SYSTEMTICKS to log format
    
    Prefixes SAL_* output lines with tools::Time::GetSystemTicks().
    Now we can drop this information from the scheduler log output.
    
    Change-Id: I4840d0d56dbb5df55edf08fe664faf3a344196d0

diff --git a/include/sal/log.hxx b/include/sal/log.hxx
index c096d52a0e47..9b8e518db50a 100644
--- a/include/sal/log.hxx
+++ b/include/sal/log.hxx
@@ -235,7 +235,7 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
       <switch> ::= <sense><item>
       <sense> ::= "+"|"-"
       <item> ::= <flag>|<level>("."<area>)?
-      <flag> ::= "TIMESTAMP"|"RELATIVETIMER"
+      <flag> ::= "TIMESTAMP"|"RELATIVETIMER"|"SYSTEMTICKS"
       <level> ::= "INFO"|"WARN"
     @endverbatim
 
@@ -245,14 +245,16 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
     "+INFO+WARN" is used instead (which in turn results in everything
     being output).
 
-    The "+TIMESTAMP" flag causes each output line (as selected by the level
-    switch(es)) to be prefixed by a timestamp like 2016-08-18:14:04:43.
+    The "+TIMESTAMP" flag causes each SAL_* output line to be prefixed by
+    a timestamp like 2016-08-18:14:04:43.
 
-    The "+RELATIVETIMER" flag causes each output line (as selected by
-    the level switch(es)) to be prefixed by a relative timestamp in
-    seconds since the first output line like 1.312.
+    The "+RELATIVETIMER" flag causes each SAL_* output line to be prefixed by
+    a relative timestamp in seconds since the first output line like 1.312.
 
-    If both +TIMESTAMP and +RELATIVETIMER are specified, they are
+    The "+SYSTEMTICKS" flag causes each SAL_* output line to be prefixed by
+    the current value of tools::Time::GetSystemTicks().
+
+    If +TIMESTAMP, +RELATIVETIMER and +SYSTEMTICKS are specified, they are
     output in that order.
 
     Specifying a flag with a negative sense has no effect. Specifying
@@ -274,7 +276,7 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
     SAL_INFO("other", ...) generate output, while calls like
     SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
 
-    The generated log output consists of the optinal timestamp, the given level
+    The generated log output consists of the optional timestamp, the given level
     ("info" or "warn"), the given area, the process ID, the thread ID, the
     source file, and the source line number, each followed by a colon, followed
     by a space, the given message, and a newline.  The precise format of the log
diff --git a/sal/osl/all/log.cxx b/sal/osl/all/log.cxx
index 1f0138f1266d..ac095a348733 100644
--- a/sal/osl/all/log.cxx
+++ b/sal/osl/all/log.cxx
@@ -22,6 +22,8 @@
 #include <fstream>
 
 #include "osl/thread.hxx"
+#include "osl/mutex.hxx"
+#include "osl/time.h"
 #include "rtl/string.h"
 #include "sal/detail/log.h"
 #include "sal/log.hxx"
@@ -53,6 +55,22 @@ bool const sal_use_syslog = false;
 
 namespace {
 
+enum OutputItem
+{
+    EMPTY,
+    TIMESTAMP,
+    RELATIVETIMER,
+    SYSTEMTICKS,
+    LAST,
+    COUNT = LAST - 1,
+};
+
+bool bParsedLogEnvironment = false;
+osl::Mutex aParserMutex;
+OutputItem aOutputList[ OutputItem::COUNT ] = { OutputItem::EMPTY, };
+
+void parseLogEnvironment();
+
 bool equalStrings(
     char const * string1, std::size_t length1, char const * string2,
     std::size_t length2)
@@ -61,7 +79,8 @@ bool equalStrings(
 }
 
 #if !defined ANDROID
-char const * toString(sal_detail_LogLevel level) {
+char const * toString(sal_detail_LogLevel level)
+{
     switch (level) {
     case SAL_DETAIL_LOG_LEVEL_INFO:
         return "info";
@@ -81,13 +100,15 @@ char const * toString(sal_detail_LogLevel level) {
 // the process is running":
 #if defined ANDROID
 
-char const * getEnvironmentVariable() {
+char const * getEnvironmentVariable()
+{
     return std::getenv("SAL_LOG");
 }
 
 #else
 
-char const * getEnvironmentVariable_(const char* env) {
+char const * getEnvironmentVariable_(const char* env)
+{
     char const * p1 = std::getenv(env);
     if (p1 == nullptr) {
         return nullptr;
@@ -99,98 +120,150 @@ char const * getEnvironmentVariable_(const char* env) {
     return p2;
 }
 
-char const * getEnvironmentVariable() {
+char const * getEnvironmentVariable()
+{
     static char const * env = getEnvironmentVariable_("SAL_LOG");
     return env;
 }
 
-char const * getLogFile() {
+char const * getLogFile()
+{
     static char const * logFile = getEnvironmentVariable_("SAL_LOG_FILE");
     return logFile;
 }
 
-void maybeOutputTimestamp(std::ostringstream &s) {
+void maybeOutputTimestamp(std::ostringstream &s)
+{
+    assert( bParsedLogEnvironment );
+    for ( unsigned int i = 0;
+          i < OutputItem::COUNT && OutputItem::EMPTY != aOutputList[ i ];
+          ++i )
+    {
+        switch (aOutputList[ i ])
+        {
+        case OutputItem::TIMESTAMP:
+        {
+            char ts[100];
+            TimeValue systemTime;
+            osl_getSystemTime(&systemTime);
+            TimeValue localTime;
+            osl_getLocalTimeFromSystemTime(&systemTime, &localTime);
+            oslDateTime dateTime;
+            osl_getDateTimeFromTimeValue(&localTime, &dateTime);
+            struct tm tm;
+            tm.tm_sec = dateTime.Seconds;
+            tm.tm_min = dateTime.Minutes;
+            tm.tm_hour = dateTime.Hours;
+            tm.tm_mday = dateTime.Day;
+            tm.tm_mon = dateTime.Month - 1;
+            tm.tm_year = dateTime.Year - 1900;
+            strftime(ts, sizeof(ts), "%Y-%m-%d:%H:%M:%S", &tm);
+            char milliSecs[11];
+            sprintf(milliSecs, "%03u", static_cast<unsigned>(dateTime.NanoSeconds/1000000));
+            s << ts << '.' << milliSecs << ':';
+            break;
+        } // case OutputItem::TIMESTAMP
+
+        case OutputItem::RELATIVETIMER:
+        {
+            static bool beenHere = false;
+            static TimeValue first;
+            if (!beenHere) {
+                osl_getSystemTime(&first);
+                beenHere = true;
+            }
+            TimeValue now;
+            osl_getSystemTime(&now);
+            int seconds = now.Seconds - first.Seconds;
+            int milliSeconds;
+            if (now.Nanosec < first.Nanosec) {
+                seconds--;
+                milliSeconds = 1000-(first.Nanosec-now.Nanosec)/1000000;
+            }
+            else
+                milliSeconds = (now.Nanosec-first.Nanosec)/1000000;
+            char relativeTimestamp[100];
+            sprintf(relativeTimestamp, "%d.%03d", seconds, milliSeconds);
+            s << relativeTimestamp << ':';
+            break;
+        } // case OutputItem::RELATIVETIMER
+
+        case OutputItem::SYSTEMTICKS:
+            s << osl_getSystemTicks() << ':';
+            break;
+
+        default:
+            return;
+        }
+    }
+}
+
+#endif
+
+void parseLogEnvironment()
+{
+    if (bParsedLogEnvironment)
+        return;
+    osl::MutexGuard aGuard( aParserMutex );
+    if (bParsedLogEnvironment)
+        return;
+    bParsedLogEnvironment = true;
     char const * env = getEnvironmentVariable();
-    if (env == nullptr)
+    if (nullptr == env)
         return;
-    bool outputTimestamp = false;
-    bool outputRelativeTimer = false;
-    for (char const * p = env;;) {
-        switch (*p++) {
+    unsigned int nOutputItem = 0;
+    bool aOutputSeenList[ OutputItem::LAST ] = { false, };
+    for (char const * p = env;;)
+    {
+        switch (*p++)
+        {
         case '\0':
-            if (outputTimestamp) {
-                char ts[100];
-                TimeValue systemTime;
-                osl_getSystemTime(&systemTime);
-                TimeValue localTime;
-                osl_getLocalTimeFromSystemTime(&systemTime, &localTime);
-                oslDateTime dateTime;
-                osl_getDateTimeFromTimeValue(&localTime, &dateTime);
-                struct tm tm;
-                tm.tm_sec = dateTime.Seconds;
-                tm.tm_min = dateTime.Minutes;
-                tm.tm_hour = dateTime.Hours;
-                tm.tm_mday = dateTime.Day;
-                tm.tm_mon = dateTime.Month - 1;
-                tm.tm_year = dateTime.Year - 1900;
-                strftime(ts, sizeof(ts), "%Y-%m-%d:%H:%M:%S", &tm);
-                char milliSecs[11];
-                sprintf(milliSecs, "%03u", static_cast<unsigned>(dateTime.NanoSeconds/1000000));
-                s << ts << '.' << milliSecs << ':';
-            }
-            if (outputRelativeTimer) {
-                static bool beenHere = false;
-                static TimeValue first;
-                if (!beenHere) {
-                    osl_getSystemTime(&first);
-                    beenHere = true;
-                }
-                TimeValue now;
-                osl_getSystemTime(&now);
-                int seconds = now.Seconds - first.Seconds;
-                int milliSeconds;
-                if (now.Nanosec < first.Nanosec) {
-                    seconds--;
-                    milliSeconds = 1000-(first.Nanosec-now.Nanosec)/1000000;
-                }
-                else
-                    milliSeconds = (now.Nanosec-first.Nanosec)/1000000;
-                char relativeTimestamp[100];
-                sprintf(relativeTimestamp, "%d.%03d", seconds, milliSeconds);
-                s << relativeTimestamp << ':';
-            }
             return;
         case '+':
+        {
+            char const * p1 = p;
+            while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
+                ++p1;
+            }
+            if (!aOutputSeenList[ OutputItem::TIMESTAMP ]
+                && equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")))
             {
-                char const * p1 = p;
-                while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
-                    ++p1;
-                }
-                if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")))
-                    outputTimestamp = true;
-                else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER")))
-                    outputRelativeTimer = true;
-                char const * p2 = p1;
-                while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
-                    ++p2;
-                }
-                p = p2;
+                aOutputSeenList[ OutputItem::TIMESTAMP ] = true;
+                aOutputList[ nOutputItem++ ] = OutputItem::TIMESTAMP;
             }
+            else if (!aOutputSeenList[ OutputItem::RELATIVETIMER ]
+                && equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER")))
+            {
+                aOutputSeenList[ OutputItem::RELATIVETIMER ] = true;
+                aOutputList[ nOutputItem++ ] = OutputItem::RELATIVETIMER;
+            }
+            else if (!aOutputSeenList[ OutputItem::SYSTEMTICKS ]
+                && equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("SYSTEMTICKS")))
+            {
+                aOutputSeenList[ OutputItem::SYSTEMTICKS ] = true;
+                aOutputList[ nOutputItem++ ] = OutputItem::SYSTEMTICKS;
+            }
+            char const * p2 = p1;
+            while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
+                ++p2;
+            }
+            p = p2;
             break;
+        } // case '+'
+
         default:
-            ; // nothing
+            break; // nothing
         }
     }
 }
 
-#endif
-
-}
+} // anonymous namespace
 
 void sal_detail_log(
     sal_detail_LogLevel level, char const * area, char const * where,
     char const * message, sal_uInt32 backtraceDepth)
 {
+    parseLogEnvironment();
     std::ostringstream s;
 #if !defined ANDROID
     // On Android, the area will be used as the "tag," and log info already
commit c3f6b2d8e5dadba5727537d8b74fcd3454e1d0c7
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 23:22:36 2017 +0200

    Move tools::time::getSystemTicks() into osl
    
    Moves the code into osl_getSystemTicks and marks the original
    funtion as deprecated. Also merges a duplicate W32 implementation.
    
    Change-Id: I5c9263540b8af55b2eeca6126e288129427f6e8e

diff --git a/canvas/Library_canvastools.mk b/canvas/Library_canvastools.mk
index 50658b362f6b..a87e53fd1043 100644
--- a/canvas/Library_canvastools.mk
+++ b/canvas/Library_canvastools.mk
@@ -69,10 +69,4 @@ $(eval $(call gb_Library_add_defs,canvastools,\
 endif
 endif
 
-ifeq ($(OS),WNT)
-$(eval $(call gb_Library_use_system_win32_libs,canvastools,\
-	winmm \
-))
-endif
-
 # vim: set noet sw=4 ts=4:
diff --git a/canvas/source/tools/elapsedtime.cxx b/canvas/source/tools/elapsedtime.cxx
index e82df7dbe3fb..cd3e44b7abc8 100644
--- a/canvas/source/tools/elapsedtime.cxx
+++ b/canvas/source/tools/elapsedtime.cxx
@@ -23,82 +23,12 @@
 
 #include <canvas/elapsedtime.hxx>
 
-#if defined(_WIN32)
-
-#if defined _MSC_VER
-#pragma warning(push,1)
-#endif
-
-// TEMP!!!
-// Awaiting corresponding functionality in OSL
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <winbase.h>
-#include <mmsystem.h>
-#endif
-
-#if defined _MSC_VER
-#pragma warning(pop)
-#endif
-
 #include <algorithm>
 #include <limits>
 
 namespace canvas {
 namespace tools {
 
-
-#if defined(_WIN32)
-// TODO(Q2): is 0 okay for the failure case here?
-double ElapsedTime::getSystemTime()
-{
-    // TEMP!!!
-    // Awaiting corresponding functionality in OSL
-
-
-    // is there a performance counter available?
-    static bool bTimeSetupDone( false );
-    static bool bPerfTimerAvailable( false );
-    static LONGLONG nPerfCountFreq;
-
-    // TODO(F1): This _might_ cause problems, as it prevents correct
-    // time handling for very long lifetimes of this class's
-    // surrounding component in memory. When the difference between
-    // current sys time and nInitialCount exceeds IEEE double's
-    // mantissa, time will start to run jerky.
-    static LONGLONG nInitialCount;
-
-    if( !bTimeSetupDone )
-    {
-        if( QueryPerformanceFrequency(
-                reinterpret_cast<LARGE_INTEGER *>(&nPerfCountFreq) ) )
-        {
-            // read initial time:
-            QueryPerformanceCounter(
-                reinterpret_cast<LARGE_INTEGER *>(&nInitialCount) );
-            bPerfTimerAvailable = true;
-        }
-        bTimeSetupDone = true;
-    }
-
-    if( bPerfTimerAvailable )
-    {
-        LONGLONG nCurrCount;
-        QueryPerformanceCounter(
-            reinterpret_cast<LARGE_INTEGER *>(&nCurrCount) );
-        nCurrCount -= nInitialCount;
-        return double(nCurrCount) / nPerfCountFreq;
-    }
-    else
-    {
-        LONGLONG nCurrTime = timeGetTime();
-        return double(nCurrTime) / 1000.0;
-    }
-}
-
-#else // ! WNT
-
 // TODO(Q2): is 0 okay for the failure case here?
 double ElapsedTime::getSystemTime()
 {
@@ -109,8 +39,6 @@ double ElapsedTime::getSystemTime()
         return 0.0;
 }
 
-#endif
-
 ElapsedTime::ElapsedTime()
     : m_pTimeBase(),
       m_fLastQueriedTime( 0.0 ),
diff --git a/include/osl/time.h b/include/osl/time.h
index 4843a9d02e25..d3376f91b1ef 100644
--- a/include/osl/time.h
+++ b/include/osl/time.h
@@ -167,11 +167,16 @@ SAL_DLLPUBLIC sal_Bool SAL_CALL osl_getSystemTimeFromLocalTime(
 
 
 /** Get the value of the global timer
-    @return current timer value in milli seconds
+    @return current timer value in milliseconds
  */
-
 SAL_DLLPUBLIC sal_uInt32 SAL_CALL osl_getGlobalTimer(void);
 
+
+/** Get the elapsed time since some unspecified starting point
+    @return current system ticks in milliseconds
+ */
+SAL_DLLPUBLIC sal_uInt64 SAL_CALL osl_getSystemTicks(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/tools/time.hxx b/include/tools/time.hxx
index d8b4e6d06fc6..04921d4636e2 100644
--- a/include/tools/time.hxx
+++ b/include/tools/time.hxx
@@ -121,7 +121,7 @@ public:
 
     static Time     GetUTCOffset();
 
-    /// Elapsed time since epoch in milliseconds
+    /// Elapsed time in milliseconds since some unspecified starting point
     static sal_uInt64 GetSystemTicks();
 
     tools::Time&           operator =( const tools::Time& rTime );
diff --git a/sal/Library_sal.mk b/sal/Library_sal.mk
index 17d89ae79e4a..c7c476b57d34 100644
--- a/sal/Library_sal.mk
+++ b/sal/Library_sal.mk
@@ -53,6 +53,7 @@ $(eval $(call gb_Library_use_system_win32_libs,sal,\
 	ole32 \
 	shell32 \
 	user32 \
+	winmm \
 	ws2_32 \
 ))
 
diff --git a/sal/osl/unx/time.cxx b/sal/osl/unx/time.cxx
index 61d452434d64..ca567ed3f0a5 100644
--- a/sal/osl/unx/time.cxx
+++ b/sal/osl/unx/time.cxx
@@ -308,4 +308,16 @@ sal_uInt32 SAL_CALL osl_getGlobalTimer()
     return nSeconds;
 }
 
+sal_uInt64 SAL_CALL osl_getSystemTicks()
+{
+    timeval tv;
+    int n = gettimeofday (&tv, nullptr);
+    if (n == -1) {
+        fprintf(stderr, "gettimeofday failed: %i\n", errno);
+        abort();
+    }
+    return static_cast<sal_uInt64>(tv.tv_sec) * 1000
+         + static_cast<sal_uInt64>(tv.tv_usec) / 1000;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/osl/w32/time.cxx b/sal/osl/w32/time.cxx
index 1a6e6ceaa181..afae9db07333 100644
--- a/sal/osl/w32/time.cxx
+++ b/sal/osl/w32/time.cxx
@@ -18,7 +18,9 @@
  */
 
 #include <sal/config.h>
+
 #include "system.h"
+#include <mmsystem.h>
 
 #include <filetime.hxx>
 #include <time.hxx>
@@ -200,4 +202,30 @@ sal_uInt32 SAL_CALL osl_getGlobalTimer(void)
   return ( nSeconds * 1000 ) + (long)( currentTime.millitm - startTime.millitm );
 }
 
+sal_uInt64 SAL_CALL osl_getSystemTicks(void)
+{
+    static LARGE_INTEGER nTicksPerSecond = { 0 };
+    static bool bTicksPerSecondInitialized = false;
+
+    if (!bTicksPerSecondInitialized)
+    {
+        bTicksPerSecondInitialized = true;
+        if (!QueryPerformanceFrequency(&nTicksPerSecond))
+            nTicksPerSecond.QuadPart = 0;
+    }
+
+    if (nTicksPerSecond.QuadPart > 0)
+    {
+        LARGE_INTEGER nPerformanceCount;
+        QueryPerformanceCounter(&nPerformanceCount);
+        return static_cast<sal_uInt64>(
+            (nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
+    }
+    else
+    {
+        LONGLONG nCurrTime = timeGetTime();
+        return double(nCurrTime) / 1000.0;
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/util/sal.map b/sal/util/sal.map
index 1a5e2c2f9401..057d95d1fd50 100644
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -710,6 +710,7 @@ LIBO_UDK_5.3 { # symbols available in >= LibO 5.3
 LIBO_UDK_6_0 { # symbols available in >= LibO 6.0
     global:
         osl_getThreadSystemID;
+        osl_getSystemTicks;
 } LIBO_UDK_5.3;
 
 PRIVATE_1.0 {
diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
index 83812f72171a..32ec7a150cf4 100644
--- a/tools/source/datetime/ttime.cxx
+++ b/tools/source/datetime/ttime.cxx
@@ -39,6 +39,7 @@
 #include <sal/log.hxx>
 #include <tools/time.hxx>
 #include <osl/diagnose.h>
+#include <osl/time.h>
 
 #if defined(__sun) && defined(__GNUC__)
 extern long altzone;
@@ -411,30 +412,7 @@ Time tools::Time::GetUTCOffset()
 
 sal_uInt64 tools::Time::GetSystemTicks()
 {
-#if defined(_WIN32)
-    static LARGE_INTEGER nTicksPerSecond;
-    static bool bTicksPerSecondInitialized = false;
-    if (!bTicksPerSecondInitialized)
-    {
-        QueryPerformanceFrequency(&nTicksPerSecond);
-        bTicksPerSecondInitialized = true;
-    }
-
-    LARGE_INTEGER nPerformanceCount;
-    QueryPerformanceCounter(&nPerformanceCount);
-
-    return static_cast<sal_uInt64>(
-        (nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
-#else
-    timeval tv;
-    int n = gettimeofday (&tv, nullptr);
-    if (n == -1) {
-        int e = errno;
-        SAL_WARN("tools.datetime", "gettimeofday failed: " << e);
-    }
-    return static_cast<sal_uInt64>(tv.tv_sec) * 1000
-        + static_cast<sal_uInt64>(tv.tv_usec) / 1000;
-#endif
+    return osl_getSystemTicks();
 }
 
 } /* namespace tools */
commit 67ef78bde2cd620568c212769cf9f54d4c677536
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 09:03:49 2017 +0200

    Abort on critical Scheduler problems
    
    There is not much sense in trying to continue without the main
    lock. An other aspect are tasks with uncaught exceptions, which
    must not happen. In both cases simply abort.
    
    Change-Id: I4d52a6ef0526a1e46b64f9f3a6e0cc1a718618cc

diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 50a45006ced1..4187af3f3e8b 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -28,6 +28,7 @@
 #include <saltimer.hxx>
 #include <salinst.hxx>
 #include <comphelper/profilezone.hxx>
+#include <tools/diagnose_ex.h>
 #include <schedulerimpl.hxx>
 
 namespace {
@@ -155,20 +156,22 @@ void Scheduler::ImplDeInitScheduler()
 
 void SchedulerMutex::acquire( sal_uInt32 nLockCount )
 {
+    assert(nLockCount > 0);
     for (sal_uInt32 i = 0; i != nLockCount; ++i) {
-        bool ok = maMutex.acquire();
-        assert(ok); (void) ok;
-        ++mnLockDepth;
+        if (!maMutex.acquire())
+            abort();
     }
+    mnLockDepth += nLockCount;
 }
 
 sal_uInt32 SchedulerMutex::release( bool bUnlockAll )
 {
-    assert(mnLockDepth != 0);
+    assert(mnLockDepth > 0);
     sal_uInt32 nLockCount = bUnlockAll ? mnLockDepth : 1;
     mnLockDepth -= nLockCount;
     for (sal_uInt32 i = 0; i != nLockCount; ++i) {
-        maMutex.release();
+        if (!maMutex.release())
+            abort();
     }
     return nLockCount;
 }
@@ -404,7 +407,17 @@ next_entry:
         // not run a nested Scheduler loop and don't need a stack push!
         pMostUrgent->mbInScheduler = true;
         sal_uInt32 nLockCount = Unlock( true );
-        pTask->Invoke();
+        try
+        {
+            pTask->Invoke();
+        }
+        catch (...)
+        {
+            SAL_WARN( "vcl.schedule",
+                      "Uncaught exception during Task::Invoke()!" );
+            DBG_UNHANDLED_EXCEPTION();
+            abort();
+        }
         Lock( nLockCount );
         pMostUrgent->mbInScheduler = false;
 
commit 14c54614cb372a7cd338d7a6b57bd543668e6eb1
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 09:02:16 2017 +0200

    SVP always drain the wakeup pipe
    
    Even when we have a lot of idle events, the pipe gets filled,
    so just drain it on every run.
    
    Change-Id: I7b6366b2649133b63138dc77fe51508404132890

diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 4b76f0c3fbec..4ebeac8f4a3c 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -370,6 +370,12 @@ bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong
 
         DoReleaseYield(nTimeoutMS);
     }
+    else if ( bEvent )
+    {
+        // Drain the wakeup pipe
+        int buffer;
+        while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0);
+    }
 
     return bEvent;
 }
@@ -394,8 +400,7 @@ void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
     if( (aPoll.revents & POLLIN) != 0 )
     {
         int buffer;
-        while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0)
-            continue;
+        while (read (m_pTimeoutFDS[0], &buffer, sizeof(buffer)) > 0);
     }
 }
 
commit d38ebe4cd345afa0602155731bedaf6a3f0cb450
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 09:19:37 2017 +0200

    tdf#99784 update Scheduler documentation
    
    Reflect special handling in the OSX backend.
    
    Change-Id: I6493ba6b6cf1c69f9fafc7ab583c430d72f73247

diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index 4c0f4c57981a..4a23355b1a6e 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -91,13 +91,26 @@ can be added to the scheduler reasonably.
 
 == MacOS implementation details ==
 
-Generally the Scheduler is handled as expected. There is a workaround for a
-problem for pushing tasks to an empty queue, as [NSApp postEvent: ...
-atStart: NO] doesn't append the event, if the message queue is empty.
+Generally the Scheduler is handled as expected, except on resize, which is
+handled with different runloop-modes in MacOS.
+In case of a resize, the normal runloop is suspended in sendEvent, so we
+can't call the scheduler via posted main loop-events.
+
+Like the Windows backend, all Cocoa / GUI handling also has to be done in
+the main thread. But unless Windows out-of-order PeekMessage processing,
+via MsgWaitForMultipleObjects, we have to rely on a wakeup message, if
+the SolarMutex is unlocked.
+
+There is also a workaround for a problem for pushing tasks to an empty queue,
+as [NSApp postEvent: ... atStart: NO] doesn't append the event, if the
+message queue is empty.
 
 Probably that's the reason, why some code comments spoke of lost events and
 there was some distinct additional event processing implemented.
 
+OTOH we can use a closure like feature to execute the GUI code block in the
+main thread, without much hazzle.
+
 == Windows implementation details ==
 
 Posted or sent event messages often trigger processing of WndProc in
@@ -154,3 +167,8 @@ easy way to process just a single event).
 Since the Scheduler is always handled by the system message queue, there is
 really no more reasoning to stop after 100 events to prevent LO Scheduler
 starvation.
+
+== Run the LO application in it's own thread ==
+
+Thi swould probably get rid of most of the MacOS and Windows implementation
+details / workarounds. But this seems to be even more work to do.
commit 04a8964274901ccbb580e5bbaa89ed573b5b6fb3
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 15 08:23:31 2017 +0200

    tdf#99784 OSX fix painting on resize
    
    While resizing MacOS suspends the NSDefaultRunLoopMode. So in this
    caae we can't post to the system event loop, but must use timers
    to restart ourself.
    
    Since the timer itself is scheduled on the NSEventTrackingRunLoopMode
    it' also triggers on resize events.
    
    There is still some minor glitch: when resizing too fast some part
    of LibreOffice isn't painted, while the left mouse button is down.
    
    Since there isn't any layouting triggered by the mouse up, there has
    to be an other inconsistency.
    
    Change-Id: I3ccba78bd23ec8526f21e7b93b027f3d3279f901

diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 48f029e5d06d..c9b10143e00c 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -79,6 +79,7 @@ public:
     osl::Condition                          maWaitingYieldCond;
     bool                                    mbNoNotificationLock;
     bool                                    mbTryToAcquireYield;
+    bool                                    mbIsLiveResize;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index fb78b39b1833..99b48b2ee439 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -541,6 +541,17 @@ private:
 
 -(void)drawRect: (NSRect)aRect
 {
+    if( GetSalData()->mpFirstInstance )
+    {
+        const bool bIsLiveResize = [self inLiveResize];
+        const bool bWasLiveResize = GetSalData()->mpFirstInstance->mbIsLiveResize;
+        if ( bWasLiveResize != bIsLiveResize )
+        {
+            GetSalData()->mpFirstInstance->mbIsLiveResize = bIsLiveResize;
+            Scheduler::ProcessTaskScheduling();
+        }
+    }
+
     // HOTFIX: #i93512# prevent deadlocks if any other thread already has the SalYieldMutex
     TryGuard aTryGuard;
     if( !aTryGuard.IsGuarded() )
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index cead8a362c1c..9ca0bae28c29 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -351,6 +351,7 @@ AquaSalInstance::AquaSalInstance()
  , maWaitingYieldCond()
  , mbNoNotificationLock( false )
  , mbTryToAcquireYield( false )
+ , mbIsLiveResize( false )
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm
index c9867cf7a79e..c9b657dcd776 100644
--- a/vcl/osx/salnstimer.mm
+++ b/vcl/osx/salnstimer.mm
@@ -30,7 +30,13 @@
 -(void)timerElapsed:(NSTimer*)pTimer
 {
     (void)pTimer;
-    ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, YES );
+    // 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 );
 }
 
 @end
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 62814759ae1a..23aa0f583707 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -83,7 +83,7 @@ static void ImplSalStartTimer( sal_uLong nMS )
         return;
     }
 
-    if ( 0 == nMS )
+    if ( 0 == nMS && !pSalData->mpFirstInstance->mbIsLiveResize )
     {
         ImplSalStopTimer();
         ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, NO );
@@ -93,7 +93,7 @@ static void ImplSalStartTimer( sal_uLong nMS )
         NSTimeInterval aTI = double(nMS) / 1000.0;
         if( AquaSalTimer::pRunningTimer != nil )
         {
-            if (rtl::math::approxEqual(
+            if ([AquaSalTimer::pRunningTimer isValid] && rtl::math::approxEqual(
                     [AquaSalTimer::pRunningTimer timeInterval], aTI))
             {
                 // set new fire date
commit 56a00ace8bee7af04323349ed9b8c06ea830e0cd
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Tue Aug 8 15:03:37 2017 +0200

    tdf#99784 OSX run GUI stuff in the main thread
    
    The extension manager starts dialogs from its own thread. But the
    OSX backend currently doesn't defer these calls to the main thread.
    This implements the deference using dispatch_*.
    
    Since dispatch_* can't return any values, we're using a thread-id
    based map to transfer the return values from the main thread to the
    callers.
    
    One major problem is the missing equivalent of Windows
    WaitForMultipleObjects function, which we have to emulate by
    try-locking the SolarMutex and waiting for an unlock message. Using
    an unprotected boolean isn't race free, therefore we use a 0.1s
    timout in the event lookup function. Our out-of-order SendMessage
    processing works fine with the processing of queued dispatch_* code
    blocks while waiting for new events.
    
    Then there is the problem of the notifications, where we have to
    disable the SolarMutex locking, because we generate these events
    ourself, but must not release it. Just ignoring the notifications
    currently results in GUI update failures.
    
    The runinmain implementation uses macros, so it can rely on guard
    objects for async calls.
    
    Change-Id: Id8977991e3eda91da27c23d8021e028d4f4cefe5

diff --git a/include/vcl/pointr.hxx b/include/vcl/pointr.hxx
index c82fb2236db0..8370b9f9d296 100644
--- a/include/vcl/pointr.hxx
+++ b/include/vcl/pointr.hxx
@@ -23,8 +23,6 @@
 #include <vcl/dllapi.h>
 #include <vcl/ptrstyle.hxx>
 
-class Point;
-
 class VCL_DLLPUBLIC Pointer
 {
     PointerStyle    meStyle;
diff --git a/vcl/inc/osx/runinmain.hxx b/vcl/inc/osx/runinmain.hxx
new file mode 100644
index 000000000000..4efdf94e2ddf
--- /dev/null
+++ b/vcl/inc/osx/runinmain.hxx
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_VCL_INC_OSX_RUNINMAIN_HXX
+#define INCLUDED_VCL_INC_OSX_RUNINMAIN_HXX
+
+/**
+ * Runs a command in the main thread.
+ *
+ * This is currently always used like a "recursive" call.
+ * These macros are most times intended to work like a closure.
+ *
+ * As dispatch_* doesn't support any return values, we have to use a
+ * global map with thread-id keys. The map is protected by the SolarMutex
+ * and is a member of the SalData object.
+ *
+ * There are three main macros, which act as function initializers:
+ *  - OSX_RUNINMAIN - for all functions without return values
+ *  - OSX_RUNINMAIN_POINTER - for all functions returning a pointer
+ *  - OSX_RUNINMAIN_UNION - for all other return types
+ *
+ * All types used via OSX_RUNINMAIN_UNION must implement a move constructor,
+ * so there is no memory leak!
+ */
+
+#include <osl/thread.h>
+#include <unordered_map>
+#include "salframe.hxx"
+
+union RuninmainResult
+{
+    void*                            pointer;
+    bool                             boolean;
+    struct SalFrame::SalPointerState state;
+
+    RuninmainResult() {}
+};
+
+typedef std::unordered_map<oslThreadIdentifier, RuninmainResult> OSXRuninmainResultMap;
+
+#define OSX_RUNINMAIN_RESULTS \
+    OSXRuninmainResultMap maResultMap;
+
+#define OSX_RUNINMAIN( dispatcher, instance, command ) \
+    if ( !instance->IsMainThread() ) \
+    { \
+        dispatcher(dispatch_get_main_queue(), ^{ \
+            assert( !instance->mbNoNotificationLock ); \
+            instance->mbNoNotificationLock = true; \
+            command; \
+            instance->mbNoNotificationLock = false; \
+        }); \
+        return; \
+    }
+
+#define OSX_RUNINMAIN_POINTER( instance, command, type ) \
+    if ( !instance->IsMainThread() ) \
+    { \
+        OSXRuninmainResultMap &rResultMap = GetSalData()->maResultMap; \
+        oslThreadIdentifier aThreadId = osl::Thread::getCurrentIdentifier(); \
+        { \
+            dispatch_sync(dispatch_get_main_queue(), ^{ \
+                assert( !instance->mbNoNotificationLock ); \
+                instance->mbNoNotificationLock = true; \
+                rResultMap[ aThreadId ].pointer = static_cast<void*>( command ); \
+                instance->mbNoNotificationLock = false; \
+            }); \
+        } \
+        auto aResultIter = rResultMap.find( aThreadId ); \
+        assert( aResultIter != rResultMap.end() ); \
+        auto aResult = static_cast<type>( aResultIter->second.pointer ); \
+        rResultMap.erase( aResultIter ); \
+        return aResult; \
+    }
+
+#define OSX_RUNINMAIN_UNION( instance, command, member ) \
+    if ( !instance->IsMainThread() ) \
+    { \
+        OSXRuninmainResultMap &rResultMap = GetSalData()->maResultMap; \
+        oslThreadIdentifier aThreadId = osl::Thread::getCurrentIdentifier(); \
+        { \
+            dispatch_sync(dispatch_get_main_queue(), ^{ \
+                assert( !instance->mbNoNotificationLock ); \
+                instance->mbNoNotificationLock = true; \
+                rResultMap[ aThreadId ].member = command; \
+                instance->mbNoNotificationLock = false; \
+            }); \
+        } \
+        auto aResultIter = rResultMap.find( aThreadId ); \
+        assert( aResultIter != rResultMap.end() ); \
+        auto aResult = std::move( aResultIter->second.member ); \
+        rResultMap.erase( aResultIter ); \
+        return aResult; \
+    }
+
+/**
+ * convenience macros used from SalInstance
+ */
+
+#define OSX_INST_RUNINMAIN( command ) \
+    OSX_RUNINMAIN( dispatch_sync, this, command )
+
+#define OSX_INST_RUNINMAIN_ASYNC( command ) \
+    OSX_RUNINMAIN( dispatch_async, this, command ) \
+    osl::Guard< comphelper::SolarMutex > aGuard( *mpSalYieldMutex );
+
+#define OSX_INST_RUNINMAIN_POINTER( command, type ) \
+    OSX_RUNINMAIN_POINTER( this, command, type )
+
+#define OSX_INST_RUNINMAIN_UNION( command, member ) \
+    OSX_RUNINMAIN_UNION( this, command, member )
+
+/**
+ * convenience macros useing global SalData
+ */
+
+#define OSX_SALDATA_RUNINMAIN( command ) \
+    OSX_RUNINMAIN( dispatch_sync, GetSalData()->mpFirstInstance, command )
+
+#define OSX_SALDATA_RUNINMAIN_ASYNC( command ) \
+    OSX_RUNINMAIN( dispatch_async, GetSalData()->mpFirstInstance, command ) \
+    osl::Guard< comphelper::SolarMutex > aGuard( *GetSalData()->mpFirstInstance->mpSalYieldMutex );
+
+#define OSX_SALDATA_RUNINMAIN_POINTER( command, type ) \
+    OSX_RUNINMAIN_POINTER( GetSalData()->mpFirstInstance, command, type )
+
+#define OSX_SALDATA_RUNINMAIN_UNION( command, member ) \
+    OSX_RUNINMAIN_UNION( GetSalData()->mpFirstInstance, command, member )
+
+#endif // INCLUDED_VCL_INC_OSX_RUNINMAIN_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx
index fbc28e05391d..625b7a32ba9b 100644
--- a/vcl/inc/osx/saldata.hxx
+++ b/vcl/inc/osx/saldata.hxx
@@ -45,6 +45,8 @@
 
 #include "apple_remote/RemoteMainController.h"
 
+#include "osx/runinmain.hxx"
+
 class AquaSalInstance;
 class SalObject;
 class SalFrame;
@@ -107,6 +109,8 @@ public:
     static void ensureThreadAutoreleasePool();
 
     static NSStatusItem* getStatusItem();
+
+    OSX_RUNINMAIN_RESULTS;
 };
 
 inline void SetSalData( SalData* pData ) { ImplGetSVData()->mpSalData = pData; }
diff --git a/vcl/inc/osx/salframe.h b/vcl/inc/osx/salframe.h
index 4b6d486f6be6..307356c76caa 100644
--- a/vcl/inc/osx/salframe.h
+++ b/vcl/inc/osx/salframe.h
@@ -29,6 +29,7 @@
 #include "osx/salmenu.h"
 #include "osx/saldata.hxx"
 #include "osx/osxvcltypes.h"
+#include "osx/runinmain.hxx"
 
 #include "salframe.hxx"
 
@@ -183,22 +184,22 @@ public:
     void VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen = true );
     void CocoaToVCL( NSPoint& io_Point, bool bRelativeToScreen = true );
 
-    NSCursor* getCurrentCursor() const;
+    NSCursor* getCurrentCursor();
 
     CGMutablePathRef getClipPath() const { return mrClippingPath; }
 
     // called by VCL_NSApplication to indicate screen settings have changed
     void screenParametersChanged();
 
- private: // methods
+private: // methods
     /** do things on initial show (like centering on parent or on screen)
     */
     void initShow();
 
     void initWindowAndView();
 
- private: // data
-    static AquaSalFrame*                   s_pCaptureFrame;
+private: // data
+    static AquaSalFrame*       s_pCaptureFrame;
 
     AquaSalFrame( const AquaSalFrame& ) = delete;
     AquaSalFrame& operator=(const AquaSalFrame&) = delete;
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index f47ae7cc8303..48f029e5d06d 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -32,7 +32,11 @@
 #endif
 #include "salinst.hxx"
 
+#include "osx/runinmain.hxx"
+
 class AquaSalFrame;
+class SalFrame;
+class SalObject;
 class ApplicationEvent;
 class Image;
 enum class SalEvent;
@@ -73,9 +77,13 @@ public:
     std::list< SalUserEvent >               maUserEvents;
     osl::Mutex                              maUserEventListMutex;
     osl::Condition                          maWaitingYieldCond;
+    bool                                    mbNoNotificationLock;
+    bool                                    mbTryToAcquireYield;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
+    OSX_RUNINMAIN_RESULTS;
+
 public:
     AquaSalInstance();
     virtual ~AquaSalInstance() override;
@@ -151,6 +159,7 @@ public:
     static const short AppStartTimerEvent = 10;
     static const short PostedUserEvent    = 20;
     static const short DispatchTimerEvent = 30;
+    static const short UnlockedYieldMutexEvent = 40;
 
     static NSMenu* GetDynamicDockMenu();
 };
diff --git a/vcl/osx/a11ytextwrapper.mm b/vcl/osx/a11ytextwrapper.mm
index a46ffd6e7fd9..14a63aa8fd9e 100644
--- a/vcl/osx/a11ytextwrapper.mm
+++ b/vcl/osx/a11ytextwrapper.mm
@@ -203,8 +203,8 @@ using namespace ::com::sun::star::uno;
 
 +(id)rangeForPositionAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)point {
     NSValue * value = nil;
-    Point aPoint( [ AquaA11yUtil nsPointToVclPoint: point ]);
-    const Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
+    css::awt::Point aPoint( [ AquaA11yUtil nsPointToVclPoint: point ]);
+    const css::awt::Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
     aPoint.X -= screenPos.X;
     aPoint.Y -= screenPos.Y;
     sal_Int32 index = [ wrapper accessibleText ] -> getIndexAtPoint( aPoint );
@@ -239,9 +239,9 @@ using namespace ::com::sun::star::uno;
         }
         if ( [ wrapper accessibleComponent ] ) {
             // get location on screen (must be added since get CharacterBounds returns values relative to parent)
-            Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
-            Point pos ( minx + screenPos.X, miny + screenPos.Y );
-            Point size ( maxx - minx, maxy - miny );
+            css::awt::Point screenPos = [ wrapper accessibleComponent ] -> getLocationOnScreen();
+            css::awt::Point pos ( minx + screenPos.X, miny + screenPos.Y );
+            css::awt::Point size ( maxx - minx, maxy - miny );
             NSValue * nsPos = [ AquaA11yUtil vclPointToNSPoint: pos ];
             rect = [ NSValue valueWithRect: NSMakeRect ( [ nsPos pointValue ].x, [ nsPos pointValue ].y - size.Y, size.X, size.Y ) ];
             //printf("Range: %s --- Rect: %s\n", [ NSStringFromRange ( [ range rangeValue ] ) UTF8String ], [ NSStringFromRect ( [ rect rectValue ] ) UTF8String ]);
diff --git a/vcl/osx/salframe.cxx b/vcl/osx/salframe.cxx
index a29eba5eb766..4d6c85299a9c 100644
--- a/vcl/osx/salframe.cxx
+++ b/vcl/osx/salframe.cxx
@@ -36,6 +36,7 @@
 #include "osx/salinst.h"
 #include "osx/salframeview.h"
 #include "osx/a11yfactory.h"
+#include "osx/runinmain.hxx"
 #include "quartz/utils.h"
 
 #include "salwtype.hxx"
@@ -92,6 +93,8 @@ AquaSalFrame::AquaSalFrame( SalFrame* pParent, SalFrameStyleFlags salFrameStyle
 
 AquaSalFrame::~AquaSalFrame()
 {
+    assert( GetSalData()->mpFirstInstance->IsMainThread() );
+
     // if the frame is destroyed and has the current menubar
     // set the default menubar
     if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu )
@@ -134,6 +137,8 @@ AquaSalFrame::~AquaSalFrame()
 
 void AquaSalFrame::initWindowAndView()
 {
+    OSX_SALDATA_RUNINMAIN( initWindowAndView() )
+
     // initialize mirroring parameters
     // FIXME: screens changing
     NSScreen* pNSScreen = [mpNSWindow screen];
@@ -259,6 +264,8 @@ void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen )
 
 void AquaSalFrame::screenParametersChanged()
 {
+    OSX_SALDATA_RUNINMAIN( screenParametersChanged() )
+
     UpdateFrameGeometry();
 
     if( mpGraphics )
@@ -298,6 +305,8 @@ void AquaSalFrame::SetTitle(const OUString& rTitle)
     if ( !mpNSWindow )
         return;
 
+    OSX_SALDATA_RUNINMAIN( SetTitle(rTitle) )
+
     // #i113170# may not be the main thread if called from UNO API
     SalData::ensureThreadAutoreleasePool();
 
@@ -342,8 +351,7 @@ void AquaSalFrame::SetIcon( sal_uInt16 )
 
 void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL )
 {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetRepresentedURL( i_rDocURL ) )
 
     if( comphelper::isFileUrl(i_rDocURL) )
     {
@@ -360,6 +368,8 @@ void AquaSalFrame::SetRepresentedURL( const OUString& i_rDocURL )
 
 void AquaSalFrame::initShow()
 {
+    OSX_SALDATA_RUNINMAIN( initShow() )
+
     mbInitShow = false;
     if( ! mbPositioned && ! mbFullScreen )
     {
@@ -397,6 +407,8 @@ void AquaSalFrame::initShow()
 
 void AquaSalFrame::SendPaintEvent( const tools::Rectangle* pRect )
 {
+    OSX_SALDATA_RUNINMAIN( SendPaintEvent( pRect ) )
+
     SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true );
     if( pRect )
     {
@@ -414,8 +426,7 @@ void AquaSalFrame::Show(bool bVisible, bool bNoActivate)
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN_ASYNC( Show(bVisible, bNoActivate) )
 
     mbShown = bVisible;
     if(bVisible)
@@ -472,8 +483,7 @@ void AquaSalFrame::Show(bool bVisible, bool bNoActivate)
 
 void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight )
 {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetMinClientSize( nWidth, nHeight ) )
 
     mnMinWidth = nWidth;
     mnMinHeight = nHeight;
@@ -495,8 +505,7 @@ void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight )
 
 void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight )
 {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetMaxClientSize( nWidth, nHeight ) )
 
     mnMaxWidth = nWidth;
     mnMaxHeight = nHeight;
@@ -536,46 +545,45 @@ void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight )
 
 void AquaSalFrame::SetWindowState( const SalFrameState* pState )
 {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetWindowState( pState ) )
 
     if ( mpNSWindow )
     {
-    // set normal state
-    NSRect aStateRect = [mpNSWindow frame];
-    aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
-    CocoaToVCL( aStateRect );
-    if( pState->mnMask & WindowStateMask::X )
-        aStateRect.origin.x = float(pState->mnX);
-    if( pState->mnMask & WindowStateMask::Y )
-        aStateRect.origin.y = float(pState->mnY);
-    if( pState->mnMask & WindowStateMask::Width )
-        aStateRect.size.width = float(pState->mnWidth);
-    if( pState->mnMask & WindowStateMask::Height )
-        aStateRect.size.height = float(pState->mnHeight);
-    VCLToCocoa( aStateRect );
-    aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
-
-    [mpNSWindow setFrame: aStateRect display: NO];
-    if( pState->mnState == WindowStateState::Minimized )
-        [mpNSWindow miniaturize: NSApp];
-    else if( [mpNSWindow isMiniaturized] )
-        [mpNSWindow deminiaturize: NSApp];
-
-    /* ZOOMED is not really maximized (actually it toggles between a user set size and
-       the program specified one), but comes closest since the default behavior is
-       "maximized" if the user did not intervene
-    */
-    if( pState->mnState == WindowStateState::Maximized )
-    {
-        if(! [mpNSWindow isZoomed])
-            [mpNSWindow zoom: NSApp];
-    }
-    else
-    {
-        if( [mpNSWindow isZoomed] )
-            [mpNSWindow zoom: NSApp];
-    }
+        // set normal state
+        NSRect aStateRect = [mpNSWindow frame];
+        aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask];
+        CocoaToVCL( aStateRect );
+        if( pState->mnMask & WindowStateMask::X )
+            aStateRect.origin.x = float(pState->mnX);
+        if( pState->mnMask & WindowStateMask::Y )
+            aStateRect.origin.y = float(pState->mnY);
+        if( pState->mnMask & WindowStateMask::Width )
+            aStateRect.size.width = float(pState->mnWidth);
+        if( pState->mnMask & WindowStateMask::Height )
+            aStateRect.size.height = float(pState->mnHeight);
+        VCLToCocoa( aStateRect );
+        aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask];
+
+        [mpNSWindow setFrame: aStateRect display: NO];
+        if( pState->mnState == WindowStateState::Minimized )
+            [mpNSWindow miniaturize: NSApp];
+        else if( [mpNSWindow isMiniaturized] )
+            [mpNSWindow deminiaturize: NSApp];
+
+        /* ZOOMED is not really maximized (actually it toggles between a user set size and
+           the program specified one), but comes closest since the default behavior is
+           "maximized" if the user did not intervene
+        */
+        if( pState->mnState == WindowStateState::Maximized )
+        {
+            if(! [mpNSWindow isZoomed])
+                [mpNSWindow zoom: NSApp];
+        }
+        else
+        {
+            if( [mpNSWindow isZoomed] )
+                [mpNSWindow zoom: NSApp];
+        }
     }
 
     // get new geometry
@@ -612,8 +620,7 @@ bool AquaSalFrame::GetWindowState( SalFrameState* pState )
     if ( !mpNSWindow )
         return FALSE;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN_UNION( GetWindowState( pState ), boolean )
 
     pState->mnMask = WindowStateMask::X                 |
                      WindowStateMask::Y                 |
@@ -644,8 +651,7 @@ void AquaSalFrame::SetScreenNumber(unsigned int nScreen)
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetScreenNumber( nScreen ) )
 
     NSArray* pScreens = [NSScreen screens];
     NSScreen* pScreen = nil;
@@ -682,14 +688,13 @@ void AquaSalFrame::ShowFullScreen( bool bFullScreen, sal_Int32 nDisplay )
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
-
     SAL_INFO("vcl.osx", OSL_THIS_FUNC << ": mbFullScreen=" << mbFullScreen << ", bFullScreen=" << bFullScreen);
 
     if( mbFullScreen == bFullScreen )
         return;
 
+    OSX_SALDATA_RUNINMAIN( ShowFullScreen( bFullScreen, nDisplay ) )
+
     mbFullScreen = bFullScreen;
 
     if( bFullScreen )
@@ -777,8 +782,7 @@ void AquaSalFrame::StartPresentation( bool bStart )
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( StartPresentation( bStart ) )
 
     if( bStart )
     {
@@ -808,8 +812,7 @@ void AquaSalFrame::ToTop(SalFrameToTop nFlags)
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( ToTop( nFlags ) )
 
     if( ! (nFlags & SalFrameToTop::RestoreWhenMin) )
     {
@@ -822,8 +825,10 @@ void AquaSalFrame::ToTop(SalFrameToTop nFlags)
         [mpNSWindow orderFront: NSApp];
 }
 
-NSCursor* AquaSalFrame::getCurrentCursor() const
+NSCursor* AquaSalFrame::getCurrentCursor()
 {
+    OSX_SALDATA_RUNINMAIN_POINTER( getCurrentCursor(), NSCursor* )
+
     NSCursor* pCursor = nil;
     switch( mePointerStyle )
     {
@@ -864,12 +869,11 @@ void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
 {
     if ( !mpNSWindow )
         return;
-
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
-
     if( ePointerStyle == mePointerStyle )
         return;
+
+    OSX_SALDATA_RUNINMAIN( SetPointer( ePointerStyle ) )
+
     mePointerStyle = ePointerStyle;
 
     [mpNSWindow invalidateCursorRectsForView: mpNSView];
@@ -877,8 +881,9 @@ void AquaSalFrame::SetPointer( PointerStyle ePointerStyle )
 
 void AquaSalFrame::SetPointerPos( long nX, long nY )
 {
-    // FIXME: use Cocoa functions
+    OSX_SALDATA_RUNINMAIN( SetPointerPos( nX, nY ) )
 
+    // FIXME: use Cocoa functions
     // FIXME: multiscreen support
     CGPoint aPoint = { static_cast<CGFloat>(nX + maGeometry.nX), static_cast<CGFloat>(nY + maGeometry.nY) };
     CGDirectDisplayID mainDisplayID = CGMainDisplayID();
@@ -890,8 +895,7 @@ void AquaSalFrame::Flush()
     if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( Flush() )
 
     [mpNSView setNeedsDisplay: YES];
 
@@ -909,8 +913,7 @@ void AquaSalFrame::Flush( const tools::Rectangle& rRect )
     if( !(mbGraphics && mpGraphics && mpNSView && mbShown) )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( Flush( rRect ) )
 
     NSRect aNSRect = { { static_cast<CGFloat>(rRect.Left()), static_cast<CGFloat>(rRect.Top()) }, { static_cast<CGFloat>(rRect.GetWidth()), static_cast<CGFloat>(rRect.GetHeight()) } };
     VCLToCocoa( aNSRect, false );
@@ -1118,6 +1121,8 @@ static vcl::Font getFont( NSFont* pFont, long nDPIY, const vcl::Font& rDefault )
 
 void AquaSalFrame::getResolution( sal_Int32& o_rDPIX, sal_Int32& o_rDPIY )
 {
+    OSX_SALDATA_RUNINMAIN( getResolution( o_rDPIX, o_rDPIY ) )
+
     if( ! mpGraphics )
     {
         AcquireGraphics();
@@ -1137,8 +1142,7 @@ void AquaSalFrame::UpdateSettings( AllSettings& rSettings )
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( UpdateSettings( rSettings ) )
 
     [mpNSView lockFocus];
 
@@ -1242,6 +1246,7 @@ const SystemEnvData* AquaSalFrame::GetSystemData() const
 
 void AquaSalFrame::Beep()
 {
+    OSX_SALDATA_RUNINMAIN( Beep() )
     NSBeep();
 }
 
@@ -1250,8 +1255,7 @@ void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_u
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetPosSize( nX, nY, nWidth, nHeight, nFlags ) )
 
     SalEvent nEvent = SalEvent::NONE;
 
@@ -1340,8 +1344,7 @@ void AquaSalFrame::GetWorkArea( tools::Rectangle& rRect )
     if ( !mpNSWindow )
         return;
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( GetWorkArea( rRect ) )
 
     NSScreen* pScreen = [mpNSWindow screen];
     if( pScreen ==  nil )
@@ -1356,8 +1359,7 @@ void AquaSalFrame::GetWorkArea( tools::Rectangle& rRect )
 
 SalPointerState AquaSalFrame::GetPointerState()
 {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN_UNION( GetPointerState(), state )
 
     SalPointerState state;
     state.mnState = 0;
@@ -1492,8 +1494,7 @@ void AquaSalFrame::DrawMenuBar()
 
 void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
 {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( SetMenu( pSalMenu ) )
 
     AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu);
     SAL_WARN_IF( pMenu && !pMenu->mbMenuBar, "vcl", "setting non menubar on frame" );
@@ -1504,14 +1505,16 @@ void AquaSalFrame::SetMenu( SalMenu* pSalMenu )
 
 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle )
 {
-    if ( mpNSWindow )
+    if ( !mpNSWindow )
     {
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+        mnExtStyle = nStyle;
+        return;
+    }
+
+    OSX_SALDATA_RUNINMAIN( SetExtendedFrameStyle( nStyle ) )
 
     if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) )
         [mpNSWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO];
-    }
 
     mnExtStyle = nStyle;
 }
@@ -1534,9 +1537,9 @@ void AquaSalFrame::SetParent( SalFrame* pNewParent )
 void AquaSalFrame::UpdateFrameGeometry()
 {
     if ( !mpNSWindow )
-    {
         return;
-    }
+
+    OSX_SALDATA_RUNINMAIN( UpdateFrameGeometry() )
 
     // keep in mind that view and window coordinates are lower left
     // whereas vcl's are upper left
@@ -1609,12 +1612,9 @@ void AquaSalFrame::CaptureMouse( bool bCapture )
 void AquaSalFrame::ResetClipRegion()
 {
     if ( !mpNSWindow )
-    {
         return;
-    }
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( ResetClipRegion() )
 
     // release old path and indicate no clipping
     CGPathRelease( mrClippingPath );
@@ -1632,12 +1632,9 @@ void AquaSalFrame::ResetClipRegion()
 void AquaSalFrame::BeginSetClipRegion( sal_uLong nRects )
 {
     if ( !mpNSWindow )
-    {
         return;
-    }
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( BeginSetClipRegion( nRects ) )
 
     // release old path
     if( mrClippingPath )
@@ -1671,12 +1668,9 @@ void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight
 void AquaSalFrame::EndSetClipRegion()
 {
     if ( !mpNSWindow )
-    {
         return;
-    }
 
-    // #i113170# may not be the main thread if called from UNO API
-    SalData::ensureThreadAutoreleasePool();
+    OSX_SALDATA_RUNINMAIN( EndSetClipRegion() )
 
     if( ! maClippingRects.empty() )
     {
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index e290891ce294..fb78b39b1833 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -223,13 +223,9 @@ static AquaSalFrame* getMouseContainerFrame()
 {
     if( GetSalData() && GetSalData()->mpFirstInstance )
     {
-        comphelper::SolarMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex();
-        if( pMutex )
-        {
-            pMutex->acquire();
-            [super displayIfNeeded];
-            pMutex->release();
-        }
+        GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
+        [super displayIfNeeded];
+        GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
     }
 }
 
@@ -312,19 +308,28 @@ static AquaSalFrame* getMouseContainerFrame()
 -(void)windowDidMove: (NSNotification*)pNotification
 {
     (void)pNotification;
-    SolarMutexGuard aGuard;
+
+    bool bNoLock = GetSalData()->mpFirstInstance->mbNoNotificationLock;
+    if ( !bNoLock )
+        GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
 
     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
     {
         mpFrame->UpdateFrameGeometry();
         mpFrame->CallCallback( SalEvent::Move, nullptr );
     }
+
+    if ( !bNoLock )
+        GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
 }
 
 -(void)windowDidResize: (NSNotification*)pNotification
 {
     (void)pNotification;
-    SolarMutexGuard aGuard;
+
+    bool bNoLock = GetSalData()->mpFirstInstance->mbNoNotificationLock;
+    if ( !bNoLock )
+        GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
 
     if( mpFrame && AquaSalFrame::isAlive( mpFrame ) )
     {
@@ -332,6 +337,9 @@ static AquaSalFrame* getMouseContainerFrame()
         mpFrame->CallCallback( SalEvent::Resize, nullptr );
         mpFrame->SendPaintEvent();
     }
+
+    if ( !bNoLock )
+        GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
 }
 
 -(void)windowDidMiniaturize: (NSNotification*)pNotification
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 45b7da6e36ee..cead8a362c1c 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -46,6 +46,7 @@
 #include "osx/salprn.h"
 #include "osx/saltimer.h"
 #include "osx/vclnsapp.h"
+#include "osx/runinmain.hxx"
 
 #include "print.h"
 #include "impbmp.hxx"
@@ -348,6 +349,8 @@ void DestroySalInstance( SalInstance* pInst )
 AquaSalInstance::AquaSalInstance()
  : maUserEventListMutex()
  , maWaitingYieldCond()
+ , mbNoNotificationLock( false )
+ , mbTryToAcquireYield( false )
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
@@ -395,6 +398,10 @@ sal_uLong AquaSalInstance::ReleaseYieldMutex( bool bUnlockAll )
             n--;
         }
 
+        if ( mbTryToAcquireYield && !IsMainThread() && (0 == nCurCount - nCount) )
+            dispatch_async(dispatch_get_main_queue(),^{
+                ImplNSAppPostEvent( AquaSalInstance::UnlockedYieldMutexEvent, NO );
+            });
         return nCount;
     }
     else
@@ -404,6 +411,26 @@ sal_uLong AquaSalInstance::ReleaseYieldMutex( bool bUnlockAll )
 void AquaSalInstance::AcquireYieldMutex( sal_uLong nCount )
 {
     SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+
+    if ( nCount && IsMainThread() )
+    {
+        while ( !mpSalYieldMutex->tryToAcquire() )
+        {
+            mbTryToAcquireYield = true;
+SAL_WNODEPRECATED_DECLARATIONS_PUSH
+            // 'NSApplicationDefinedMask' is deprecated: first deprecated in macOS 10.12
+            NSEvent* pPeekEvent = [NSApp nextEventMatchingMask: NSApplicationDefinedMask
+SAL_WNODEPRECATED_DECLARATIONS_POP
+                                   untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]
+                                   inMode: NSDefaultRunLoopMode
+                                   dequeue: YES];
+            if ( UnlockedYieldMutexEvent != (int) [pPeekEvent subtype] )
+                [NSApp postEvent: pPeekEvent atStart: YES];
+        }
+        mbTryToAcquireYield = false;
+        --nCount;
+    }
+
     while ( nCount )
     {
         pYieldMutex->acquire();
@@ -473,12 +500,16 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
         // dispatch it
         if ( aEvent.mpFrame )
         {
-            osl::Guard< comphelper::SolarMutex > aGuard( *mpSalYieldMutex );
+            AcquireYieldMutex( 1 );
             if ( AquaSalFrame::isAlive( aEvent.mpFrame ) )
                 aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData );
+            ReleaseYieldMutex( false );
         }
         break;
     }
+    case UnlockedYieldMutexEvent:
+        // do nothing
+        break;
 #if !HAVE_FEATURE_MACOSX_SANDBOX
     case AppleRemoteControlEvent: // Defined in <apple_remote/RemoteMainController.h>
     {
@@ -573,8 +604,6 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLon
         NSEvent* pEvent = nil;
         do
         {
-            sal_uLong nCount = ReleaseYieldMutex();
-
 SAL_WNODEPRECATED_DECLARATIONS_PUSH
     // 'NSAnyEventMask' is deprecated: first deprecated in macOS 10.12
             pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask
@@ -584,12 +613,13 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
                             dequeue: YES];
             if( pEvent )
             {
+                sal_uLong nCount = ReleaseYieldMutex();
                 [NSApp sendEvent: pEvent];
+                [NSApp updateWindows];
+                AcquireYieldMutex( nCount );
                 bHadEvent = true;
             }
-            [NSApp updateWindows];
 
-            AcquireYieldMutex( nCount );
         } while( bHandleAllCurrentEvents && pEvent );
 
         // if we had no event yet, wait for one if requested
@@ -606,7 +636,10 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
                             inMode: NSDefaultRunLoopMode
                             dequeue: YES];
             if( pEvent )
+            {
                 [NSApp sendEvent: pEvent];
+                bHadEvent = true;
+            }
             [NSApp updateWindows];
 
             AcquireYieldMutex( nCount );
@@ -630,9 +663,8 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
         // wait until any thread (most likely the main thread)
         // has dispatched an event, cop out at 200 ms
         maWaitingYieldCond.reset();
-        TimeValue aVal = { 0, 200000000 };
         sal_uLong nCount = ReleaseYieldMutex();
-        maWaitingYieldCond.wait( &aVal );
+        maWaitingYieldCond.wait();
         AcquireYieldMutex( nCount );
     }
 
@@ -672,6 +704,8 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType )

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list