[Libreoffice-commits] core.git: Branch 'private/jmux/scheduler-fixes' - 27 commits - avmedia/source basegfx/source canvas/Library_canvastools.mk canvas/source comphelper/source cui/source dbaccess/Module_dbaccess.mk dbaccess/source desktop/source framework/source icon-themes/sifr_svg include/comphelper include/osl include/sal include/tools include/vcl odk/config sal/Library_sal.mk sal/osl sal/util sd/inc sd/qa sd/source sw/qa sw/source tools/source vcl/android vcl/headless vcl/inc vcl/ios vcl/osx vcl/README.scheduler vcl/source vcl/unx vcl/win

Jan-Marek Glogowski glogow at fbihome.de
Sat Aug 19 06:13:47 UTC 2017


Rebased ref, commits from common ancestor:
commit 402fce50de2b403a1692fa2a43a982dc9687d53e
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..59ff34f68a32 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -91,9 +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 run in
+the main thread. We're emulating Windows out-of-order PeekMessage processing,
+via a YieldWakeupEvent and two conditionals. When in a RUNINMAIN call, all
+the DBG_TESTSOLARMUTEX calls are disabled, as we can't release the SolarMutex,
+but we can prevent running any other SolarMutex based code. Same for all the
+SolarMutex acquire and release calls, so the calling and the main thread
+don't deadlock.
+
+We can neigher rely on MacOS dispatch_sync code block execution nor the
+message handling, as both can't be priorized or filtered and the first
+does also not allow nested execution.
+
+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.
@@ -154,3 +171,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 c2b1116b13c3406b71878e3361d5183d39f14621
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 76fb1da00836..14ade5917ed8 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -81,6 +81,7 @@ public:
     osl::Mutex                              maUserEventListMutex;
     osl::Condition                          maWaitingYieldCond;
     bool                                    mbNoYieldLock;
+    bool                                    mbIsLiveResize;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm
index 162f559f523b..d205c0b3b1db 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -528,6 +528,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 11e6655ad2ce..42aa9caf5779 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -377,6 +377,7 @@ AquaSalInstance::AquaSalInstance()
  : maUserEventListMutex()
  , maWaitingYieldCond()
  , mbNoYieldLock( 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 149e4b7b995e505d138a015ccf9d83c3a4aade9e
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..e9ef9113d041
--- /dev/null
+++ b/vcl/inc/osx/runinmain.hxx
@@ -0,0 +1,150 @@
+/* -*- 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.
+ *
+ * These macros are always used like a recursive calls, so they work like
+ * a closure.
+ *
+ * Uses two conditionals for a two way communication.
+ * The data (code block + result) is protected by the SolarMutex.
+ *
+ * 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 <unordered_map>
+
+#include <Block.h>
+
+#include <osl/thread.h>
+
+#include "saltimer.h"
+#include "salframe.hxx"
+
+union RuninmainResult
+{
+    void*                            pointer;
+    bool                             boolean;
+    struct SalFrame::SalPointerState state;
+
+    RuninmainResult() {}
+};
+
+#define OSX_RUNINMAIN_MEMBERS \
+    osl::Condition          m_aInMainCondition; \
+    osl::Condition          m_aResultCondition; \
+    RuninmainBlock          m_aCodeBlock; \
+    RuninmainResult         m_aResult;
+
+#define OSX_RUNINMAIN( instance, command ) \
+    if ( !instance->IsMainThread() ) \
+    { \
+        DBG_TESTSOLARMUTEX(); \
+        SalYieldMutex *aMutex = static_cast<SalYieldMutex*>(instance->GetYieldMutex()); \
+        assert( !aMutex->m_aCodeBlock ); \
+        aMutex->m_aCodeBlock = Block_copy(^{ \
+            command; \
+        }); \
+        aMutex->m_aResultCondition.reset(); \
+        dispatch_async(dispatch_get_main_queue(),^{ \
+            ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
+            }); \
+        aMutex->m_aInMainCondition.set(); \
+        osl::Condition::Result res =  aMutex->m_aResultCondition.wait(); \
+        assert(osl::Condition::Result::result_ok == res); \
+        return; \
+    }
+
+#define OSX_RUNINMAIN_POINTER( instance, command, type ) \
+    if ( !instance->IsMainThread() ) \
+    { \
+        DBG_TESTSOLARMUTEX(); \
+        SalYieldMutex *aMutex = static_cast<SalYieldMutex*>(instance->GetYieldMutex()); \
+        assert( !aMutex->m_aCodeBlock ); \
+        aMutex->m_aCodeBlock = Block_copy(^{ \
+            aMutex->m_aResult.pointer = static_cast<void*>( command ); \
+        }); \
+        aMutex->m_aResultCondition.reset(); \
+        dispatch_async(dispatch_get_main_queue(),^{ \
+            ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
+            }); \
+        aMutex->m_aInMainCondition.set(); \
+        osl::Condition::Result res =  aMutex->m_aResultCondition.wait(); \
+        assert(osl::Condition::Result::result_ok == res); \
+        return static_cast<type>( aMutex->m_aResult.pointer ); \
+    }
+
+#define OSX_RUNINMAIN_UNION( instance, command, member ) \
+    if ( !instance->IsMainThread() ) \
+    { \
+        DBG_TESTSOLARMUTEX(); \
+        SalYieldMutex *aMutex = static_cast<SalYieldMutex*>(instance->GetYieldMutex()); \
+        assert( !aMutex->m_aCodeBlock ); \
+        aMutex->m_aCodeBlock = Block_copy(^{ \
+            aMutex->m_aResult.member = command; \
+        }); \
+        aMutex->m_aResultCondition.reset(); \
+        dispatch_async(dispatch_get_main_queue(),^{ \
+            ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
+            }); \
+        aMutex->m_aInMainCondition.set(); \
+        osl::Condition::Result res =  aMutex->m_aResultCondition.wait(); \
+        assert(osl::Condition::Result::result_ok == res); \
+        return std::move( aMutex->m_aResult.member ); \
+    }
+
+/**
+ * convenience macros used from SalInstance
+ */
+
+#define OSX_INST_RUNINMAIN( command ) \
+    OSX_RUNINMAIN( this, command )
+
+#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 using global SalData
+ */
+
+#define OSX_SALDATA_RUNINMAIN( command ) \
+    OSX_RUNINMAIN( GetSalData()->mpFirstInstance, command )
+
+#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..1cbdabb88563 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;
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 8d5a7451da68..76fb1da00836 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -32,14 +32,21 @@
 #endif
 #include "salinst.hxx"
 
+#include "osx/runinmain.hxx"
+
 class AquaSalFrame;
+class SalFrame;
+class SalObject;
 class ApplicationEvent;
 class Image;
 enum class SalEvent;
 
+typedef void(^RuninmainBlock)(void);
+
 class SalYieldMutex : public comphelper::GenericSolarMutex
 {
-    bool                    mbInAquireWithTry;
+public:
+    OSX_RUNINMAIN_MEMBERS
 
 protected:
     virtual void            doAcquire( sal_uInt32 nLockCount ) override;
@@ -48,6 +55,8 @@ protected:
 public:
     SalYieldMutex();
     virtual ~SalYieldMutex();
+
+    virtual bool IsCurrentThread() const override;
 };
 
 class AquaSalInstance : public SalInstance
@@ -71,6 +80,7 @@ public:
     std::list< SalUserEvent >               maUserEvents;
     osl::Mutex                              maUserEventListMutex;
     osl::Condition                          maWaitingYieldCond;
+    bool                                    mbNoYieldLock;
 
     static std::list<const ApplicationEvent*> aAppEventList;
 
@@ -146,8 +156,9 @@ public:
     static const short AppExecuteSVMain   = 0x7fff;
     static const short AppEndLoopEvent    = 1;
     static const short AppStartTimerEvent = 10;
-    static const short PostedUserEvent    = 20;
+    static const short YieldWakeupEvent   = 20;
     static const short DispatchTimerEvent = 30;
+    static const short PostedUserEvent    = 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..e54073cdf4f1 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( 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/salinst.cxx b/vcl/osx/salinst.cxx
index f41723001b14..11e6655ad2ce 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"
@@ -259,7 +260,7 @@ void InitSalMain()
 }
 
 SalYieldMutex::SalYieldMutex()
-    : mbInAquireWithTry( false )
+    : m_aCodeBlock( nullptr )
 {
 }
 
@@ -269,22 +270,31 @@ SalYieldMutex::~SalYieldMutex()
 
 void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
 {
-    if ( GetSalData()->mpFirstInstance && GetSalData()->mpFirstInstance->IsMainThread() )
+    AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+    if ( pInst && pInst->IsMainThread() )
     {
-        while ( !m_aMutex.tryToAcquire() )
-        {
-            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 ( AquaSalInstance::UnlockedYieldMutexEvent != (int) [pPeekEvent subtype] )
-                [NSApp postEvent: pPeekEvent atStart: YES];
+        if ( pInst->mbNoYieldLock )
+            return;
+        do {
+            m_aInMainCondition.reset();
+            if ( m_aCodeBlock )
+            {
+                assert( !pInst->mbNoYieldLock );
+                pInst->mbNoYieldLock = true;
+                m_aCodeBlock();
+                pInst->mbNoYieldLock = false;
+                Block_release( m_aCodeBlock );
+                m_aCodeBlock = nullptr;
+                m_aResultCondition.set();
+            }
+            // reset condition *before* acquiring!
+            if (m_aMutex.tryToAcquire())
+                break;
+            // wait for doRelease() or RUNINMAIN_* to set the condition
+            osl::Condition::Result res =  m_aInMainCondition.wait();
+            assert(osl::Condition::Result::result_ok == res);
         }
-        mbInAquireWithTry = false;
+        while ( true );
     }
     else
         m_aMutex.acquire();
@@ -296,17 +306,25 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
 
 sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
 {
+    AquaSalInstance *pInst = GetSalData()->mpFirstInstance;
+    if ( pInst->mbNoYieldLock && pInst->IsMainThread() )
+        return 1;
     sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll );
 
-    if ( mbInAquireWithTry && 0 == m_nCount
-            && !GetSalData()->mpFirstInstance->IsMainThread() )
-        dispatch_async(dispatch_get_main_queue(),^{
-            ImplNSAppPostEvent( AquaSalInstance::UnlockedYieldMutexEvent, NO );
-            });
+    if ( 0 == m_nCount && !pInst->IsMainThread() )
+        m_aInMainCondition.set();
 
     return nCount;
 }
 
+bool SalYieldMutex::IsCurrentThread() const
+{
+    if ( !GetSalData()->mpFirstInstance->mbNoYieldLock )
+        return comphelper::GenericSolarMutex::IsCurrentThread();
+    else
+        return GetSalData()->mpFirstInstance->IsMainThread();
+}
+
 // some convenience functions regarding the yield mutex, aka solar mutex
 
 bool ImplSalYieldMutexTryToAcquire()
@@ -358,6 +376,7 @@ void DestroySalInstance( SalInstance* pInst )
 AquaSalInstance::AquaSalInstance()
  : maUserEventListMutex()
  , maWaitingYieldCond()
+ , mbNoYieldLock( false )
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
@@ -453,6 +472,9 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
         }
         break;
     }
+    case YieldWakeupEvent:
+        // do nothing
+        break;
 #if !HAVE_FEATURE_MACOSX_SANDBOX
     case AppleRemoteControlEvent: // Defined in <apple_remote/RemoteMainController.h>
     {
@@ -578,7 +600,10 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
                             inMode: NSDefaultRunLoopMode
                             dequeue: YES];
             if( pEvent )
+            {
                 [NSApp sendEvent: pEvent];
+                bHadEvent = true;
+            }
             [NSApp updateWindows];
         }
 
@@ -640,6 +665,8 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType )
             return false;
     }
 
+    OSX_INST_RUNINMAIN_UNION( AnyInput( nType ), boolean )
+
     if( nType & VclInputFlags::TIMER )
     {
         if( AquaSalTimer::pRunningTimer )
@@ -652,9 +679,6 @@ bool AquaSalInstance::AnyInput( VclInputFlags nType )
         }
     }
 
-    if (!IsMainThread())
-        return false;
-
     unsigned/*NSUInteger*/ nEventMask = 0;
 SAL_WNODEPRECATED_DECLARATIONS_PUSH
         // 'NSFlagsChangedMask' is deprecated: first deprecated in macOS 10.12
@@ -702,29 +726,28 @@ SalFrame* AquaSalInstance::CreateChildFrame( SystemParentData*, SalFrameStyleFla
 
 SalFrame* AquaSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nSalFrameStyle )
 {
-    SalData::ensureThreadAutoreleasePool();
-
-    SalFrame* pFrame = new AquaSalFrame( pParent, nSalFrameStyle );
-    return pFrame;
+    OSX_INST_RUNINMAIN_POINTER( CreateFrame( pParent, nSalFrameStyle ), SalFrame* )
+    return new AquaSalFrame( pParent, nSalFrameStyle );
 }
 
 void AquaSalInstance::DestroyFrame( SalFrame* pFrame )
 {
+    OSX_INST_RUNINMAIN( DestroyFrame( pFrame ) )
     delete pFrame;
 }
 
 SalObject* AquaSalInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData, bool /* bShow */ )
 {
-    AquaSalObject *pObject = nullptr;
-
-    if ( pParent )
-        pObject = new AquaSalObject( static_cast<AquaSalFrame*>(pParent), pWindowData );
+    if ( !pParent )
+        return nullptr;
 
-    return pObject;
+    OSX_INST_RUNINMAIN_POINTER( CreateObject( pParent, pWindowData, false ), SalObject* )
+    return new AquaSalObject( static_cast<AquaSalFrame*>(pParent), pWindowData );
 }
 
 void AquaSalInstance::DestroyObject( SalObject* pObject )
 {
+    OSX_INST_RUNINMAIN( DestroyObject( pObject ) )
     delete pObject;
 }
 
diff --git a/vcl/osx/salobj.cxx b/vcl/osx/salobj.cxx
index 957f017363fc..4113d43caf3c 100644
--- a/vcl/osx/salobj.cxx
+++ b/vcl/osx/salobj.cxx
@@ -26,6 +26,7 @@
 #include "osx/salframe.h"
 #include "osx/salinst.h"
 #include "osx/salobj.h"
+#include "osx/runinmain.hxx"
 
 #include <AppKit/NSOpenGLView.h>
 
@@ -105,6 +106,8 @@ AquaSalObject::AquaSalObject( AquaSalFrame* pFrame, SystemWindowData* pWindowDat
 
 AquaSalObject::~AquaSalObject()
 {
+    assert( GetSalData()->mpFirstInstance->IsMainThread() );
+
     if( maSysData.mpNSView )
     {
         NSView *pView = maSysData.mpNSView;
@@ -194,6 +197,8 @@ void AquaSalObject::SetPosSize( long nX, long nY, long nWidth, long nHeight )
 
 void AquaSalObject::setClippedPosSize()
 {
+    OSX_SALDATA_RUNINMAIN( setClippedPosSize() )
+
     NSRect aViewRect = { NSZeroPoint, NSMakeSize( mnWidth, mnHeight) };
     if( maSysData.mpNSView )
     {
@@ -222,8 +227,12 @@ void AquaSalObject::setClippedPosSize()
 
 void AquaSalObject::Show( bool bVisible )
 {
-    if( mpClipView )
-        [mpClipView setHidden: (bVisible ? NO : YES)];
+    if( !mpClipView )
+        return;
+
+    OSX_SALDATA_RUNINMAIN( Show( bVisible ) )
+
+    [mpClipView setHidden: (bVisible ? NO : YES)];
 }
 
 const SystemEnvData* AquaSalObject::GetSystemData() const
@@ -235,8 +244,10 @@ class AquaOpenGLContext : public OpenGLContext
 {
 public:
     virtual bool initWindow() override;
+
 private:
     GLWindow m_aGLWin;
+
     virtual const GLWindow& getOpenGLWindow() const override { return m_aGLWin; }
     virtual GLWindow& getModifiableOpenGLWindow() override { return m_aGLWin; }
     NSOpenGLView* getOpenGLView();
@@ -250,6 +261,8 @@ private:
 
 void AquaOpenGLContext::resetCurrent()
 {
+    OSX_SALDATA_RUNINMAIN( resetCurrent() )
+
     clearCurrent();
 
     OpenGLZone aZone;
@@ -260,6 +273,8 @@ void AquaOpenGLContext::resetCurrent()
 
 void AquaOpenGLContext::makeCurrent()
 {
+    OSX_SALDATA_RUNINMAIN( makeCurrent() )
+
     if (isCurrent())
         return;
 
@@ -275,6 +290,8 @@ void AquaOpenGLContext::makeCurrent()
 
 void AquaOpenGLContext::swapBuffers()
 {
+    OSX_SALDATA_RUNINMAIN( swapBuffers() )
+
     OpenGLZone aZone;
 
     NSOpenGLView* pView = getOpenGLView();
@@ -293,11 +310,14 @@ SystemWindowData AquaOpenGLContext::generateWinData(vcl::Window* /*pParent*/, bo
 
 void AquaOpenGLContext::destroyCurrentContext()
 {
+    OSX_SALDATA_RUNINMAIN( destroyCurrentContext() )
     [NSOpenGLContext clearCurrentContext];
 }
 
 bool AquaOpenGLContext::initWindow()
 {
+    OSX_SALDATA_RUNINMAIN_UNION( initWindow(), boolean )
+
     if( !m_pChildWindow )
     {
         SystemWindowData winData = generateWinData(mpWindow, mbRequestLegacyContext);
@@ -314,6 +334,8 @@ bool AquaOpenGLContext::initWindow()
 
 bool AquaOpenGLContext::ImplInit()
 {
+    OSX_SALDATA_RUNINMAIN_UNION( ImplInit(), boolean )
+
     OpenGLZone aZone;
 
     VCL_GL_INFO("OpenGLContext::ImplInit----start");
@@ -332,6 +354,7 @@ NSOpenGLView* AquaOpenGLContext::getOpenGLView()
 
 OpenGLContext* AquaSalInstance::CreateOpenGLContext()
 {
+    OSX_SALDATA_RUNINMAIN_POINTER( CreateOpenGLContext(), OpenGLContext* )
     return new AquaOpenGLContext;
 }
 
diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx
index 3cf74529a301..62814759ae1a 100644
--- a/vcl/osx/saltimer.cxx
+++ b/vcl/osx/saltimer.cxx
@@ -131,9 +131,10 @@ static void ImplSalStopTimer()
 void AquaSalTimer::handleDispatchTimerEvent()
 {
     ImplSVData* pSVData = ImplGetSVData();
-    SolarMutexGuard aGuard;
+    GetSalData()->mpFirstInstance->AcquireYieldMutex( 1 );
     if( pSVData->maSchedCtx.mpSalTimer )
         pSVData->maSchedCtx.mpSalTimer->CallCallback();
+    GetSalData()->mpFirstInstance->ReleaseYieldMutex( false );
 }
 
 void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent )
commit 5c49e92a25ae8047d5436cbf5ebfa8c284bbd19d
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Aug 18 23:26:23 2017 +0200

    Unify SolarMutex implementations
    
    All backends implement the SolarMutex in mostly the same way.
    So this consolidates this code into a GenericSolarMutex.
    
    We still need the abstract SolarMutex class for all these fake
    AKA fascade implementations.
    
    The patch also replaces various places of direct mutex usage with
    either SolarMutexGuard or SolarMutexReleaser objects.
    
    Change-Id: Ia0146dd6c51a3b9a513cc6af34a66def58aad831

diff --git a/comphelper/source/misc/solarmutex.cxx b/comphelper/source/misc/solarmutex.cxx
index 4b573078dffd..66b783f3368c 100644
--- a/comphelper/source/misc/solarmutex.cxx
+++ b/comphelper/source/misc/solarmutex.cxx
@@ -42,6 +42,67 @@ 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 )
+{
+    for ( sal_uInt32 n = nLockCount; n ; --n )
+        m_aMutex.acquire();
+    m_nThreadId = osl::Thread::getCurrentIdentifier();
+    m_nCount += nLockCount;
+}
+
+sal_uInt32 GenericSolarMutex::doRelease( bool bUnlockAll )
+{
+    if ( m_nCount == 0 )
+        abort();
+    if ( m_nThreadId != osl::Thread::getCurrentIdentifier() )
+        abort();
+
+    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::IsCurrentThread() const
+{
+    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..6d57f98710e4 100644
--- a/dbaccess/Module_dbaccess.mk
+++ b/dbaccess/Module_dbaccess.mk
@@ -12,23 +12,23 @@ $(eval $(call gb_Module_Module,dbaccess))
 ifneq (,$(filter DBCONNECTIVITY,$(BUILD_TYPE)))
 
 $(eval $(call gb_Module_add_targets,dbaccess,\
-	$(if $(filter WNT,$(OS)),Executable_odbcconfig) \
-	Library_dba \
-	Library_dbaxml \
-	Library_dbmm \
-	Library_dbu \
-	Library_sdbt \
-	UIConfig_dbaccess \
-	UIConfig_dbapp \
-	UIConfig_dbbrowser \
-	UIConfig_dbquery \
-	UIConfig_dbrelation \
-	UIConfig_dbtable \
-	UIConfig_dbtdata \
+    $(if $(filter WNT,$(OS)),Executable_odbcconfig) \
+        Library_dba \
+        Library_dbaxml \
+        Library_dbmm \
+        Library_dbu \
+        Library_sdbt \
+        UIConfig_dbaccess \
+        UIConfig_dbapp \
+        UIConfig_dbbrowser \
+        UIConfig_dbquery \
+        UIConfig_dbrelation \
+        UIConfig_dbtable \
+        UIConfig_dbtdata \
 ))
 
 $(eval $(call gb_Module_add_l10n_targets,dbaccess,\
-	AllLangMoTarget_dba \
+    AllLangMoTarget_dba \
 ))
 
 ifneq ($(OS),IOS)
@@ -39,16 +39,15 @@ $(eval $(call gb_Module_add_check_targets,dbaccess,\
 endif
 
 $(eval $(call gb_Module_add_check_targets,dbaccess,\
-	CppunitTest_dbaccess_dialog_save \
-	CppunitTest_dbaccess_empty_stdlib_save \
-	CppunitTest_dbaccess_nolib_save \
-	CppunitTest_dbaccess_macros_test \
-	$(if $(ENABLE_JAVA), \
-		CppunitTest_dbaccess_RowSetClones) \
+    CppunitTest_dbaccess_dialog_save \
+    CppunitTest_dbaccess_empty_stdlib_save \
+    CppunitTest_dbaccess_nolib_save \
+    CppunitTest_dbaccess_macros_test \
 ))
 
 ifeq ($(ENABLE_JAVA),TRUE)
 $(eval $(call gb_Module_add_check_targets,dbaccess,\
+    CppunitTest_dbaccess_RowSetClones \
     CppunitTest_dbaccess_hsqldb_test \
 ))
 endif
@@ -64,14 +63,14 @@ endif
 endif
 
 $(eval $(call gb_Module_add_subsequentcheck_targets,dbaccess,\
-	JunitTest_dbaccess_complex \
+    JunitTest_dbaccess_complex \
     JunitTest_dbaccess_unoapi \
 ))
 
 ifneq ($(DISABLE_PYTHON),TRUE)
 ifneq ($(ENABLE_JAVA),)
 $(eval $(call gb_Module_add_subsequentcheck_targets,dbaccess,\
-	PythonTest_dbaccess_python \
+    PythonTest_dbaccess_python \
 ))
 endif
 endif
diff --git a/dbaccess/source/core/dataaccess/ModelImpl.cxx b/dbaccess/source/core/dataaccess/ModelImpl.cxx
index bbbe69d5f52f..3ddffa4caa52 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::IsCurrentThread() const
+{
+    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..034e1bbd4b8d 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 IsCurrentThread() const 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..7efd4bd0dc40 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,82 @@ namespace comphelper {
  */
 class COMPHELPER_DLLPUBLIC SolarMutex {
 public:
-    virtual void acquire() = 0;
+    typedef void (*BeforeReleaseHandler) ();
 
-    virtual void release() = 0;
+    void acquire( sal_uInt32 nLockCount = 1 );
+    sal_uInt32 release( bool bReleaseAll = false );
 
     virtual bool tryToAcquire() = 0;
 
+    // returns true, if the mutex is owned by the current thread
+    virtual bool IsCurrentThread() const = 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;
 };
 
+inline void SolarMutex::acquire( sal_uInt32 nLockCount )
+{
+    assert( nLockCount > 0 );
+    doAcquire( nLockCount );
+}
+
+inline sal_uInt32 SolarMutex::release( bool bReleaseAll )
+{
+     return doRelease( bReleaseAll );
+}
+
+
+/**
+ * Generic implementation of the abstract SolarMutex interface.
+ *
+ * Treat this as a singleton, as its constructor calls
+ * setSolarMutex( this )!
+ *
+ * Kept seperately from SolarMutex, so others can implement fascades.
+ */
+class COMPHELPER_DLLPUBLIC GenericSolarMutex
+    : public SolarMutex
+{
+public:
+    void SetBeforeReleaseHandler( const BeforeReleaseHandler& rLink )
+         { m_aBeforeReleaseHandler = rLink; }
+
+    virtual bool tryToAcquire() override;
+    virtual bool IsCurrentThread() const override;
+
+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/osl/mutex.hxx b/include/osl/mutex.hxx
index f42323b9fd0a..7ff265f149ed 100644
--- a/include/osl/mutex.hxx
+++ b/include/osl/mutex.hxx
@@ -110,29 +110,36 @@ namespace osl
     private:
         Guard( const Guard& ) SAL_DELETED_FUNCTION;
         const Guard& operator = ( const Guard& ) SAL_DELETED_FUNCTION;
-
     protected:
-        T * pT;
+        T * m_pT;
+        const bool m_bAquired;
     public:
 
         /** Acquires the object specified as parameter.
         */
-        Guard(T * pT_) : pT(pT_)
+        Guard(T * pT, bool bAquire = true)
+            : m_pT(pT)
+            , m_bAquired(bAquire)
         {
-            pT->acquire();
+            if ( m_bAquired )
+                m_pT->acquire();
         }
 
         /** Acquires the object specified as parameter.
         */
-        Guard(T & t) : pT(&t)
+        Guard(T & rT, bool bAquire = true)
+            : m_pT(&rT)
+            , m_bAquired( bAquire )
         {
-            pT->acquire();
+            if ( m_bAquired )
+                m_pT->acquire();
         }
 
         /** Releases the mutex or interface. */
         ~Guard()
         {
-            pT->release();
+            if ( m_bAquired )
+                m_pT->release();
         }
     };
 
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index d5b81b2a20a4..f70feabdde61 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>
@@ -531,7 +532,7 @@ public:
      @see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
           GetMainThreadIdentifier, AcquireSolarMutex,
     */
-    static sal_uLong            ReleaseSolarMutex();
+    static sal_uInt32           ReleaseSolarMutex();
 
     /** @brief Acquire Solar Mutex(es) for this thread.
 
@@ -541,7 +542,7 @@ public:
      @see Execute, Quit, Reschedule, Yield, EndYield, GetSolarMutex,
           GetMainThreadIdentifier, ReleaseSolarMutex,
     */
-    static void                 AcquireSolarMutex( sal_uLong nCount );
+    static void                 AcquireSolarMutex( sal_uInt32 nCount );
 
     /** Queries whether the application is in "main", i.e. not yet in
         the event loop
@@ -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( bool bAcquire = true )
+        : osl::Guard<comphelper::SolarMutex>( Application::GetSolarMutex(), bAcquire ) {}
 };
 
-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
@@ -1553,14 +1472,20 @@ public:
 */
 class SolarMutexReleaser
 {
-    sal_uLong mnReleased;
+    sal_uInt32 mnReleased;
 
 public:
-    SolarMutexReleaser(): mnReleased(Application::ReleaseSolarMutex()) {}
+    SolarMutexReleaser( bool bDoRelease = true )
+        : mnReleased( 0 )
+    {
+        if ( bDoRelease )
+             mnReleased = Application::ReleaseSolarMutex();
+    }
 
     ~SolarMutexReleaser()
     {
-        Application::ReAcquireSolarMutex(mnReleased);
+        if ( mnReleased )
+            Application::ReAcquireSolarMutex( mnReleased );
     }
 };
 
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/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 4ebeac8f4a3c..b75a035466f1 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -389,7 +389,7 @@ void SvpSalInstance::DoReleaseYield( int nTimeoutMS )
     aPoll.revents = 0;
 
     // release yield mutex
-    sal_uLong nAcquireCount = ReleaseYieldMutex();
+    sal_uInt32 nAcquireCount = ReleaseYieldMutex( true );
 
     (void)poll( &aPoll, 1, nTimeoutMS );
 
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index f47ae7cc8303..8d5a7451da68 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -37,19 +37,17 @@ 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 ~SalYieldMutex();
 };
 
 class AquaSalInstance : public SalInstance
@@ -103,9 +101,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 bool            CheckYieldMutex() override;
+    virtual sal_uInt32      ReleaseYieldMutex( bool bUnlockAll = false ) override;
+    virtual void            AcquireYieldMutex( sal_uInt32 nCount = 1 ) override;
     virtual bool            DoYield(bool bWait, bool bHandleAllCurrentEvents,
                                     sal_uLong nReleased) override;
     virtual bool            AnyInput( VclInputFlags nType ) override;
@@ -155,15 +152,6 @@ public:
     static NSMenu* GetDynamicDockMenu();
 };
 
-// helper class: inverted solar guard
-class YieldMutexReleaser
-{
-    sal_uLong mnCount;
-    public:
-    YieldMutexReleaser();
-    ~YieldMutexReleaser();
-};
-
 CGImageRef CreateCGImage( const Image& );
 NSImage*   CreateNSImage( const Image& );
 
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index fc8febbf035f..19136e9d7747 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,10 +122,9 @@ 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..5b3cbc9c98b6 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,8 @@ 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;
 
     // Printing
     virtual SalInfoPrinter*     CreateInfoPrinter      ( SalPrinterQueueInfo* pQueueInfo,
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index 4d8361d57325..bc5b9c5db1eb 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -172,11 +172,9 @@ bool ImplLoadSalIcon( int nId, HICON& rIcon, HICON& rSmallIcon );
 void ImplInitSalGDI();
 void ImplFreeSalGDI();
 
-void ImplSalYieldMutexAcquireWithWait( sal_uLong nCount = 1 );
+void ImplSalYieldMutexAcquireWithWait( sal_uInt32 nCount = 1 );
 bool ImplSalYieldMutexTryToAcquire();
 void ImplSalYieldMutexRelease();
-sal_uLong ImplSalReleaseYieldMutex();
-void ImplSalAcquireYieldMutex( sal_uLong nCount );
 
 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
 
diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h
index 3683e9369cfa..6efecbd6bd5e 100644
--- a/vcl/inc/win/salinst.h
+++ b/vcl/inc/win/salinst.h
@@ -59,9 +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 bool                CheckYieldMutex() override;
+    virtual sal_uInt32          ReleaseYieldMutex( bool bUnlockAll = false ) override;
+    virtual void                AcquireYieldMutex( sal_uInt32 nCount = 1 ) override;
     virtual bool                IsMainThread() const override;
 
     virtual bool                DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong nReleased) override;
diff --git a/vcl/inc/win/salprn.h b/vcl/inc/win/salprn.h
index a483e2502cc7..ed6005283661 100644
--- a/vcl/inc/win/salprn.h
+++ b/vcl/inc/win/salprn.h
@@ -84,6 +84,9 @@ public:
 
     bool                    mbValid;
 
+protected:
+    void                            DoEndDoc(HDC hDC);
+
 public:
     WinSalPrinter();
     virtual ~WinSalPrinter() 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 e290891ce294..162f559f523b 100644
--- a/vcl/osx/salframeview.mm
+++ b/vcl/osx/salframeview.mm
@@ -223,13 +223,8 @@ static AquaSalFrame* getMouseContainerFrame()
 {
     if( GetSalData() && GetSalData()->mpFirstInstance )
     {
-        comphelper::SolarMutex* pMutex = GetSalData()->mpFirstInstance->GetYieldMutex();
-        if( pMutex )
-        {
-            pMutex->acquire();
-            [super displayIfNeeded];
-            pMutex->release();
-        }
+        SolarMutexGuard aGuard;
+        [super displayIfNeeded];
     }
 }
 
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 45b7da6e36ee..f41723001b14 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -259,42 +259,52 @@ void InitSalMain()
 }
 
 SalYieldMutex::SalYieldMutex()
+    : mbInAquireWithTry( false )
 {
-    mnCount  = 0;
-    mnThreadId  = 0;
 }
 
-void SalYieldMutex::acquire()
+SalYieldMutex::~SalYieldMutex()
 {
-    m_mutex.acquire();
-    mnThreadId = osl::Thread::getCurrentIdentifier();
-    mnCount++;
 }
 
-void SalYieldMutex::release()
+void SalYieldMutex::doAcquire( sal_uInt32 nLockCount )
 {
-    if ( mnThreadId == osl::Thread::getCurrentIdentifier() )
+    if ( GetSalData()->mpFirstInstance && GetSalData()->mpFirstInstance->IsMainThread() )
     {
-        if ( mnCount == 1 )
+        while ( !m_aMutex.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 ( AquaSalInstance::UnlockedYieldMutexEvent != (int) [pPeekEvent subtype] )
+                [NSApp postEvent: pPeekEvent atStart: YES];
         }
-        mnCount--;
+        mbInAquireWithTry = false;
     }
-    m_mutex.release();
+    else
+        m_aMutex.acquire();
+    ++m_nCount;
+    --nLockCount;
+
+    comphelper::GenericSolarMutex::doAcquire( nLockCount );
 }
 
-bool SalYieldMutex::tryToAcquire()
+sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
 {
-    if ( m_mutex.tryToAcquire() )
-    {
-        mnThreadId = osl::Thread::getCurrentIdentifier();
-        mnCount++;
-        return true;
-    }
-    else
-        return false;
+    sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll );
+
+    if ( mbInAquireWithTry && 0 == m_nCount
+            && !GetSalData()->mpFirstInstance->IsMainThread() )
+        dispatch_async(dispatch_get_main_queue(),^{
+            ImplNSAppPostEvent( AquaSalInstance::UnlockedYieldMutexEvent, NO );
+            });
+
+    return nCount;
 }
 
 // some convenience functions regarding the yield mutex, aka solar mutex
@@ -351,14 +361,12 @@ AquaSalInstance::AquaSalInstance()
 {
     mpSalYieldMutex = new SalYieldMutex;
     mpSalYieldMutex->acquire();
-    ::comphelper::SolarMutex::setSolarMutex( mpSalYieldMutex );
     maMainThread = osl::Thread::getCurrentIdentifier();
     mnActivePrintJobs = 0;
 }
 
 AquaSalInstance::~AquaSalInstance()
 {
-    ::comphelper::SolarMutex::setSolarMutex( nullptr );
     mpSalYieldMutex->release();
     delete mpSalYieldMutex;
 }
@@ -380,48 +388,14 @@ comphelper::SolarMutex* AquaSalInstance::GetYieldMutex()
     return mpSalYieldMutex;
 }
 
-sal_uLong AquaSalInstance::ReleaseYieldMutex( bool bUnlockAll )
+sal_uInt32 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--;
-        }
-
-        return nCount;
-    }
-    else
-        return 0;
+    return mpSalYieldMutex->release( bUnlockAll );
 }
 
-void AquaSalInstance::AcquireYieldMutex( sal_uLong nCount )
+void AquaSalInstance::AcquireYieldMutex( sal_uInt32 nCount )
 {
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex;
-    while ( nCount )
-    {
-        pYieldMutex->acquire();
-        nCount--;
-    }
-}
-
-bool AquaSalInstance::CheckYieldMutex()
-{
-    bool bRet = true;
-
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex;
-    if ( pYieldMutex->GetThreadId() != osl::Thread::getCurrentIdentifier())
-    {
-        bRet = false;
-    }
-
-    return bRet;
+    mpSalYieldMutex->acquire( nCount );
 }
 
 bool AquaSalInstance::IsMainThread() const
@@ -473,7 +447,7 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent )
         // dispatch it
         if ( aEvent.mpFrame )
         {
-            osl::Guard< comphelper::SolarMutex > aGuard( *mpSalYieldMutex );
+            SolarMutexGuard aGuard;
             if ( AquaSalFrame::isAlive( aEvent.mpFrame ) )
                 aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData );
         }
@@ -573,8 +547,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,18 +556,18 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
                             dequeue: YES];
             if( pEvent )
             {
+                SolarMutexReleaser aReleaser;
                 [NSApp sendEvent: pEvent];
+                [NSApp updateWindows];
                 bHadEvent = true;
             }
-            [NSApp updateWindows];
-
-            AcquireYieldMutex( nCount );
-        } while( bHandleAllCurrentEvents && pEvent );
+        }
+        while( bHandleAllCurrentEvents && pEvent );
 
         // if we had no event yet, wait for one if requested
         if( bWait && ! bHadEvent )
         {
-            sal_uLong nCount = ReleaseYieldMutex();
+            SolarMutexReleaser aReleaser;
 
             NSDate* pDt = AquaSalTimer::pRunningTimer ? [AquaSalTimer::pRunningTimer fireDate] : [NSDate distantFuture];
 SAL_WNODEPRECATED_DECLARATIONS_PUSH
@@ -608,8 +580,6 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
             if( pEvent )
                 [NSApp sendEvent: pEvent];
             [NSApp updateWindows];
-
-            AcquireYieldMutex( nCount );
         }
 
         // collect update rectangles
@@ -630,10 +600,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 );
-        AcquireYieldMutex( nCount );
+        SolarMutexReleaser aReleaser;
+        maWaitingYieldCond.wait();
     }
 
     // we get some apple events way too early
@@ -957,23 +925,6 @@ OUString AquaSalInstance::getOSVersion()
     return aVersion;
 }
 
-// YieldMutexReleaser
-YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 )
-{
-    SalData* pSalData = GetSalData();
-    if( ! pSalData->mpFirstInstance->IsMainThread() )
-    {
-        SalData::ensureThreadAutoreleasePool();
-        mnCount = pSalData->mpFirstInstance->ReleaseYieldMutex();
-    }
-}
-
-YieldMutexReleaser::~YieldMutexReleaser()
-{
-    if( mnCount != 0 )
-        GetSalData()->mpFirstInstance->AcquireYieldMutex( mnCount );
-}
-
 CGImageRef CreateCGImage( const Image& rImage )
 {
     BitmapEx aBmpEx( rImage.GetBitmapEx() );
diff --git a/vcl/source/app/dbggui.cxx b/vcl/source/app/dbggui.cxx
index b191ae9a5b9d..f2ebc5117ddd 100644
--- a/vcl/source/app/dbggui.cxx
+++ b/vcl/source/app/dbggui.cxx
@@ -44,7 +44,7 @@ using namespace ::com::sun::star;
 
 void ImplDbgTestSolarMutex()
 {
-    assert(ImplGetSVData()->mpDefInst->CheckYieldMutex() && "SolarMutex not locked");
+    assert(ImplGetSVData()->mpDefInst->GetYieldMutex()->IsCurrentThread() && "SolarMutex not owned!");
 }
 
 void DbgGUIInitSolarMutexCheck()
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..6a1c10587696 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -590,13 +590,13 @@ oslThreadIdentifier Application::GetMainThreadIdentifier()
     return ImplGetSVData()->mnMainThreadId;
 }
 
-sal_uLong Application::ReleaseSolarMutex()
+sal_uInt32 Application::ReleaseSolarMutex()
 {
     ImplSVData* pSVData = ImplGetSVData();
-    return pSVData->mpDefInst->ReleaseYieldMutex();
+    return pSVData->mpDefInst->ReleaseYieldMutex( true );
 }
 
-void Application::AcquireSolarMutex( sal_uLong nCount )
+void Application::AcquireSolarMutex( sal_uInt32 nCount )
 {
     ImplSVData* pSVData = ImplGetSVData();
     pSVData->mpDefInst->AcquireYieldMutex( nCount );
diff --git a/vcl/unx/generic/app/geninst.cxx b/vcl/unx/generic/app/geninst.cxx
index b5a954f591f3..d80c0499554c 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,14 @@ 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;
-}
-
-void SalGenericInstance::AcquireYieldMutex( sal_uLong nCount )
-{
-    SalYieldMutex* pYieldMutex = mpSalYieldMutex.get();
-    while ( nCount )
-    {
-        pYieldMutex->acquire();
-        nCount--;
-    }
+    return mpSalYieldMutex.get()->release( bUnlockAll );
 }
 
-bool SalGenericInstance::CheckYieldMutex()
+void SalGenericInstance::AcquireYieldMutex( sal_uInt32 nCount )
 {
-    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;
+    mpSalYieldMutex.get()->acquire( nCount );
 }
 
 SalGenericInstance::~SalGenericInstance()
diff --git a/vcl/unx/generic/app/saldisp.cxx b/vcl/unx/generic/app/saldisp.cxx
index b73c5046a3d2..73d63086bec6 100644
--- a/vcl/unx/generic/app/saldisp.cxx
+++ b/vcl/unx/generic/app/saldisp.cxx
@@ -378,9 +378,8 @@ static int DisplayHasEvent( int fd, void * data )
 
   bool result;
 
-  GetSalData()->m_pInstance->GetYieldMutex()->acquire();
+  SolarMutexGuard aGuard;
   result = pDisplay->IsEvent();
-  GetSalData()->m_pInstance->GetYieldMutex()->release();
   return int(result);
 }
 static int DisplayQueue( int fd, void * data )
@@ -390,11 +389,9 @@ static int DisplayQueue( int fd, void * data )
               "wrong fd in DisplayHasEvent" );
   int result;
 
-  GetSalData()->m_pInstance->GetYieldMutex()->acquire();
+  SolarMutexGuard aGuard;
   result =  XEventsQueued( pDisplay->GetDisplay(),
                         QueuedAfterReading );
-  GetSalData()->m_pInstance->GetYieldMutex()->release();
-
   return result;
 }
 static int DisplayYield( int fd, void * data )
@@ -403,9 +400,8 @@ static int DisplayYield( int fd, void * data )
   SAL_WARN_IF( ConnectionNumber( pDisplay->GetDisplay() ) != fd, "vcl",
               "wrong fd in DisplayHasEvent" );
 
-  GetSalData()->m_pInstance->GetYieldMutex()->acquire();
+  SolarMutexGuard aGuard;
   pDisplay->Yield();
-  GetSalData()->m_pInstance->GetYieldMutex()->release();
   return 1;
 }
 
@@ -1911,8 +1907,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()->IsCurrentThread(),
                 "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/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx
index 29f7d33be75e..19ea9f2f0fcd 100644
--- a/vcl/unx/gtk/gtkdata.cxx
+++ b/vcl/unx/gtk/gtkdata.cxx
@@ -726,9 +726,7 @@ extern "C" {
         if( !pTSource->pInstance )
             return FALSE;
 
-        GtkData *pSalData = static_cast< GtkData* >( GetSalData());
-
-        osl::Guard< comphelper::SolarMutex > aGuard( pSalData->m_pInstance->GetYieldMutex() );
+        SolarMutexGuard aGuard;
 
         sal_gtk_timeout_defer( pTSource );
 
@@ -822,7 +820,7 @@ gboolean GtkData::userEventFn( gpointer data )
     gboolean bContinue = FALSE;
     GtkData *pThis = static_cast<GtkData *>(data);
     SalGenericData *pData = GetGenericData();
-    osl::Guard< comphelper::SolarMutex > aGuard( pData->m_pInstance->GetYieldMutex() );
+    SolarMutexGuard aGuard;
     const SalGenericDisplay *pDisplay = pData->GetDisplay();
     if (pDisplay)
     {
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/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx
index 5308d57be70f..2690c2614ae6 100644
--- a/vcl/unx/gtk3/gtk3gtkdata.cxx
+++ b/vcl/unx/gtk3/gtk3gtkdata.cxx
@@ -688,9 +688,7 @@ extern "C" {
         if( !pTSource->pInstance )
             return FALSE;
 
-        GtkData *pSalData = static_cast< GtkData* >( GetSalData());
-
-        osl::Guard< comphelper::SolarMutex > aGuard( pSalData->m_pInstance->GetYieldMutex() );
+        SolarMutexGuard aGuard;
 
         sal_gtk_timeout_defer( pTSource );
 
@@ -784,7 +782,7 @@ gboolean GtkData::userEventFn( gpointer data )
     gboolean bContinue = FALSE;
     GtkData *pThis = static_cast<GtkData *>(data);
     SalGenericData *pData = GetGenericData();
-    osl::Guard< comphelper::SolarMutex > aGuard( pData->m_pInstance->GetYieldMutex() );
+    SolarMutexGuard aGuard;
     const SalGenericDisplay *pDisplay = pData->GetDisplay();
     if (pDisplay)
     {
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx
index 7c30c7aa40c9..4647b3d111c8 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()->IsCurrentThread(),
                 "will crash soon since solar mutex not locked in SalKDEDisplay::Yield" );
 
     XEvent event;
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 1082b278a041..0561e52b0de4 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -96,87 +96,48 @@ void SalAbort( const OUString& rErrorText, bool )
 
 LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
 
-class SalYieldMutex : public comphelper::SolarMutex
+class SalYieldMutex : public comphelper::GenericSolarMutex
 {
 public: // for ImplSalYield() and ImplSalYieldMutexAcquireWithWait()
-    osl::Mutex                  m_mutex;
-    osl::Condition              m_condition; /// for MsgWaitForMultipleObjects()
-    WinSalInstance*             mpInstData;
-    sal_uLong                   mnCount;
-    DWORD                       mnThreadId;
+    osl::Condition            m_condition; /// for MsgWaitForMultipleObjects()
 
-public:
-    explicit SalYieldMutex( WinSalInstance* pInstData );
+protected:
+    virtual sal_uInt32        doRelease( bool bUnlockAll ) override;
 
-    virtual void                acquire() override;
-    virtual void                release() override;
-    virtual bool                tryToAcquire() override;
+    static void               BeforeReleaseHandler();
 
-    sal_uLong                   GetAcquireCount( sal_uLong nThreadId );
-};
+public:
+    explicit SalYieldMutex();
 
-SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData )
-{
-    mpInstData  = pInstData;
-    mnCount     = 0;
-    mnThreadId  = 0;
-}
+    virtual bool              IsCurrentThread() const override;
+};
 
-void SalYieldMutex::acquire()
+SalYieldMutex::SalYieldMutex()
 {
-    m_mutex.acquire();
-    mnCount++;
-    mnThreadId = GetCurrentThreadId();
+    SetBeforeReleaseHandler( &SalYieldMutex::BeforeReleaseHandler );
 }
 
-void SalYieldMutex::release()
+void SalYieldMutex::BeforeReleaseHandler()
 {
-    DWORD nThreadId = GetCurrentThreadId();
-    assert(mnThreadId == nThreadId);
+    OpenGLContext::prepareForYield();
 
-    bool const isRelease(1 == mnCount);
-    if ( isRelease )
+    if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() )
     {
-        OpenGLContext::prepareForYield();
-
-        SalData* pSalData = GetSalData();
-        if ( pSalData->mnAppThreadId != nThreadId )
-        {
-            // If we don't call these message, the Output from the
-            // Java clients doesn't come in the right order
-            GdiFlush();
-
-        }
-        mnThreadId = 0;
-    }
-
-    mnCount--;
-    m_mutex.release();
-
-    if ( isRelease )
-    {   // do this *after* release
-        m_condition.set(); // wake up ImplSalYieldMutexAcquireWithWait()
+        // If we don't call these message, the Output from the
+        // Java clients doesn't come in the right order
+        GdiFlush();
     }
 }
 
-bool SalYieldMutex::tryToAcquire()
+sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll )
 {
-    if( m_mutex.tryToAcquire() )
-    {
-        mnCount++;
-        mnThreadId = GetCurrentThreadId();
-        return true;
-    }
-    else
-        return false;
-}
+    sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll );
 
-sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
-{
-    if ( nThreadId == mnThreadId )
-        return mnCount;
-    else
-        return 0;
+    // wake up ImplSalYieldMutexAcquireWithWait() after release
+    if ( 0 == m_nCount )
+        m_condition.set();
+
+    return nCount;
 }
 
 /// note: while VCL is fully up and running (other threads started and
@@ -188,6 +149,7 @@ void ImplSalYieldMutexAcquireWithWait( sal_uLong nCount )
     if ( !pInst )
         return;
 
+    SalYieldMutex * const pYieldMutex = pInst->mpSalYieldMutex;
     if ( pInst->IsMainThread() )
     {
         // tdf#96887 If this is the main thread, then we must wait for two things:
@@ -197,26 +159,23 @@ void ImplSalYieldMutexAcquireWithWait( sal_uLong nCount )
         // needed because if we don't reschedule, then we create deadlocks if a
         // Window's create/destroy is called via SendMessage() from another thread.
         // Have a look at the osl_waitCondition implementation for more info.
-        SalYieldMutex * const pYieldMutex = pInst->mpSalYieldMutex;
         osl::Condition &rCondition = pYieldMutex->m_condition;
-        while ( nCount )
-        {
-            do {
-                // reset condition *before* acquiring!
-                rCondition.reset();
-                if (pYieldMutex->tryToAcquire())
-                    break;
-                // wait for SalYieldMutex::release() to set the condition
-                osl::Condition::Result res = rCondition.wait();
-                assert(osl::Condition::Result::result_ok == res);
-            }
-            while ( true );
-            --nCount;
+
+        do {
+            // reset condition *before* acquiring!
+            rCondition.reset();
+            if (pYieldMutex->tryToAcquire())
+                break;
+            // wait for SalYieldMutex::release() to set the condition
+            osl::Condition::Result res = rCondition.wait();
+            assert(osl::Condition::Result::result_ok == res);
         }
+        while ( true );
+        --nCount;
     }
-    else
-        // If this is not the main thread, call acquire directly.
-        ImplSalAcquireYieldMutex( nCount );
+
+    if ( nCount )
+        pYieldMutex->acquire( nCount );
 }
 
 bool ImplSalYieldMutexTryToAcquire()
@@ -238,47 +197,10 @@ void ImplSalYieldMutexRelease()
     }
 }
 
-sal_uLong ImplSalReleaseYieldMutex()
+bool SalYieldMutex::IsCurrentThread() const
 {
-    WinSalInstance* pInst = GetSalData()->mpFirstInstance;
-    if ( !pInst )
-        return 0;
-
-    SalYieldMutex*  pYieldMutex = pInst->mpSalYieldMutex;
-    const sal_uLong nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() );
-    sal_uLong       n = nCount;
-    while ( n )
-    {
-        pYieldMutex->release();
-        n--;
-    }
-
-    return nCount;
-}
-
-void ImplSalAcquireYieldMutex( sal_uLong nCount )
-{
-    WinSalInstance* pInst = GetSalData()->mpFirstInstance;
-    if ( !pInst )
-        return;
-
-    SalYieldMutex*  pYieldMutex = pInst->mpSalYieldMutex;
-    while ( nCount )
-    {
-        pYieldMutex->acquire();
-        nCount--;
-    }
-}
-
-bool WinSalInstance::CheckYieldMutex()
-{
-    SalData*    pSalData = GetSalData();
-    if ( pSalData->mpFirstInstance )
-    {
-        SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex;
-        return (pYieldMutex->mnThreadId == (GetCurrentThreadId()));
-    }
-    return true;
+    // For the Windows backend, the LO identifier is the system thread ID
+    return m_nThreadId == GetCurrentThreadId();
 }
 
 void SalData::initKeyCodeMap()
@@ -520,14 +442,12 @@ void DestroySalInstance( SalInstance* pInst )
 WinSalInstance::WinSalInstance()
 {
     mhComWnd                 = nullptr;
-    mpSalYieldMutex          = new SalYieldMutex( this );
+    mpSalYieldMutex          = new SalYieldMutex();
     mpSalYieldMutex->acquire();
-    ::comphelper::SolarMutex::setSolarMutex( mpSalYieldMutex );
 }
 
 WinSalInstance::~WinSalInstance()
 {
-    ::comphelper::SolarMutex::setSolarMutex( nullptr );
     mpSalYieldMutex->release();
     delete mpSalYieldMutex;
     DestroyWindow( mhComWnd );
@@ -538,14 +458,14 @@ comphelper::SolarMutex* WinSalInstance::GetYieldMutex()
     return mpSalYieldMutex;
 }
 
-sal_uLong WinSalInstance::ReleaseYieldMutex( bool )
+sal_uInt32 WinSalInstance::ReleaseYieldMutex( bool bUnlockAll )
 {
-    return ImplSalReleaseYieldMutex();
+    return mpSalYieldMutex->release( bUnlockAll );
 }
 
-void WinSalInstance::AcquireYieldMutex( sal_uLong nCount )
+void WinSalInstance::AcquireYieldMutex( sal_uInt32 nCount )
 {
-    ImplSalAcquireYieldMutex( nCount );
+    mpSalYieldMutex->acquire( nCount );
 }
 
 static void ImplSalDispatchMessage( MSG* pMsg )
@@ -615,8 +535,8 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong
     bool bDidWork = false;
     // NOTE: if nReleased != 0 this will be called without SolarMutex
     //       so don't do anything dangerous before releasing it here
-    sal_uLong const nCount = (nReleased != 0)
-                             ? nReleased : ImplSalReleaseYieldMutex();
+    sal_uInt32 const nCount = (nReleased != 0)
+                              ? nReleased : mpSalYieldMutex->release( true );
     if ( !IsMainThread() )
     {
         // #97739# A SendMessage call blocks until the called thread (here: the main thread)
@@ -636,7 +556,7 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong
             // the PeekMessage( ... PM_QS_POSTMESSAGE) calls!
             bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents );
 
-        ImplSalAcquireYieldMutex( nCount );
+        mpSalYieldMutex->acquire( nCount );
     }
     else
     {
diff --git a/vcl/win/gdi/salprn.cxx b/vcl/win/gdi/salprn.cxx
index 153ec5c54928..867727458a8b 100644
--- a/vcl/win/gdi/salprn.cxx
+++ b/vcl/win/gdi/salprn.cxx
@@ -387,17 +387,15 @@ static bool ImplUpdateSalJobSetup( WinSalInfoPrinter* pPrinter, ImplJobSetup* pS
         nMode |= DM_IN_PROMPT;
     }
 
-    // Release mutex, in the other case we don't get paints and so on
-    sal_uLong nMutexCount=0;
-    if ( pVisibleDlgParent )
-        nMutexCount = ImplSalReleaseYieldMutex();
-
-    BYTE* pOutDevMode = (reinterpret_cast<BYTE*>(pOutBuffer) + pOutBuffer->mnDriverOffset);
-    nRet = DocumentPropertiesW( hWnd, hPrn,
-                                pPrinterNameW,
-                                reinterpret_cast<LPDEVMODEW>(pOutDevMode), reinterpret_cast<LPDEVMODEW>(const_cast<BYTE *>(pInBuffer)), nMode );
-    if ( pVisibleDlgParent )
-        ImplSalAcquireYieldMutex( nMutexCount );
+    BYTE* pOutDevMode;
+    {
+        // Release mutex, in the other case we don't get paints and so on
+        SolarMutexReleaser aReleaser( pVisibleDlgParent );
+        pOutDevMode = (reinterpret_cast<BYTE*>(pOutBuffer) + pOutBuffer->mnDriverOffset);
+        nRet = DocumentPropertiesW( hWnd, hPrn, pPrinterNameW,
+                                    reinterpret_cast<LPDEVMODEW>(pOutDevMode),
+                                    reinterpret_cast<LPDEVMODEW>(const_cast<BYTE *>(pInBuffer)), nMode );
+    }
     ClosePrinter( hPrn );
 
     if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) )
@@ -1514,6 +1512,14 @@ bool WinSalPrinter::StartJob( const OUString* pFileName,
     return TRUE;
 }
 
+void WinSalPrinter::DoEndDoc(HDC hDC)
+{
+    CATCH_DRIVER_EX_BEGIN;
+    if( ::EndDoc( hDC ) <= 0 )
+        GetLastError();
+    CATCH_DRIVER_EX_END( "exception in EndDoc", this );
+}
+
 bool WinSalPrinter::EndJob()
 {
     HDC hDC = mhDC;
@@ -1532,13 +1538,10 @@ bool WinSalPrinter::EndJob()
         // it should be safe to release the yield mutex over the EndDoc
         // call, however the real solution is supposed to be the threading
         // framework yet to come.
-        volatile sal_uLong nAcquire = GetSalData()->mpFirstInstance->ReleaseYieldMutex();
-        CATCH_DRIVER_EX_BEGIN;
-        if( ::EndDoc( hDC ) <= 0 )
-            GetLastError();
-        CATCH_DRIVER_EX_END( "exception in EndDoc", this );
-
-        GetSalData()->mpFirstInstance->AcquireYieldMutex( nAcquire );
+        {
+            SolarMutexReleaser aReleaser;
+            DoEndJob( hDC );
+        }
         DeleteDC( hDC );
         mhDC = nullptr;
     }
commit dd0519331df0b8c56ff3e89ca17d9b8b6e840b4a
Author: Jan-Marek Glogowski <glogow at fbihome.de>
Date:   Fri Aug 18 20:14:59 2017 +0200

    loplugin:unnecessaryparen
    
    Change-Id: I4f8b76a9f924a476d04aa745837e732b10348ffa

diff --git a/basegfx/source/vector/b3dvector.cxx b/basegfx/source/vector/b3dvector.cxx
index 88fe80549643..fc20d37494b3 100644
--- a/basegfx/source/vector/b3dvector.cxx
+++ b/basegfx/source/vector/b3dvector.cxx
@@ -81,7 +81,7 @@ namespace basegfx

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list