Introduce protobuf-unsafe-registry feature

The feature guards the private code paths that enable or disable
the safe registering of the custom protobuf serializers.
The feature is useful when user want to trade the thread safety for
performance.

From the code perspective feature disables read/write locks when
accessing custom protobuf serializers registered privately.

Change-Id: I07cb622481a798e7aeba9c7afb29593e791e065e
Reviewed-by: Dennis Oberst <dennis.oberst@qt.io>
This commit is contained in:
Alexey Edelev 2025-01-14 18:39:32 +01:00
parent c7b78a5cbd
commit 7986e077c1
3 changed files with 31 additions and 2 deletions

View File

@ -87,11 +87,20 @@ qt_feature("protobufquick" PUBLIC
AUTODETECT TRUE
CONDITION TARGET Qt6::Quick
)
qt_feature("protobuf-unsafe-registry" PRIVATE
SECTION "Qt Protobuf"
LABEL "Unsafe registry"
PURPOSE "Allows lock-free registry access for custom serializers"
AUTODETECT FALSE
)
qt_configure_add_summary_section(NAME "Qt Protobuf")
qt_configure_add_summary_entry(ARGS "protobuf-qtcoretypes")
qt_configure_add_summary_entry(ARGS "protobuf-qtguitypes")
qt_configure_add_summary_entry(ARGS "protobuf-wellknowntypes")
qt_configure_add_summary_entry(ARGS "protobufquick")
qt_configure_add_summary_entry(ARGS "protobuf-unsafe-registry")
qt_configure_end_summary_section()
qt_configure_add_summary_section(NAME "Qt Protobuf tools")
qt_configure_add_summary_entry(ARGS "qtprotobufgen")

View File

@ -3,6 +3,7 @@
#include <QtProtobuf/qprotobufjsonserializer.h>
#include <QtProtobuf/private/qtprotobuf-config_p.h>
#include <QtProtobuf/private/protobuffieldpresencechecker_p.h>
#include <QtProtobuf/private/protobufscalarjsonserializers_p.h>
#include <QtProtobuf/private/qprotobufdeserializerbase_p.h>
@ -18,7 +19,9 @@
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qreadwritelock.h>
#if !QT_CONFIG(protobuf_unsafe_registry)
# include <QtCore/qreadwritelock.h>
#endif
#include <QtCore/qtimezone.h>
#include <QtCore/qvariant.h>
@ -52,13 +55,17 @@ struct JsonHandlerRegistry
void registerHandler(QMetaType metaType, QtProtobufPrivate::CustomJsonSerializer serializer,
QtProtobufPrivate::CustomJsonDeserializer deserializer)
{
#if !QT_CONFIG(protobuf_unsafe_registry)
QWriteLocker locker(&m_lock);
#endif
m_registry[metaType] = { serializer, deserializer };
}
QtProtobufPrivate::CustomJsonSerializer findSerializer(QMetaType metaType)
{
#if !QT_CONFIG(protobuf_unsafe_registry)
QReadLocker locker(&m_lock);
#endif
const auto it = m_registry.constFind(metaType);
if (it != m_registry.constEnd())
return it.value().first;
@ -67,7 +74,9 @@ struct JsonHandlerRegistry
QtProtobufPrivate::CustomJsonDeserializer findDeserializer(QMetaType metaType)
{
#if !QT_CONFIG(protobuf_unsafe_registry)
QReadLocker locker(&m_lock);
#endif
const auto it = m_registry.constFind(metaType);
if (it != m_registry.constEnd())
return it.value().second;
@ -77,7 +86,9 @@ struct JsonHandlerRegistry
private:
using Handler = std::pair<QtProtobufPrivate::CustomJsonSerializer,
QtProtobufPrivate::CustomJsonDeserializer>;
#if !QT_CONFIG(protobuf_unsafe_registry)
QReadWriteLock m_lock;
#endif
QHash<QMetaType, Handler> m_registry;
};
Q_GLOBAL_STATIC(JsonHandlerRegistry, jsonHandlersRegistry)

View File

@ -3,12 +3,15 @@
#include <QtProtobuf/qprotobufregistration.h>
#include <QtProtobuf/private/qtprotobuf-config_p.h>
#include <QtProtobuf/private/qprotobufregistration_p.h>
#include <QtProtobuf/qtprotobuftypes.h>
#include <QtCore/qmutex.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qreadwritelock.h>
#if !QT_CONFIG(protobuf_unsafe_registry)
# include <QtCore/qreadwritelock.h>
#endif
#include <mutex>
@ -122,13 +125,17 @@ struct HandlersRegistry
void registerHandler(QMetaType type, QtProtobufPrivate::Serializer serializer,
QtProtobufPrivate::Deserializer deserializer)
{
#if !QT_CONFIG(protobuf_unsafe_registry)
QWriteLocker locker(&m_lock);
#endif
m_registry[type] = { serializer, deserializer };
}
QtProtobufPrivate::SerializationHandler findHandler(QMetaType type)
{
#if !QT_CONFIG(protobuf_unsafe_registry)
QReadLocker locker(&m_lock);
#endif
auto it = m_registry.constFind(type);
if (it != m_registry.constEnd())
return it.value();
@ -136,7 +143,9 @@ struct HandlersRegistry
}
private:
# if !QT_CONFIG(protobuf_unsafe_registry)
QReadWriteLock m_lock;
# endif
QHash<QMetaType, QtProtobufPrivate::SerializationHandler> m_registry;
};
Q_GLOBAL_STATIC(HandlersRegistry, handlersRegistry)