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; ScriptValue result;
auto scriptManager = weakScriptManager.lock(); auto scriptManager = weakScriptManager.lock();
if (scriptManager) { if (scriptManager) {
BLOCKING_INVOKE_METHOD(scriptManager.get(), "evaluate", BLOCKING_INVOKE_METHOD(scriptManager.get(), [&scriptManager, &consoleFileName, &command, &result]() -> void {
Q_RETURN_ARG(ScriptValue, result), result = scriptManager->evaluate(command, consoleFileName);
Q_ARG(const QString&, command), });
Q_ARG(const QString&, consoleFileName));
} }
return result; return result;
}); });

View file

@ -40,6 +40,16 @@ void addBlockingForbiddenThread(const QString& name, QThread* thread) {
threadHash[thread] = name; 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( bool blockingInvokeMethod(
const char* function, const char* function,
QObject *obj, const char *member, QObject *obj, const char *member,

View file

@ -11,14 +11,21 @@
#define hifi_Shared_QtHelpers_h #define hifi_Shared_QtHelpers_h
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QLoggingCategory>
#include "../Profile.h"
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// Enable event queue debugging // Enable event queue debugging
#define DEBUG_EVENT_QUEUE #define DEBUG_EVENT_QUEUE
#endif #endif
class QLoggingCategory;
const QLoggingCategory& thread_safety();
namespace hifi { namespace qt { namespace hifi { namespace qt {
void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr); void addBlockingForbiddenThread(const QString& name, QThread* thread = nullptr);
QString isBlockingForbiddenThread(QThread* currentThread);
bool blockingInvokeMethod( bool blockingInvokeMethod(
const char* function, const char* function,
@ -49,6 +56,43 @@ bool blockingInvokeMethod(
QGenericArgument val8 = QGenericArgument(), QGenericArgument val8 = QGenericArgument(),
QGenericArgument val9 = 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 // Inspecting of the qt event queue
// requres access to private Qt datastructures // requres access to private Qt datastructures
// Querying the event queue should be done with // Querying the event queue should be done with