Restructure ContextAwareProfile from a (thread-blocking) polling to a threadsafe-notification

This commit is contained in:
Heather Anderson 2020-04-22 23:16:51 -07:00
parent bfb4eaeb21
commit 61e6e8dfc9
2 changed files with 89 additions and 16 deletions

View file

@ -20,20 +20,62 @@
static const QString RESTRICTED_FLAG_PROPERTY = "RestrictFileAccess";
ContextAwareProfile::ContextAwareProfile(QQmlContext* context) :
ContextAwareProfileParent(context), _context(context) {
assert(context);
QMutex RestrictedContextMonitor::gl_monitorMapProtect;
RestrictedContextMonitor::TMonitorMap RestrictedContextMonitor::gl_monitorMap;
RestrictedContextMonitor::~RestrictedContextMonitor() {
gl_monitorMapProtect.lock();
TMonitorMap::iterator lookup = gl_monitorMap.find(context);
if (lookup != gl_monitorMap.end()) {
gl_monitorMap.erase(lookup);
}
gl_monitorMapProtect.unlock();
}
RestrictedContextMonitor::TSharedPtr RestrictedContextMonitor::getMonitor(QQmlContext* context, bool createIfMissing) {
TSharedPtr monitor;
gl_monitorMapProtect.lock();
TMonitorMap::const_iterator lookup = gl_monitorMap.find(context);
if (lookup != gl_monitorMap.end()) {
monitor = lookup->second.lock();
assert(monitor);
} else if(createIfMissing) {
monitor = std::make_shared<RestrictedContextMonitor>(context);
monitor->selfPtr = monitor;
gl_monitorMap.insert(TMonitorMap::value_type(context, monitor));
}
gl_monitorMapProtect.unlock();
return monitor;
}
ContextAwareProfile::ContextAwareProfile(QQmlContext* context) : ContextAwareProfileParent(context), _context(context) {
assert(context);
_monitor = RestrictedContextMonitor::getMonitor(context, true);
assert(_monitor);
connect(_monitor.get(), &RestrictedContextMonitor::onIsRestrictedChanged, this, &ContextAwareProfile::onIsRestrictedChanged);
if (_monitor->isUninitialized) {
_monitor->isRestricted = isRestrictedGetProperty();
_monitor->isUninitialized = false;
}
_isRestricted.store(_monitor->isRestricted ? 1 : 0);
}
void ContextAwareProfile::restrictContext(QQmlContext* context, bool restrict) {
RestrictedContextMonitor::TSharedPtr monitor = RestrictedContextMonitor::getMonitor(context, false);
context->setContextProperty(RESTRICTED_FLAG_PROPERTY, restrict);
if (monitor && monitor->isRestricted != restrict) {
monitor->isRestricted = restrict;
monitor->onIsRestrictedChanged(restrict);
}
}
bool ContextAwareProfile::isRestrictedInternal() {
bool ContextAwareProfile::isRestrictedGetProperty() {
if (QThread::currentThread() != thread()) {
bool restrictedResult = false;
BLOCKING_INVOKE_METHOD(this, "isRestrictedInternal", Q_RETURN_ARG(bool, restrictedResult));
BLOCKING_INVOKE_METHOD(this, "isRestrictedGetProperty", Q_RETURN_ARG(bool, restrictedResult));
return restrictedResult;
}
@ -47,11 +89,10 @@ bool ContextAwareProfile::isRestrictedInternal() {
return true;
}
bool ContextAwareProfile::isRestricted() {
auto now = usecTimestampNow();
if (now > _cacheExpiry) {
_cachedValue = isRestrictedInternal();
_cacheExpiry = now + MAX_CACHE_AGE;
}
return _cachedValue;
void ContextAwareProfile::onIsRestrictedChanged(bool newValue) {
_isRestricted.store(newValue ? 1 : 0);
}
bool ContextAwareProfile::isRestricted() {
return _isRestricted.load() != 0;
}

View file

@ -12,6 +12,7 @@
#define hifi_ContextAwareProfile_h
#include <QtCore/QtGlobal>
#include <QtCore/QMutex>
#if !defined(Q_OS_ANDROID)
#include <QtWebEngine/QQuickWebEngineProfile>
@ -30,12 +31,39 @@ using RequestInterceptorParent = QObject;
class QQmlContext;
class RestrictedContextMonitor : public QObject {
Q_OBJECT
public:
typedef std::shared_ptr<RestrictedContextMonitor> TSharedPtr;
typedef std::weak_ptr<RestrictedContextMonitor> TWeakPtr;
inline RestrictedContextMonitor(QQmlContext* c) : context(c) {}
~RestrictedContextMonitor();
static TSharedPtr getMonitor(QQmlContext* context, bool createIfMissing);
signals:
void onIsRestrictedChanged(bool newValue);
public:
TWeakPtr selfPtr;
QQmlContext* context{ nullptr };
bool isRestricted{ true };
bool isUninitialized{ true };
private:
typedef std::map<QQmlContext*, TWeakPtr> TMonitorMap;
static QMutex gl_monitorMapProtect;
static TMonitorMap gl_monitorMap;
};
class ContextAwareProfile : public ContextAwareProfileParent {
Q_OBJECT
public:
static void restrictContext(QQmlContext* context, bool restrict = true);
bool isRestricted();
Q_INVOKABLE bool isRestrictedInternal();
Q_INVOKABLE bool isRestrictedGetProperty();
protected:
class RequestInterceptor : public RequestInterceptorParent {
@ -48,9 +76,13 @@ protected:
ContextAwareProfile(QQmlContext* parent);
QQmlContext* _context{ nullptr };
bool _cachedValue{ false };
quint64 _cacheExpiry{ 0 };
constexpr static quint64 MAX_CACHE_AGE = MSECS_PER_SECOND;
QAtomicInt _isRestricted{ 0 };
private slots:
void onIsRestrictedChanged(bool newValue);
private:
RestrictedContextMonitor::TSharedPtr _monitor;
};
#endif // hifi_FileTypeProfile_h