/* -*- 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 .
*/
#pragma once
/**
* 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>
#include <tools/debug.hxx>
union RuninmainResult
{
void * pointer;
bool boolean;
struct SalFrame::SalPointerState state;
RuninmainResult() {}
};
#define OSX_RUNINMAIN_MEMBERS \
std::mutex m_runInMainMutex; \
std::condition_variable m_aInMainCondition; \
std::condition_variable m_aResultCondition; \
bool m_wakeUpMain = false ; \
bool m_resultReady = false ; \
RuninmainBlock m_aCodeBlock; \
RuninmainResult m_aResult;
#define OSX_RUNINMAIN( instance, command ) \
if ( !instance->IsMainThread() ) \
{ \
DBG_TESTSOLARMUTEX(); \
SalYieldMutex *aMutex = static_cast <SalYieldMutex*>(instance->GetYieldMutex()); \
{ \
std::scoped_lock<std::mutex> g(aMutex->m_runInMainMutex); \
assert( !aMutex->m_aCodeBlock ); \
aMutex->m_aCodeBlock = Block_copy(^{ \
command; \
}); \
aMutex->m_wakeUpMain = true ; \
aMutex->m_aInMainCondition.notify_all(); \
} \
dispatch_async(dispatch_get_main_queue(),^{ \
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
}); \
{ \
std::unique_lock<std::mutex> g(aMutex->m_runInMainMutex); \
aMutex->m_aResultCondition.wait( \
g, [&aMutex]() { return aMutex->m_resultReady; }); \
aMutex->m_resultReady = false ; \
} \
return ; \
}
#define OSX_RUNINMAIN_POINTER( instance, command, type ) \
if ( !instance->IsMainThread() ) \
{ \
DBG_TESTSOLARMUTEX(); \
SalYieldMutex *aMutex = static_cast <SalYieldMutex*>(instance->GetYieldMutex()); \
{ \
std::scoped_lock<std::mutex> g(aMutex->m_runInMainMutex); \
assert( !aMutex->m_aCodeBlock ); \
aMutex->m_aCodeBlock = Block_copy(^{ \
aMutex->m_aResult.pointer = static_cast <void *>( command ); \
}); \
aMutex->m_wakeUpMain = true ; \
aMutex->m_aInMainCondition.notify_all(); \
} \
dispatch_async(dispatch_get_main_queue(),^{ \
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
}); \
{ \
std::unique_lock<std::mutex> g(aMutex->m_runInMainMutex); \
aMutex->m_aResultCondition.wait( \
g, [&aMutex]() { return aMutex->m_resultReady; }); \
aMutex->m_resultReady = false ; \
} \
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()); \
{ \
std::scoped_lock<std::mutex> g(aMutex->m_runInMainMutex); \
assert( !aMutex->m_aCodeBlock ); \
aMutex->m_aCodeBlock = Block_copy(^{ \
aMutex->m_aResult.member = command; \
}); \
aMutex->m_wakeUpMain = true ; \
aMutex->m_aInMainCondition.notify_all(); \
} \
dispatch_async(dispatch_get_main_queue(),^{ \
ImplNSAppPostEvent( AquaSalInstance::YieldWakeupEvent, NO ); \
}); \
{ \
std::unique_lock<std::mutex> g(aMutex->m_runInMainMutex); \
aMutex->m_aResultCondition.wait( \
g, [&aMutex]() { return aMutex->m_resultReady; }); \
aMutex->m_resultReady = false ; \
} \
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()->mpInstance, command )
#define OSX_SALDATA_RUNINMAIN_POINTER( command, type ) \
OSX_RUNINMAIN_POINTER( GetSalData()->mpInstance, command, type )
#define OSX_SALDATA_RUNINMAIN_UNION( command, member ) \
OSX_RUNINMAIN_UNION( GetSalData()->mpInstance, command, member )
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=92 H=100 G=95
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-11)
¤
*© Formatika GbR, Deutschland