remove requirement that ScriptManager::evaluate be meta-invokable

This commit is contained in:
Heather Anderson 2022-03-21 00:24:27 -07:00 committed by ksuprynowicz
parent 67260b92bd
commit 306f3d07c9
3 changed files with 57 additions and 4 deletions

View file

@ -355,10 +355,9 @@ void JSConsole::executeCommand(const QString& command) {
ScriptValue result;
auto scriptManager = weakScriptManager.lock();
if (scriptManager) {
BLOCKING_INVOKE_METHOD(scriptManager.get(), "evaluate",
Q_RETURN_ARG(ScriptValue, result),
Q_ARG(const QString&, command),
Q_ARG(const QString&, consoleFileName));
BLOCKING_INVOKE_METHOD(scriptManager.get(), [&scriptManager, &consoleFileName, &command, &result]() -> void {
result = scriptManager->evaluate(command, consoleFileName);
});
}
return result;
});

View file

@ -40,6 +40,16 @@ void addBlockingForbiddenThread(const QString& name, QThread* thread) {
threadHash[thread] = name;
}
QString isBlockingForbiddenThread(QThread* currentThread) {
QReadLocker locker(&threadHashLock);
for (const auto& thread : threadHash.keys()) {
if (currentThread == thread) {
return threadHash[thread];
}
}
return QString();
}
bool blockingInvokeMethod(
const char* function,
QObject *obj, const char *member,

View file

@ -11,14 +11,21 @@
#define hifi_Shared_QtHelpers_h
#include <QtCore/QObject>
#include <QtCore/QLoggingCategory>
#include "../Profile.h"
#if defined(Q_OS_WIN)
// Enable event queue debugging
#define DEBUG_EVENT_QUEUE
#endif
class QLoggingCategory;
const QLoggingCategory& thread_safety();
namespace hifi { namespace qt {
void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr);
QString isBlockingForbiddenThread(QThread* currentThread);
bool blockingInvokeMethod(
const char* function,
@ -49,6 +56,43 @@ bool blockingInvokeMethod(
QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = QGenericArgument());
// handling unregistered functions
template <typename Func, typename ReturnType>
typename std::enable_if<!std::is_convertible<Func, const char*>::value, bool>::type
blockingInvokeMethod(const char* callingFunction, QObject* context, Func function, ReturnType* retVal) {
auto currentThread = QThread::currentThread();
if (currentThread == qApp->thread()) {
qCWarning(thread_safety) << "BlockingQueuedConnection invoked on main thread from " << callingFunction;
return QMetaObject::invokeMethod(context, function, Qt::BlockingQueuedConnection, retVal);
}
QString forbiddenThread = isBlockingForbiddenThread(currentThread);
if (!forbiddenThread.isEmpty()) {
qCWarning(thread_safety) << "BlockingQueuedConnection invoked on forbidden thread " << forbiddenThread;
}
PROFILE_RANGE(app, callingFunction);
return QMetaObject::invokeMethod(context, function, Qt::BlockingQueuedConnection, retVal);
}
template <typename Func>
typename std::enable_if<!std::is_convertible<Func, const char*>::value, bool>::type
blockingInvokeMethod(const char* callingFunction, QObject* context, Func function) {
auto currentThread = QThread::currentThread();
if (currentThread == qApp->thread()) {
qCWarning(thread_safety) << "BlockingQueuedConnection invoked on main thread from " << callingFunction;
return QMetaObject::invokeMethod(context, function, Qt::BlockingQueuedConnection);
}
QString forbiddenThread = isBlockingForbiddenThread(currentThread);
if (!forbiddenThread.isEmpty()) {
qCWarning(thread_safety) << "BlockingQueuedConnection invoked on forbidden thread " << forbiddenThread;
}
PROFILE_RANGE(app, callingFunction);
return QMetaObject::invokeMethod(context, function, Qt::BlockingQueuedConnection);
}
// Inspecting of the qt event queue
// requres access to private Qt datastructures
// Querying the event queue should be done with