[Development] RFC: new moc feature

Sean Harmer sean.harmer at kdab.com
Sat Dec 5 13:00:44 CET 2015


Hi Olivier,

On 05/12/2015 10:22, Olivier Goffart wrote:
> On Saturday 5. December 2015 09:30:33 Sean Harmer wrote:
>> Hi devs,
>>
>> I'd like to get some feedback on a new feature for moc before we take it
>> any further than mild musing. The context is Qt3D has some frontend
>> QObject subclass types, and corresponding backend, non-QObject subclass
>> types for reasons of allowing us to process data on the backend without
>> blocking the main thread or locking it.
>>
>> To get the property values from the frontend objects to the backend we
>> wrap the data up in QScenePropertyChange and in the backend object we
>> unpack the data and handle it with code something like this:
>>
>>       if (e->type() == NodeUpdated) {
>>           const QScenePropertyChangePtr &propertyChange =
>> qSharedPointerCast<QScenePropertyChange>(e);
>>           if (propertyChange->propertyName() ==
>> QByteArrayLiteral("scale3D")) {
>>               m_scale = propertyChange->value().value<QVector3D>();
>>               updateMatrix();
>>           } else if (propertyChange->propertyName() ==
>> QByteArrayLiteral("rotation")) {
>>               m_rotation = propertyChange->value().value<QQuaternion>();
>>               updateMatrix();
>>           } else if (propertyChange->propertyName() ==
>> QByteArrayLiteral("translation")) {
>>               m_translation = propertyChange->value().value<QVector3D>();
>>               updateMatrix();
>>           } else if (propertyChange->propertyName() ==
>> QByteArrayLiteral("enabled")) {
>>               m_enabled = propertyChange->value().toBool();
>>           }
>>       }
>>
>> Not too bad in this case but those cascaded if-else if blocks are not
>> good when the number of properties is large.
> Why not?  Readability or performence?

Both but performance is the main driver as potentially we have a large 
number of string comparisons.

>
>> This is where the proposed new feature of moc would come in. If moc were
>> able to generate an enum where each enum value corresponds to a static
>> property we would be able to use a switch in the above code.
>>
>> Is such a feature feasible? Are there reasons why it couldn't work?
> I'm afraid this is not feasable. This enum would need to be in the header, and
> the moc generated code is not a header.

Ah yes of course. Silly me.

> Instead, I would suggest something similar to llvm::StringSwitch
> http://code.woboq.org/llvm/llvm/include/llvm/ADT/StringSwitch.h.html

Right, thanks. I've also been considering compile time hashing of the 
strings via constexpr implementation of some hashing algorithm but from 
reading around it seems MSVC2012 won't be up to the job for this approach.

So at present that leaves a build time preprocess tool that goes over 
the sources and replaces marked up strings with their hashed values. 
Plus side is that the work is done at build time leaving just an integer 
comparison at run time. Down side is getting access to the original 
strings during debugging/runtime. This could be overcome by having the 
debugger/runtime load up the mapping of hashed values to original strings.

So given the above example we'd be able to have something like this 
(name of macro pending):

     if (e->type() == NodeUpdated) {
         const QScenePropertyChangePtr &propertyChange = 
qSharedPointerCast<QScenePropertyChange>(e);
         switch (propertyChange->propertyNameStringId()) {
         case qStrId("scale3D"):
             m_scale = propertyChange->value().value<QVector3D>();
             updateMatrix();
             break;
         case qStrId("rotation"):
             m_rotation = propertyChange->value().value<QQuaternion>();
             updateMatrix();
             break;
         case qStrId("translation"):
             m_translation = propertyChange->value().value<QVector3D>();
             updateMatrix();
             break;
         case qStrId("enabled"):
             m_enabled = propertyChange->value().toBool();
             break;
          default:
             qWarning() << "Unknown property update";
         }
     }

Where the qStrId macro expands to nothing and the preprocess tool 
replaces its contents with the hashed value. No idea if all of our 
supported compilers allow hooking in custom preprocessors or not.

Yes, I know in this particular case, the wrapping/unwrapping of the 
property values in QVariants is likely the bottleneck but we can solve 
that with specialised property change types.

Cheers,

Sean

-- 
Dr Sean Harmer | sean.harmer at kdab.com | Managing Director UK
KDAB (UK) Ltd, a KDAB Group company
Tel. +44 (0)1625 809908; Sweden (HQ) +46-563-540090
Mobile: +44 (0)7545 140604
KDAB - Qt Experts




More information about the Development mailing list