<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0"><channel><title>Woboq</title><description>Woboq does Qt consulting and services</description><link>https://woboq.com</link>

<item><title>Integrating QML and Rust: Creating a QMetaObject at Compile Time</title><link>https://woboq.com/blog/qmetaobject-from-rust.html</link><guid>http://woboq.com/blog/qmetaobject-from-rust.html</guid><pubDate>Thu, 07 Jun 2018 15:12:51 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>In this blog post, I would like to present a research project I have been working on: Trying to
use QML from Rust, and in general, using a C++ library from Rust.</p>
    <p>The project is a <span title="A crate in rust is a compilation unit, it is compiled into a library or a binary">Rust crate</span> which allows to create QMetaObject at compile time from pure
Rust code. It is available here: <a href="https://github.com/woboq/qmetaobject-rs">https://github.com/woboq/qmetaobject-rs</a>
    </p>
</div>
<h2>Qt and Rust</h2>
<p>There were already numerous existing projects that attempt to integrate Qt and Rust.
A great GUI toolkit should be working with a great language.</p>
<p>As far back as 2014, the project <em>cxx2rust</em> tried to generate automatic
bindings to C++, and in particular to Qt5.
<a href="https://endl.ch/content/cxx2rust-pains-wrapping-c-rust-example-qt5">
The blog post explain all the problems.</a>
Another project that automatically generate C++ bindings for Qt is
<a href="https://github.com/rust-qt/cpp_to_rust">cpp_to_rust</a>.
I would not pursue this way of automatically create bindings because it cannot produce a binding that can be used from idiomatic Rust code, without using <code>unsafe</code>.</p>
<p>There is also <a href="https://crates.io/crates/qmlrs">qmlrs</a>. The idea here is to
develop manually a small wrapper C++ library that exposes <code>extern "C"</code> functions.
Then a Rust crate with a good and safe API can internally call these wrappers.
<br/>
Similarly, the project <a href="https://github.com/White-Oak/qml-rust">qml-rust</a> does approximately
the same, but uses the <a href="https://github.com/filcuc/DOtherSide">DOtherSide bindings</a> as
the Qt wrapper library. The same used for D and Nim bindings for QML.<br/>
These two projects only concentrate on QML and not QtWidget nor the whole of Qt.
Since the API is then much smaller, this simplifies a lot the fastidious work of
creating the bindings manually.
Both these projects generate a QMetaObject at runtime from information given by rust macros.
Also you cannot use any type as parameter for your property or method arguments. You are limited
to convert to built-in types.
</p>
<p>Finally, there is Jos van den Oever's
<a href="https://phabricator.kde.org/source/rust-qt-binding-generator/">Rust Qt Binding Generator</a>.
To use this project, one has to write a JSON description of the interface one wants to expose,
then the generator will generate the rust and C++ glue code so that you can easily call rust from
your Qt C++/Qml application.<br/>
What I think is a problem is that you are still expected to write some C++
and add an additional step in your build system.
That is perfectly fine if you want to add Rust to an existing C++ project, but not if you just
want a GUI for a Rust application.
Also writing this JSON description is a bit alien.
</p>
<p>I started the <em>qmetaobject</em> crate mainly because I wanted to create the
QMetaObject at rust compile time.
The QMetaObject is a data structure which contains all the information about a
class deriving from QObject (or <code>Q_GADGET</code>) so the Qt runtime can connect signals with
slots, or read and write properties. Normally, the QMetaObject is built at compile time from a
C++ file generated by <code>moc</code>, Qt's meta object compiler.<br/>
I'm a fan of creating QMetaObject: I am contributing to Qt, and I also wrote
<a href="https://woboq.com/blog/moc-with-clang.html">moc-ng</a> and <a href="https://woboq.com/blog/verdigris-qt-without-moc.html">Verdigris</a> which are all about creating QMetaObject.
Verdigris uses the power of C++ constexpr to create the QMetaObject at compile time, and I wanted
to try using Rust to see if it could also be done at compile time.</p>
<h2>The <code>qmetaobject</code> crate</h2>
<p>The crate uses a custom derive macro to generate the QMetaObject.
Custom derive works by adding an annotation in front of a rust struct such as
<code>#[derive(QObject)]</code> or <code>#[derive(QGadget)]</code>.
Upon seeing this annotation, the rustc compiler will call the function from the qmetaobject_impl crate
which implements the custom derive. The function has the signature
<code>fn(input : TokenStream) -&gt; TokenStream</code>. It will be called at compile time, and takes
as input the source code of the struct it derives and should generate more source code
that will then be compiled. <br/>
What we do in this custom derive macro is first to parse the content of the struct and find about
some annotations. I've used a set of macros such as <code>qt_property!</code>, <code>qt_method!</code>
and so on, similar to Qt's C++ macros. I could also have used custom attributes but I chose macros
as it seemed more natural coming from the Qt world (but perhaps this should be revised).
</p>
<p>Let's simply go over a dummy example of using the crate.</p>
<pre class="brush: rust">
extern crate qmetaobject;
use qmetaobject::*; // For simplicity

// Deriving from QObject will automatically implement the QObject trait and
// generates QMetaObject through the custom derive macro.
// This is equivalent to add the Q_OBJECT in Qt code.
#[derive(QObject,Default)]
struct Greeter {
  // We need to specify a C++ base class. This is done by specifying a
  // QObject-like trait. Here we can specify other QObject-like traits such
  // as QAbstractListModel or QQmlExtensionPlugin.
  // The 'base' field is in fact a pointer to the C++ QObject.
  base : qt_base_class!(trait QObject),
  // We declare the 'name' property using the qt_property! macro.
  name : qt_property!(QString; NOTIFY name_changed),
  // We declare a signal. The custom derive will automatically create
  // a function of the same name that can be called to emit it.
  name_changed : qt_signal!(),
  // We can also declare invokable methods.
  compute_greetings : qt_method!(fn compute_greetings(&amp;self, verb : String) -&gt; QString {
      return (verb + " " + &amp;self.name.to_string()).into()
  })
}

fn main() {
  // We then use qml_register_type as an equivalent to qmlRegisterType
  qml_register_type::&lt;Greeter&gt;(cstr!("Greeter"), 1, 0, cstr!("Greeter"));
  let mut engine = QmlEngine::new();
  engine.load_data(r#"
    import QtQuick 2.6; import QtQuick.Window 2.0; import Greeter 1.0;
    Window {
      visible: true;
      // We can instantiate our rust object here.
      Greeter { id: greeter; name: 'World'; }
      // and use it by accessing its property or method.
      Text { text: greeter.compute_greetings('hello'); }
    }"#.into());
  engine.exec();
}
</pre>
<p>In this example, we used <code>qml_register_type</code> to register the type to QML, but we
can also also set properties on the global context. An example with this model, which also demonstrate
QGadget</p>
<pre class="brush: rust">
// derive(QGadget) is the equivalent of Q_GADGET.
#[derive(QGadget,Clone,Default)]
struct Point {
  x: qt_property!(i32),
  y: qt_property!(i32),
}

#[derive(QObject, Default)]
struct Model {
  // Here the C++ class will derive from QAbstractListModel
  base: qt_base_class!(trait QAbstractListModel),
  data: Vec&lt;Point&gt;
}

// But we still need to implement the QAbstractListModel manually
impl QAbstractListModel for Model {
  fn row_count(&amp;self) -&gt; i32 {
    self.data.len() as i32
  }
  fn data(&amp;self, index: QModelIndex, role:i32) -&gt; QVariant {
    if role != USER_ROLE { return QVariant::default(); }
    // We use the QGadget::to_qvariant function
    self.data.get(index.row() as usize).map(|x|x.to_qvariant()).unwrap_or_default()
  }
  fn role_names(&amp;self) -&gt; std::collections::HashMap&lt;i32, QByteArray&gt; {
    vec![(USER_ROLE, QByteArray::from("value"))].into_iter().collect()
  }
}

fn main() {
  let mut model = Model { data: vec![ Point{x:1,y:2} , Point{x:3, y:4} ], ..Default::default() };
  let mut engine = QmlEngine::new();
  // Registers _model as a context property.
  engine.set_object_property("_model".into(), &amp;mut model);
  engine.load_data(r#"
    import QtQuick 2.6; import QtQuick.Window 2.0;
    Window {
      visible: true;
      ListView {
        anchors.fill: parent;
        model: _model;  // We reference our Model object
        // And we can access the property or method of our gadget
        delegate: Text{ text: value.x + ','+value.y; } }
    }"#.into());
  engine.exec();
</pre>
<p>Other implemented features include the creation of Qt plugins such as <a href="http://doc.qt.io/qt-5/qqmlextensionplugin.html">QQmlExtensionPlugin</a> without
writing a line of C++, only using rust and cargo. (See the <a href="https://github.com/woboq/qmetaobject-rs/tree/master/examples/qmlextensionplugins">qmlextensionplugins example</a>.)</p>
<h2>QMetaObject generation</h2>
<p>The QMetaObject consists in a bunch of tables in the data section of the binary:
a table of string and a table of integer. And there is also a function pointer with code used
to read/write the properties or call the methods.</p>
<p>The custom derive macro will generate the tables as <code>&amp;'static[u8]</code>.
The moc generated code contains <code>QByteArrayData</code>, built in C++, but since
we don't want to use a C++ compiler to generate the QMetaObject, we have to layout all the
bytes of the <code>QByteArrayData</code> one by one. Another tricky part is the creation
of the Qt binary JSON for the plugin metadata. The Qt binary JSON is also an undocumented
data structure which needs to be built byte by byte, respecting many invariants such as alignment
and order of the fields.</p>
<p>The code from the static_metacall is just an <code>extern "C" fn</code>. Then we can assemble all these
pointers in a QMetaObject. We cannot create const static structure containing pointers.
This is then implemented using the <code>lazy_static!</code> macro.</p>
<h2>QObject Creation</h2>
<p>Qt needs a <code>QObject*</code> pointer for our object.
It has virtual methods to get the QMetaObject.
The same applies for QAbstractListModel or any other class we could like to inherit from, which has
many virtual methods that we wish to override.</p>
<p>We will then have to materialize an actual C++ object on the heap.
This C++ counterpart is created by some of the C++ glue code. We will store a pointer to this C++
counterpart in the field annotated with the <code>qt_base_class!</code> macro.
The glue code will instantiate a
<a href="https://github.com/ogoffart/qmetaobject-rs/blob/72baa6dc53a74bb152e53fda280bab9ba97c5406/qmetaobject/qmetaobject_rust.hpp#L34">
        <code>RustObject&lt;QObject&gt;</code>
    </a>. It is a class that inherits
from QObject (or any other QObject derivative) and overrides the virtual to forward
them to a callback in rust which will then be able to call the right function on the rust object.
</p>
<img src="https://woboq.com/blog/qmetaobject-from-rust/layout.png"/>
<p>One of the big problems is that in rust, contrary to C++, objects can be moved in memory at will.
This is a big problem, as the C++ object contains a pointer to the rust object. So the rust object
needs somehow to be fixed in memory. This can be achieved by putting it into a <code>Box</code>
or a <code>Rc</code>, but even then, it is still possible to move the object in safe code.
This problem is not entirely fixed, but the interface takes the object by value and moves it to an
immutable location. Then the object can still be accessed safely from a <code>QJSValue</code> object.
</p>
<p>Note that QGadget does not need a C++ counter-part.</p>
<h2>C++ Glue code</h2>
<p>For this project I need a bit of C++ glue code to create the C++ counter part of my object, or
to access the C++ API for Qt types or QML API.
I am using the <code>cpp!</code> macro from the <a href="https://docs.rs/cpp/*/cpp/">cpp crate</a>.
This macro allows embedding C++ code directly into rust code with very little boiler plate compared
to manually creating callbacks and declaring <code>extern "C"</code> functions.<br/>
I even <a href="https://github.com/mystor/rust-cpp/pull/28">contributed a cpp_class macro</a>
which allows wrapping C++ classes from rust.
</p>
<p>Should an API be missing, it is easy to add the missing wrapper function. Also when we want
to inherit from a class, we just need to imitate what is done for QAbstractListView, that is
override all the virtual functions we want to override, and forward them to the function
from the trait.</p>
<h2>Final Words</h2>
<p>My main goal with this crate was to try to see if we can integrate QML with idiomatic
and safe Rust code. Without requiring to use of C++ or any other alien tool for the developer.
I also had performance in mind and wanted to create the QMetaObject at compile time and
limit the amount of conversions or heap allocations.<br/>

Although there are still some problems to solve, and that the exposed API is far from complete,
this is already a beginning.
</p>
<p>
You can get the metaobject crate at this URL: <a href="https://github.com/woboq/qmetaobject-rs">https://github.com/woboq/qmetaobject-rs</a>
</p>
]]></description></item>
<item><title>Two C++ tricks used in Verdigris implementation</title><link>https://woboq.com/blog/verdigris-implementation-tricks.html</link><guid>http://woboq.com/blog/verdigris-implementation-tricks.html</guid><pubDate>Thu, 15 Feb 2018 06:41:45 GMT</pubDate><description><![CDATA[

<img alt="A verdigris statue" src="https://woboq.com/blog/verdigris-qt-without-moc/verdigris-brandenburgertor.jpeg" style="float:right; margin-left:1ex; width:30%"/>

<div class="intro">
<p>I have just tagged the version 1.0 <a href="https://github.com/woboq/verdigris">Verdigris</a>.
I am taking this opportunity to write an article about two C++ tricks used in its implementation.
</p></div>
<p>
Verdigris is a header-only C++ library which lets one use Qt without the need of moc. I've written an
<a href="https://woboq.com/blog/verdigris-qt-without-moc.html">introductory blog post</a> about it two years
ago and have since then <a href="https://github.com/woboq/verdigris/issues?q=is%3Aclosed">
 received several contributions on GitHub</a> that extend the software.
</p>

<h2>Optionally Removing Parentheses in a Macro</h2>

<p>This trick is used in the <code>W_PROPERTY</code> and the <code>W_OBJECT_IMPL</code> macro.
The first argument of <code>W_PROPERTY</code> is
a type. Typically: <code>W_PROPERTY(QString, myProperty MEMBER m_myProperty)</code>.
 <br/>But what happens when the type
contains one or several commas, as in: <code>W_PROPERTY(QMap&lt;QString, int&gt;, myProperty MEMBER m_myProperty)</code>?
 That's not valid, macro expansion does not consider template and therefore the first argument would be up to
the first comma. The solution is to put the type name in parentheses. The new problem is then how can we ignore parentheses
 in the implementation
of the macro.
</p>
<p>Let's rephrase the problem with simplified macros.  Imagine we want to do a macro similar to this:</p>

<pre class="code"><i>// Naive implementation of a macro that declares a getter function</i>
<u>#define <dfn class="macro" id="_M/DECLARE_GETTER" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</dfn>(TYPE, NAME) TYPE get_##NAME()</u>

<i>// Can be used like this</i>
<span class="macro" title="QString get_property1()" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</span>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/tools/qstring.h.html#QString" title='QString' data-ref="QString" data-proj="qtbase" ">QString</a>, property1);   <i>// line A</i>
<i  data-doc="ex1::DECLARE_GETTER">// OK: expands to "QString get_property1()"</i>
<i  data-doc="ex1::DECLARE_GETTER"></i>
<i  data-doc="ex1::DECLARE_GETTER">// But this does not work:</i>
<span class='error' title="C++ requires a type specifier for all declarations"><dfn class="tu decl def" id="ex1::DECLARE_GETTER" title='ex1::DECLARE_GETTER' data-type='int' data-ref="ex1::DECLARE_GETTER">DECLARE_GETTER</dfn></span>(QMap&lt;QString, <em>int</em>&gt;, <span class='error' title="too many arguments provided to function-like macro invocation">property2</span>);
<i>// ERROR: 3 arguments passed to the macro, but only 2 expected</i>
<i></i>
<i>// And this</i>
<span class="macro" title="(QMap&lt;QString, int&gt;) get_property3()" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</span>((<span class='error' title="C++ requires a type specifier for all declarations"><span class='error' title="template specialization requires &apos;template&lt;&gt;&apos;"><span class='error' title="no variable template matches specialization">QMap</span></span></span>&lt;QString, <em>int</em>&gt;), property3);  <i>// line B</i>
<i>// ERROR: expands to "(QMap&lt;QString, int&gt;) get_property3()"</i>
<i>// Can we get rid of the parenthesis?</i>
</pre>

<p>The question is: <b>How can we implement DECLARE_GETTER so both line A and line B produce the expected result?</b>
Can we get the macro to remove the parentheses.
</p>

<p>Let's make a first attempt:</p>

<pre class="code"><i>// REMOVE_PAREN will be our macro that removes the parenthesis</i>
<u>#define <dfn class="macro" id="_M/DECLARE_GETTER" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</dfn>(TYPE, NAME) REMOVE_PAREN(TYPE) get_##NAME()</u>

<i>// Forward to REMOVE_PAREN_HELPER</i>
<u>#define <dfn class="macro" id="_M/REMOVE_PAREN" data-ref="_M/REMOVE_PAREN">REMOVE_PAREN</dfn>(A) <span class='error' title="unknown type name &apos;REMOVE_PAREN_HELPER&apos;">REMOVE_PAREN_HELPER</span> A</u>
<u>#define <dfn class="macro" id="_M/REMOVE_PAREN_HELPER" data-ref="_M/REMOVE_PAREN_HELPER">REMOVE_PAREN_HELPER</dfn>(...) __VA_ARGS__</u>

<span class="macro" title="QMap&lt;QString, int&gt; get_property1()" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</span>((<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qtypeinfo.h.html#221" title='QMap' data-ref="QMap" data-proj="qtbase" ">QMap</a>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/tools/qstring.h.html#QString" title='QString' data-ref="QString" data-proj="qtbase">QString</a>, <em>int</em>&gt;), property1);
<i>// OK: expands to "QMap&lt;QString, int&gt; get_property1()"</i>
<i>// This worked because "REMOVE_PAREN_HELPER (QMap&lt;QString, int&gt;)" was expanded to "QMap&lt;QString, int&gt;"</i>

<span class="macro" title="REMOVE_PAREN_HELPER QString get_property2()" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</span>(<dfn class="tu decl def" id="ex2::QString" title='ex2::QString' data-type='int' data-ref="ex2::QString">QString</dfn>, property2);
<i>// ERROR: expands to "REMOVE_PAREN_HELPER QString get_property2()"</i>
<i>// There was no parenteses after REMOVE_PAREN_HELPER so it was not taken as a macro"</i>
</pre>

<p>We managed to remove the parentheses, but we broke the case where there are no parentheses.
Which lead to a sub-question: <b>How to remove a specific token if present?</b> In this case, how to
remove "REMOVE_PARENT_HELPER" from the expansion</p>

<pre class="code"><i>// Same as before</i>
<u>#define <dfn class="macro" id="_M/DECLARE_GETTER" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</dfn>(TYPE, NAME) REMOVE_PAREN(TYPE) get_##NAME()</u>

<i>// Macro that removes the first argument</i>
<u>#define <dfn class="macro" id="_M/TAIL" data-ref="_M/TAIL">TAIL</dfn>(A, ...) __VA_ARGS__</u>

<i>// This time, we add a "_ ," in front of the arguments</i>
<u>#define <dfn class="macro" id="_M/REMOVE_PAREN_HELPER" data-ref="_M/REMOVE_PAREN_HELPER">REMOVE_PAREN_HELPER</dfn>(...) _ , __VA_ARGS__</u>

<u>#define <dfn class="macro" id="_M/REMOVE_PAREN" data-ref="_M/REMOVE_PAREN">REMOVE_PAREN</dfn>(A) REMOVE_PAREN2(REMOVE_PAREN_HELPER A)</u>

<u>#define <dfn class="macro" id="_M/REMOVE_PAREN2" data-ref="_M/REMOVE_PAREN2">REMOVE_PAREN2</dfn>() TAIL(REMOVE_PAREN_HELPER_##__VA_ARGS__)</u>
<i>//  ##__VA_ARGS__ will "glue" the first token of its argument with "REMOVE_PAREN_HELPER_"</i>
<i>// The first token is:</i>
<i>//  -  "_" if REMOVE_PAREN_HELPER was expanded, in which case we have "REMOVE_PAREN_HELPER__"</i>
<i>//      which will be removed by the TAIL macro; or</i>
<i>//  - "REMOVE_PAREN_HELPER if it was not expanded, in chich case we now have</i>
<i>//    "REMOVE_PAREN_HELPER_REMOVE_PAREN_HELPER"</i>
<i></i>
<i>// So we define a macro so that it will be removed by the TAIL macro</i>
<u>#define <dfn class="macro" id="_M/REMOVE_PAREN_HELPER_REMOVE_PAREN_HELPER" data-ref="_M/REMOVE_PAREN_HELPER_REMOVE_PAREN_HELPER">REMOVE_PAREN_HELPER_REMOVE_PAREN_HELPER</dfn> _,</u>
</pre>


<p>The above code should give you an idea on how things should work. But it is not yet working.
We need to add a few layers of indirection so all macros arguments gets expanded</p>

<p>Here is <a href="https://code.woboq.org/woboq/verdigris/src/wobjectdefs.h.html#_M/W_MACRO_REMOVEPAREN">
 the real code from Verdigris</a>:</p>

<pre class="code"><u>#define <dfn class="macro" id="_M/W_MACRO_MSVC_EXPAND" data-ref="_M/W_MACRO_MSVC_EXPAND">W_MACRO_MSVC_EXPAND</dfn>(...) __VA_ARGS__</u>
<u>#define <dfn class="macro" id="_M/W_MACRO_DELAY" data-ref="_M/W_MACRO_DELAY">W_MACRO_DELAY</dfn>(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))</u>
<u>#define <dfn class="macro" id="_M/W_MACRO_DELAY2" data-ref="_M/W_MACRO_DELAY2">W_MACRO_DELAY2</dfn>(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))</u>
<u>#define <dfn class="macro" id="_M/W_MACRO_TAIL" data-ref="_M/W_MACRO_TAIL">W_MACRO_TAIL</dfn>(A, ...) __VA_ARGS__</u>

<u>#define <dfn class="macro" id="_M/W_MACRO_REMOVEPAREN" data-ref="_M/W_MACRO_REMOVEPAREN">W_MACRO_REMOVEPAREN</dfn>(A) W_MACRO_DELAY(W_MACRO_REMOVEPAREN2, W_MACRO_REMOVEPAREN_HELPER A)</u>
<u>#define <dfn class="macro" id="_M/W_MACRO_REMOVEPAREN2" data-ref="_M/W_MACRO_REMOVEPAREN2">W_MACRO_REMOVEPAREN2</dfn>(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_MACRO_REMOVEPAREN_HELPER_##__VA_ARGS__)</u>
<u>#define <dfn class="macro" id="_M/W_MACRO_REMOVEPAREN_HELPER" data-ref="_M/W_MACRO_REMOVEPAREN_HELPER">W_MACRO_REMOVEPAREN_HELPER</dfn>(...) _ , __VA_ARGS__</u>
<u>#define <dfn class="macro" id="_M/W_MACRO_REMOVEPAREN_HELPER_W_MACRO_REMOVEPAREN_HELPER" data-ref="_M/W_MACRO_REMOVEPAREN_HELPER_W_MACRO_REMOVEPAREN_HELPER">W_MACRO_REMOVEPAREN_HELPER_W_MACRO_REMOVEPAREN_HELPER</dfn> ,</u>

<u>#define <dfn class="macro" id="_M/DECLARE_GETTER" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</dfn>(TYPE, NAME) W_MACRO_REMOVEPAREN(TYPE) get_##NAME()</u>

<i>// And now it works as expected:</i>
<span class="macro" title="QString get_property1()" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</span>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/tools/qstring.h.html#QString" title='QString' data-ref="QString" data-proj="qtbase">QString</a>, property1);
<span class="macro" title="QMap&lt;QString, int&gt; get_property2()" data-ref="_M/DECLARE_GETTER">DECLARE_GETTER</span>((<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qtypeinfo.h.html#221" title='QMap' data-ref="QMap" data-proj="qtbase">QMap</a>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/tools/qstring.h.html#QString" title='QString' data-ref="QString" data-proj="qtbase">QString</a>, <em>int</em>&gt;), property2);
</pre>

<p>Note that the <code>W_MACRO_MSVC_EXPAND</code> is there only to work around a MSVC bug.</p>

<h2>Building a <code>constexpr</code> State in a Class from a Macro</h2>

<p>Conceptually, this is what the macro does</p>

<pre class="code"><b>class</b> <dfn class="type def" id="Ex1::Foo" title='Ex1::Foo' data-ref="Ex1::Foo">Foo</dfn> : <b>public</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#QObject" title='QObject' data-ref="QObject" data-proj="qtbase" ">QObject</a> {
   <a class="macro" href="https://code.woboq.org/woboq/verdigris/src/wobjectdefs.h.html#697" title="using W_ThisType = Foo; static constexpr auto &amp;W_UnscopedName = &quot;Foo&quot;; friend struct w_internal::FriendHelper; friend constexpr w_internal::binary::tree&lt;&gt; w_SlotState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_SignalState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_MethodState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_ConstructorState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_PropertyState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_EnumState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_ClassInfoState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } friend constexpr w_internal::binary::tree&lt;&gt; w_InterfaceState(w_internal::w_number&lt;0&gt;, W_ThisType**) { return {}; } public: struct W_MetaObjectCreatorHelper; public: using W_BaseType = std::remove_reference_t&lt;decltype( w_internal::getParentObjectHelper(&amp;W_ThisType::qt_metacast))&gt;; public: static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private: __attribute__((visibility(&quot;hidden&quot;))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); struct QPrivateSignal {};" data-ref="_M/W_OBJECT" data-proj="verdigris" ">W_OBJECT</a>(<span class="type" title='Ex1::Foo' data-ref="Ex1::Foo">Foo</span>) <i>// init the state</i>
   <em>int</em> <dfn class="tu decl fn" id="_ZN3Ex13Foo2xxEv" title='Ex1::Foo::xx' data-type='int Ex1::Foo::xx()' data-ref="_ZN3Ex13Foo2xxEv">xx</dfn>();
   <a class="macro" href="https://code.woboq.org/woboq/verdigris/src/wobjectdefs.h.html#761" title="friend constexpr auto w_MethodState(w_internal::w_number&lt;w_internal::identity_t&lt;decltype(w_MethodState( w_internal::w_number&lt;&gt;{}, static_cast&lt;W_ThisType**&gt;(nullptr)))&gt;::size+1&gt; w_counter, W_ThisType **w_this) -&gt; decltype(w_internal::binary::tree_append(w_MethodState(w_counter.prev(), w_this), w_internal::makeMetaMethodInfo( (&amp;W_ThisType::xx), &quot;xx&quot;, w_internal::makeStaticStringList(&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;), w_internal::W_EmptyFlag))) { return w_internal::binary::tree_append(w_MethodState(w_counter.prev(), w_this), w_internal::makeMetaMethodInfo( (&amp;W_ThisType::xx), &quot;xx&quot;, w_internal::makeStaticStringList(&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;), w_internal::W_EmptyFlag)); }" data-ref="_M/W_INVOKABLE" data-proj="verdigris">W_INVOKABLE</a>(<span class="tu ref fn" title='Ex1::Foo::xx' data-use='a' data-ref="_ZN3Ex13Foo2xxEv">xx</span>) <i>// add things to the state</i>
   <em>int</em> <dfn class="tu decl fn" id="_ZN3Ex13Foo2yyEv" title='Ex1::Foo::yy' data-type='int Ex1::Foo::yy()' data-ref="_ZN3Ex13Foo2yyEv">yy</dfn>();
   <a class="macro" href="https://code.woboq.org/woboq/verdigris/src/wobjectdefs.h.html#761" title="friend constexpr auto w_MethodState(w_internal::w_number&lt;w_internal::identity_t&lt;decltype(w_MethodState( w_internal::w_number&lt;&gt;{}, static_cast&lt;W_ThisType**&gt;(nullptr)))&gt;::size+1&gt; w_counter, W_ThisType **w_this) -&gt; decltype(w_internal::binary::tree_append(w_MethodState(w_counter.prev(), w_this), w_internal::makeMetaMethodInfo( (&amp;W_ThisType::yy), &quot;yy&quot;, w_internal::makeStaticStringList(&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;), w_internal::W_EmptyFlag))) { return w_internal::binary::tree_append(w_MethodState(w_counter.prev(), w_this), w_internal::makeMetaMethodInfo( (&amp;W_ThisType::yy), &quot;yy&quot;, w_internal::makeStaticStringList(&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;), w_internal::W_EmptyFlag)); }" data-ref="_M/W_INVOKABLE" data-proj="verdigris">W_INVOKABLE</a>(<span class="tu ref fn" title='Ex1::Foo::yy' data-use='a' data-ref="_ZN3Ex13Foo2yyEv">yy</span>) <i>// add more things</i>
};
<a class="macro" href="https://code.woboq.org/woboq/verdigris/src/wobjectimpl.h.html#831" title=" struct Foo::W_MetaObjectCreatorHelper { static constexpr auto objectInfo = w_internal::makeObjectInfo&lt;Foo::W_ThisType&gt;(&quot;Foo&quot;); static constexpr auto data = w_internal::generateDataArray&lt;Foo::W_ThisType&gt;(objectInfo); static constexpr auto string_data = data.first; static constexpr auto int_data = data.second; }; constexpr const QMetaObject Foo::staticMetaObject = w_internal::createMetaObject&lt;Foo::W_ThisType&gt;(); void Foo::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void** _a) { w_internal::qt_static_metacall_impl&lt;Foo&gt;(_o, _c, _id, _a); } const QMetaObject *Foo::metaObject() const { return &amp;staticMetaObject; } void *Foo::qt_metacast(const char *_clname) { return w_internal::qt_metacast_impl&lt;Foo&gt;(this, _clname); } int Foo::qt_metacall(QMetaObject::Call _c, int _id, void** _a) { return w_internal::qt_metacall_impl&lt;Foo&gt;(this, _c, _id, _a); }" data-ref="_M/W_OBJECT_IMPL" data-proj="verdigris" ">W_OBJECT_IMPL</a>(<span class="type" title='Ex1::Foo' data-ref="Ex1::Foo">Foo</span>); <i>// Do something with the state</i>
</pre>

<p>But what's the state? How do we represent it?<br/>
The idea is to have a static function (let's call it <code>w_state</code>) whose return value contains the state.
Each W_INVOKABLE macro would then expand to a new definition of that function. Of course, it needs
to take a different argument, so this just declares a new overload. We do it by having a
<code>w_number&lt;N&gt;</code> class template, which inherits from <code>w_number&lt;N-1&gt;</code>.
(This idea is basically inspired from CopperSpice's <code>cs_counter</code>, whose authors
 <a href="https://www.youtube.com/watch?v=gI6Qtn4US9E">described in a talk at CppCon 2015</a>)<br/>
<br/>
 Here is a simplified expanded version:
</p>


<pre class="code"><b>template</b>&lt;<em>int</em> N&gt; <b>struct</b> <dfn class="type def" id="w_number" title='w_number' data-ref="w_number">w_number</dfn> : <b>public</b> <span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<span class="tu ref" title='w_number::N' data-use='r' data-ref="w_number::N">N</span> - <var>1</var>&gt; {
    <em>static</em> <b>constexpr</b> <em>int</em> <dfn class="tu decl" id="w_number::value" title='w_number::value' data-type='const int' data-ref="w_number::value">value</dfn> = <span class="tu ref" title='w_number::N' data-ref="w_number::N">N</span>;
    <em>static</em> <b>constexpr</b> <span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<span class="tu member" title='w_number::N' data-use='r' data-ref="w_number::N">N</span>-<var>1</var>&gt; <dfn class="tu decl def fn" id="_ZN8w_number4prevEv" title='w_number::prev' data-type='static w_number&lt;N - 1&gt; w_number::prev()' data-ref="_ZN8w_number4prevEv">prev</dfn>() { <b>return</b> {}; }
};
<i>// Specialize for 0 to break the recursion.</i>
<b>template</b>&lt;&gt; <b>struct</b> <dfn class="type def" id="w_number" title='w_number' data-ref="w_number"><span class="type" title='w_number' data-ref="w_number">w_number</span></dfn>&lt;<var>0</var>&gt; { <em>static</em> <b>constexpr</b> <em>int</em> <dfn class="tu decl" id="w_number{0}::value" title='w_number&lt;0&gt;::value' data-type='const int' data-ref="w_number{0}::value">value</dfn> = <var>0</var>; };


<b>class</b> <dfn class="type def" id="Foo" title='Foo' data-ref="Foo">Foo</dfn> {
<b>public</b>:
    <i  data-doc="_ZN3Foo7w_stateE8w_numberILi0EE">// init the state  (expanded from W_OBJECT)</i>
    <em>static</em> <b>constexpr</b> <a class="type" href="https://code.woboq.org/qt5/include/c++/7.3.0/type_traits.html#std::tuple" title='std::tuple' data-ref="std::tuple" data-proj="include" ">tuple</a>&lt;&gt; <dfn class="tu decl def fn" id="_ZN3Foo7w_stateE8w_numberILi0EE" title='Foo::w_state' data-type='static tuple&lt;&gt; Foo::w_state(w_number&lt;0&gt; )' data-ref="_ZN3Foo7w_stateE8w_numberILi0EE">w_state</dfn>(<span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>0</var>&gt;) { <b>return</b> <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZNSt5tupleIJEEC1Ev" title='std::tuple&lt;&gt;::tuple' data-ref="_ZNSt5tupleIJEEC1Ev" data-proj="include" ">{</a>}; }

    <em>int</em> <dfn class="tu decl fn" id="_ZN3Foo2xxEv" title='Foo::xx' data-type='int Foo::xx()' data-ref="_ZN3Foo2xxEv">xx</dfn>();

    <i  data-doc="_ZN3Foo7w_stateE8w_numberILi1EE">// add &amp;Foo::xx to the state by defining w_state(w_number&lt;1&gt;)</i>
    <em>static</em> <b>constexpr</b> <em>auto</em> <dfn class="tu decl def fn" id="_ZN3Foo7w_stateE8w_numberILi1EE" title='Foo::w_state' data-type='static decltype(tuple_cat(w_state(n.prev()), make_tuple(&amp;Foo::xx))) Foo::w_state(w_number&lt;tuple_size&lt;decltype(w_state(w_number&lt;255&gt;()))&gt;::value + 1&gt; n)' data-ref="_ZN3Foo7w_stateE8w_numberILi1EE">w_state</dfn>(<span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<a class="type" href="https://code.woboq.org/qt5/include/c++/7.3.0/utility.html#std::tuple_size" title='std::tuple_size' data-ref="std::tuple_size" data-proj="include" ">tuple_size</a>&lt;
                <b>decltype</b>(<span class="tu member fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi0EE">w_state</span>(<span class="tu ref fn fake" title='w_number&lt;0&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi0EEC1EOS0_"></span><span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>255</var>&gt;<span class="tu ref fn" title='w_number&lt;255&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi255EEC1Ev">(</span>)))&gt;::<a class="ref" href="https://code.woboq.org/qt5/include/c++/7.3.0/type_traits.html#std::integral_constant::value" title='std::integral_constant::value' data-ref="std::integral_constant::value" data-proj="include">value</a> + <var>1</var>&gt; <dfn class="local col2 decl" id="2n" title='n' data-type='w_number&lt;tuple_size&lt;decltype(w_state(w_number&lt;255&gt;()))&gt;::value + 1&gt;' data-ref="2n">n</dfn>)
        -&gt; <b>decltype</b>(<a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="tu member fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi0EE">w_state</span>(<span class="local col2 ref" title='n' data-ref="2n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Foo' data-ref="Foo">Foo</span>::<span class="tu member fn" title='Foo::xx' data-use='a' data-ref="_ZN3Foo2xxEv">xx</span>)))
    { <b>return</b> <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="tu member fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi0EE">w_state</span>(<span class="local col2 ref" title='n' data-ref="2n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Foo' data-ref="Foo">Foo</span>::<span class="tu member fn" title='Foo::xx' data-use='a' data-ref="_ZN3Foo2xxEv">xx</span>)); }

    <em>int</em> <dfn class="tu decl fn" id="_ZN3Foo2yyEv" title='Foo::yy' data-type='int Foo::yy()' data-ref="_ZN3Foo2yyEv">yy</dfn>();

    <i  data-doc="_ZN3Foo7w_stateE8w_numberILi2EE">// add &amp;Foo::yy to the state by defining w_state(w_number&lt;2&gt;)</i>
    <em>static</em> <b>constexpr</b> <em>auto</em> <dfn class="tu decl def fn" id="_ZN3Foo7w_stateE8w_numberILi2EE" title='Foo::w_state' data-type='static decltype(tuple_cat(w_state(n.prev()), make_tuple(&amp;Foo::yy))) Foo::w_state(w_number&lt;tuple_size&lt;decltype(w_state(w_number&lt;255&gt;()))&gt;::value + 1&gt; n)' data-ref="_ZN3Foo7w_stateE8w_numberILi2EE">w_state</dfn>(<span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<a class="type" href="https://code.woboq.org/qt5/include/c++/7.3.0/utility.html#std::tuple_size" title='std::tuple_size' data-ref="std::tuple_size" data-proj="include">tuple_size</a>&lt;
                <b>decltype</b>(<span class="tu member fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi1EE">w_state</span>(<span class="tu ref fn fake" title='w_number&lt;1&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi1EEC1EOS0_"></span><span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>255</var>&gt;<span class="tu ref fn" title='w_number&lt;255&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi255EEC1Ev">(</span>)))&gt;::<a class="ref" href="https://code.woboq.org/qt5/include/c++/7.3.0/type_traits.html#std::integral_constant::value" title='std::integral_constant::value' data-ref="std::integral_constant::value" data-proj="include">value</a> + <var>1</var>&gt; <dfn class="local col3 decl" id="3n" title='n' data-type='w_number&lt;tuple_size&lt;decltype(w_state(w_number&lt;255&gt;()))&gt;::value + 1&gt;' data-ref="3n">n</dfn>)
        -&gt; <b>decltype</b>(<a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="tu member fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi1EE">w_state</span>(<span class="local col3 ref" title='n' data-ref="3n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Foo' data-ref="Foo">Foo</span>::<span class="tu member fn" title='Foo::yy' data-use='a' data-ref="_ZN3Foo2yyEv">yy</span>)))
    { <b>return</b> <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="tu member fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi1EE">w_state</span>(<span class="local col3 ref" title='n' data-ref="3n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Foo' data-ref="Foo">Foo</span>::<span class="tu member fn" title='Foo::yy' data-use='a' data-ref="_ZN3Foo2yyEv">yy</span>)); }
};

<i  data-doc="FooMetaObject">// Use that state</i>
<b>constexpr</b> <em>auto</em> <dfn class="tu decl def" id="FooMetaObject" title='FooMetaObject' data-type='const std::tuple&lt;int (Foo::*)(), int (Foo::*)()&gt;' data-ref="FooMetaObject">FooMetaObject</dfn> = <span class="ref fn" title='buildMetaObject' data-ref="_Z15buildMetaObjectT_">buildMetaObject</span>(<span class="type" title='Foo' data-ref="Foo">Foo</span>::<span class="tu ref fn" title='Foo::w_state' data-use='c' data-ref="_ZN3Foo7w_stateE8w_numberILi2EE">w_state</span>(<span class="tu ref fn fake" title='w_number&lt;2&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi2EEC1EOS0_"></span><span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>255</var>&gt;<span class="tu ref fn" title='w_number&lt;255&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi255EEC1Ev">(</span>)));
</pre>

<p>This is working pretty well.  At the end of this simplified example,
our state is a <code>std::tuple</code> containing
&amp;Foo::xx and &amp;Foo::yy, from which we could build the meta object.
(In the real implementation, the state is a bit more complicated and contains more
data)</p>

<p>This works because the call to <code>w_state(w_number&lt;255>()))</code> that
we use to get the size of the tuple, is referring to the previous declaration of w_state. Since our current
function is not yet defined yet, the most appropriate function is the remaining one with the
highest number. <br />
Notice that we have to repeat the same code in the decltype and after the return and we cannot
use return type deduction because we need to use that function before the class is fully defined.
</p>

<p>So far so good.  However, I've hit what I think is a compiler bug when doing that with class template
(eg, <code>Foo</code> would be <code>template&lt;typename> Foo</code>).
For this reason, instead of using static functions,
I have used friend functions in verdigris.  The principle is exactly the same. It is not well-known,
but <code>friend</code> functions can be declared inline in the class, despite still being global functions.
(I've also used that fact <a href="https://woboq.com/blog/q_enum.html"> in the implementation of Q_ENUM</a>)<br/>

One just needs to add a type which relates to the current class as an argument.
I use a pointer to a pointer to the class instead of just a pointer because I don't want potential
pointer conversion when calling it with a derived class.</p>



<pre class="code"><b>class</b> <dfn class="type def" id="Bar" title='Bar' data-ref="Bar">Bar</dfn> {
<b>public</b>:

    <i>// init the state  (expanded from W_OBJECT)</i>
    <b>friend</b> <b>constexpr</b> <a class="type" href="https://code.woboq.org/qt5/include/c++/7.3.0/type_traits.html#std::tuple" title='std::tuple' data-ref="std::tuple" data-proj="include">tuple</a>&lt;&gt; <dfn class="decl def fn" id="_Z7w_statePP3Bar8w_numberILi0EE" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi0EE">w_state</dfn>(<span class="type" title='Bar' data-ref="Bar">Bar</span> **, <span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>0</var>&gt;) { <b>return</b> <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZNSt5tupleIJEEC1Ev" title='std::tuple&lt;&gt;::tuple' data-ref="_ZNSt5tupleIJEEC1Ev" data-proj="include">{</a>}; }

    <em>int</em> <dfn class="tu decl fn" id="_ZN3Bar2xxEv" title='Bar::xx' data-type='int Bar::xx()' data-ref="_ZN3Bar2xxEv">xx</dfn>();

    <b>friend</b> <b>constexpr</b> <em>auto</em> <dfn class="decl def fn" id="_Z7w_statePP3Bar8w_numberILi1EE" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi1EE">w_state</dfn>(<span class="type" title='Bar' data-ref="Bar">Bar</span> **<dfn class="local col4 decl" id="4t" title='t' data-type='Bar **' data-ref="4t">t</dfn>, <span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<a class="type" href="https://code.woboq.org/qt5/include/c++/7.3.0/utility.html#std::tuple_size" title='std::tuple_size' data-ref="std::tuple_size" data-proj="include">tuple_size</a>&lt;<b>decltype</b>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi0EE">w_state</span>(
            <b>static_cast</b>&lt;<span class="type" title='Bar' data-ref="Bar">Bar</span>**&gt;(<b>nullptr</b>), <span class="tu ref fn fake" title='w_number&lt;0&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi0EEC1EOS0_"></span><span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>255</var>&gt;<span class="tu ref fn" title='w_number&lt;255&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi255EEC1Ev">(</span>)))&gt;::<a class="ref" href="https://code.woboq.org/qt5/include/c++/7.3.0/type_traits.html#std::integral_constant::value" title='std::integral_constant::value' data-ref="std::integral_constant::value" data-proj="include">value</a> + <var>1</var>&gt; <dfn class="local col5 decl" id="5n" title='n' data-type='w_number&lt;tuple_size&lt;decltype(w_state(static_cast&lt;Bar **&gt;(nullptr), w_number&lt;255&gt;()))&gt;::value + 1&gt;' data-ref="5n">n</dfn>)
        -&gt; <b>decltype</b>(<a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi0EE">w_state</span>(<span class="local col4 ref" title='t' data-ref="4t">t</span>, <span class="local col5 ref" title='n' data-ref="5n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Bar' data-ref="Bar">Bar</span>::<span class="tu ref fn" title='Bar::xx' data-use='a' data-ref="_ZN3Bar2xxEv">xx</span>)))
    { <b>return</b> <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi0EE">w_state</span>(<span class="local col4 ref" title='t' data-ref="4t">t</span>, <span class="local col5 ref" title='n' data-ref="5n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Bar' data-ref="Bar">Bar</span>::<span class="tu ref fn" title='Bar::xx' data-use='a' data-ref="_ZN3Bar2xxEv">xx</span>)); }

    <em>int</em> <dfn class="tu decl fn" id="_ZN3Bar2yyEv" title='Bar::yy' data-type='int Bar::yy()' data-ref="_ZN3Bar2yyEv">yy</dfn>();

    <b>friend</b> <b>constexpr</b> <em>auto</em> <dfn class="decl def fn" id="_Z7w_statePP3Bar8w_numberILi2EE" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi2EE">w_state</dfn>(<span class="type" title='Bar' data-ref="Bar">Bar</span> **<dfn class="local col6 decl" id="6t" title='t' data-type='Bar **' data-ref="6t">t</dfn>, <span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<a class="type" href="https://code.woboq.org/qt5/include/c++/7.3.0/utility.html#std::tuple_size" title='std::tuple_size' data-ref="std::tuple_size" data-proj="include">tuple_size</a>&lt;<b>decltype</b>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi1EE">w_state</span>(
            <b>static_cast</b>&lt;<span class="type" title='Bar' data-ref="Bar">Bar</span>**&gt;(<b>nullptr</b>), <span class="tu ref fn fake" title='w_number&lt;1&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi1EEC1EOS0_"></span><span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>255</var>&gt;<span class="tu ref fn" title='w_number&lt;255&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi255EEC1Ev">(</span>)))&gt;::<a class="ref" href="https://code.woboq.org/qt5/include/c++/7.3.0/type_traits.html#std::integral_constant::value" title='std::integral_constant::value' data-ref="std::integral_constant::value" data-proj="include">value</a> + <var>1</var>&gt; <dfn class="local col7 decl" id="7n" title='n' data-type='w_number&lt;tuple_size&lt;decltype(w_state(static_cast&lt;Bar **&gt;(nullptr), w_number&lt;255&gt;()))&gt;::value + 1&gt;' data-ref="7n">n</dfn>)
        -&gt; <b>decltype</b>(<a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi1EE">w_state</span>(<span class="local col6 ref" title='t' data-ref="6t">t</span>, <span class="local col7 ref" title='n' data-ref="7n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Bar' data-ref="Bar">Bar</span>::<span class="tu ref fn" title='Bar::yy' data-use='a' data-ref="_ZN3Bar2yyEv">yy</span>)))
    { <b>return</b> <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt9tuple_catDpOT_" title='std::tuple_cat' data-ref="_ZSt9tuple_catDpOT_" data-proj="include">tuple_cat</a>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi1EE">w_state</span>(<span class="local col6 ref" title='t' data-ref="6t">t</span>, <span class="local col7 ref" title='n' data-ref="7n">n</span>.<span class="tu ref fn" title='w_number::prev' data-use='c' data-ref="_ZN8w_number4prevEv">prev</span>()), <a class="ref fn" href="https://code.woboq.org/qt5/include/c++/7.3.0/tuple.html#_ZSt10make_tupleDpOT_" title='std::make_tuple' data-ref="_ZSt10make_tupleDpOT_" data-proj="include">make_tuple</a>(&amp;<span class="type" title='Bar' data-ref="Bar">Bar</span>::<span class="tu ref fn" title='Bar::yy' data-use='a' data-ref="_ZN3Bar2yyEv">yy</span>)); }
};

<i  data-doc="BarMetaObject">// Use that state</i>
<b>constexpr</b> <em>auto</em> <dfn class="tu decl def" id="BarMetaObject" title='BarMetaObject' data-type='const std::tuple&lt;int (Bar::*)(), int (Bar::*)()&gt;' data-ref="BarMetaObject">BarMetaObject</dfn> = <span class="ref fn" title='buildMetaObject' data-ref="_Z15buildMetaObjectT_">buildMetaObject</span>(<span class="ref fn" title='w_state' data-ref="_Z7w_statePP3Bar8w_numberILi2EE">w_state</span>(<b>static_cast</b>&lt;<span class="type" title='Bar' data-ref="Bar">Bar</span>**&gt;(<b>nullptr</b>), <span class="tu ref fn fake" title='w_number&lt;2&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi2EEC1EOS0_"></span><span class="type" title='w_number' data-ref="w_number">w_number</span>&lt;<var>255</var>&gt;<span class="tu ref fn" title='w_number&lt;255&gt;::w_number' data-use='c' data-ref="_ZN8w_numberILi255EEC1Ev">(</span>)));
</pre>

 <h2>Conclusion</h2>
 <p>Please let me know when you find Verdigris useful or want to help out, either here in the comments or contribute directly on GitHub.
 </p>

]]></description></item>
<item><title>QML vs. C++ for application startup time</title><link>https://woboq.com/blog/qml-vs-cpp-for-application-startup-time.html</link><guid>http://woboq.com/blog/qml-vs-cpp-for-application-startup-time.html</guid><pubDate>Tue, 18 Jul 2017 14:24:11 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>After 5.8 reduced startup times with its QML compilation caching, object creation remains one of the largest startup time consumer for Qt Quick applications. One can use Loaders to avoid loading parts of the application that are not currently visible, but some scenes with higher complexity can still be taking quite some time to initialize when they urgently need to be displayed, especially on embedded systems.</p>
    <p>At QtCon 2016 <a href="https://conf.qtcon.org/en/qtcon/public/events/428">Andrew Knight presented a few benchmarks</a> showing a situations where C++ can improve Qt Quick object creation times over QML. A conclusion of the session was that those benchmark results would need to be taken with a grain of salt since the specific benefits could be smaller in a real application relatively to everything else happening around.</p>
    <p>What we’re presenting today are results of converting parts of a well-known QML example to C++ using public and private APIs, measuring the improvements on loading and execution times to have a better estimate of the opportunity for real world applications.</p>
</div>
<h3>Preparation</h3>
<p>We’re going to use the <a href="http://doc.qt.io/qt-5/qtquick-demos-samegame-example.html">samegame QML example</a> as reference. This gives us a complete application handling events and producing visual outputs. Like many QML applications reaching initial maturity, focus hasn’t been put on performance optimizations in samegame yet.</p>
<p>Let's start by profiling the application in order to fix the low hanging fruits first. This involves the QML Profiler, but also a regular C++ profiler (like macOS Instruments or Linux perf) together with a "<code>-release -force-debug-info</code>" configured Qt (don't pass <code>-developer-build</code> since it changes the way QML caching behaves). This leads us to remove Qt Quick Particles, QQmlFileSelector, and we’ll also convert property behaviors and states into imperative animations. These changes already considerably improve the performances by reducing the number of QObjects in the scene and by preventing the use of a few less scalable features of Qt Quick.</p>
<p>Most importantly for now, this allows us to focus performance measurements on application code, making sure that both our QML and C++ implementations use the same Qt Quick code paths and total number of QObjects.</p>
<h3>Benchmarks</h3>
<p>Samegame will be <a href="https://code.woboq.org/qt5/qtbase/src/plugins/platforms/eglfs/api/qeglfswindow.cpp.html#_ZN12QEglFSWindow11setGeometryERK5QRect">launched in fullscreen when using the eglfs platform plugin</a>, this means that the game area will fill the screen, and on a 1080p display will give us a grid of 60x31 game blocks. We use a Nitrogen6X quad core i.MX6 for this project, running Yocto 2.2 and a standard cross-compiled build of Qt 5.9.1. Running those benchmarks on desktop gave us times around 20x faster, but the relative improvements were similar so we'll focus on i.MX6 results.</p>
<p>Two actions in the application will be uses as reference for our benchmarks:</p>
<ul>
    <li>
        <a href="https://github.com/woboq/samegame-benchmark/blob/master/main.cpp#L89">
            <b>Starting a new game,</b>
        </a> which uses a thin JavaScript loop to fill the game area with created Block objects.</li>
    <li>
        <a href="https://github.com/woboq/samegame-benchmark/blob/master/main.cpp#L106">
            <b>Clicking at a fixed position inside the game area,</b>
        </a> which is a heavier JavaScript loop that updates the position of all blocks on the right of the clicked column (since the game has been hardcoded to fill each column with the same color, clicking removes one column and move following columns to the left)</li>
</ul>
<p style="width:90%; margin: auto; text-align: center;">
    <img style="display: block; width:100%; box-shadow: 1px 1px 2px 2px #ddd" src="https://woboq.com/blog/qml-vs-cpp-for-application-startup-time/samegame-benchmark.png"/>
    <i>The StartGameBenchmark measures creating this scene, the HandleClickBenchmark measures clicking on the left-most row and iterating over all blocks to move them left.</i>
</p>
<p>A benchmark has been written inside <code>main()</code> to wrap those functions and execute them multiple times to be able to provide more precise measurements. <a href="https://github.com/woboq/samegame-benchmark/commits/master">At multiple stages of the conversion from QML to C++</a> we will run those two benchmarks and gather results:</p>
<ol>
    <li>
        <p>The reference QML implementation (with Qt Quick Particles, QQmlFileSelector and declarative animations removed) without any C++:</p>
        <pre class="brush: qml">
// QML
Block { function fadeIn() { /*...*/ } }
</pre>
        <pre class="brush: qml">
// JavaScript
block.fadeIn();
</pre>
    </li>
    <li>
        <p>Only the samegame.js JavaScript Logic code that is run through our benchmarks has been converted to C++:</p>
        <pre class="brush: qml">
// QML
Block { function fadeIn() { /*...*/ } }
</pre>
        <pre class="brush: cpp">
// C++
QMetaObject::invokeMethod(block, "fadeIn");
</pre>
    </li>
    <li>
        <p>Block.qml is also implemented in C++ as a QQuickItem subclass. Everything is still connected together using Qt meta-object properties and methods:</p>
        <pre class="brush: cpp">
// C++
class Block : public QQuickItem { Q_INVOKABLE void fadeIn() { /*...*/ } };
</pre>
        <pre class="brush: cpp">
// C++
QMetaObject::invokeMethod(block, "fadeIn");
</pre>
    </li>
    <li>
        <p>As above, but doing direct C++ method calls rather than going through meta-objects:</p>
        <pre class="brush: cpp">
// C++
class Block : public QQuickItem { void fadeIn() { /*...*/ } };
</pre>
        <pre class="brush: cpp">
// C++
block-&gt;fadeIn();
</pre>
    </li>
</ol>
<h3>Benchmark 1: Starting a new game</h3>
<img src="https://woboq.com/blog/qml-vs-cpp-for-application-startup-time/startGameResults.png" srcset="https://woboq.com/blog/qml-vs-cpp-for-application-startup-time/startGameResults@2x.png 2x"/>
<p>Our implementation is using 5 QObjects per block, 2 of which are QQuickItems, for a total of 9300 QObjects. Creating a screen full of blocks for a new game takes 1.153 seconds on our i.MX6 (<b>definitely user-noticeable</b>), but we can reduce it to 0.388 seconds if we create the same item and object structure in C++ (197% faster). The largest gain comes from reimplementing Block.qml in C++ which alone gives us a speed improvement of 124%, mostly because we avoid the evaluation of QML properties and the creation of property bindings during instantiation.</p>
<h3>Benchmark 2: Handling a click</h3>
<img src="https://woboq.com/blog/qml-vs-cpp-for-application-startup-time/handleClickResults.png" srcset="https://woboq.com/blog/qml-vs-cpp-for-application-startup-time/handleClickResults@2x.png 2x"/>
<p>This benchmark iterates over the blocks that need to be moved, starts an animation on the x and y property of each block’s root item, and update the blocks board position in the index array. Our C++ implementation is 120% faster but since this action doesn’t create any new QML object, the largest gain comes from reimplementing the JavaScript for-loop in C++, which alone is 57% faster.</p>
<p>The QML JIT implementation usually competes acceptably well with C++ and one thing to note is that the total time for handling this click in our case also has a considerably smaller performance footprint on our application than creation times covered by the Start Game benchmark. So while relatively put this is faster, the user will not notice the 117 ms reduction for Handle Click as much as the 764 ms reduction of the Start Game case.</p>
<h3>Why is C++ faster?</h3>
<p>Qt Quick and QML are very efficient when it comes to update a scene frame after frame to produce a smooth animation. Properties are consistently and efficiently updated according to animations by property bindings, layout will involve only the necessary elements and the scene graph will reuse as many OpenGL objects as possible to render the new frame, most of the time, with optimal state changes in system and graphics memory.</p>
<p>However, having this structure in place requires some runtime initialization to be done at creation time, and a mostly-dynamically-typed language like QML can’t really compete in this sport with a language like C++, whose design makes performance and compile-time optimizations a top-priority over its other language characteristics.<br/>
On top of having to create the same backing C++ QObject and QQuickItem, <b>QML must resolve dynamic types, create data-structures to represent property bindings and go through the Qt meta-object type system to access any native member. Almost all of which C++ performs equivalently at compile time.</b>
</p>
<p>One of the reasons why QML can choose to offer conciseness and development speed at the cost of some performance is because it’s also designed to interface well with C++ code. This is an opportunity that, for example, <a href="http://blog.qt.io/blog/2016/06/10/qt-quick-controls-2-0-a-new-beginning/">Qt Quick Controls 2</a> has taken to reduce compilation and creation times with gains comparable to what is presented here. Qt Quick Controls 2 has an advantage over applications though: it’s part of Qt and it has access to private symbols like QQuickText, QQuickRectangle, QQuickFlickable, and even QQuickItemPrivate.</p>
<p>While our C++ implementation is tailored for measuring the potential performance gain of those two specific benchmarks, an ideal method would be if applications could do layout in QML, but handle events and state changes from C++ where the performance gain would be valuable. This could take advantage of strengths of both languages while reducing the number of dynamically-typed property bindings and JavaScript blocks to perform at runtime.<br/>
There is still some work to be done in Qt Quick to be able to conveniently harness C++ in UI code. We've already been able to mix the two languages <a href="https://github.com/woboq/samegame-benchmark/blob/master/gameareaimpl.h#L47">using some hacks for this exercise</a>, but the real blocker at the moment is that we need to be able to create Qt Quick visual primitives like animations, images and rectangles from C++ just like from QML.</p>
<h3>Give up binary compatibility?</h3>
<p>For this experiment, we had to expose private API that isn’t dynamically exported (i.e. QQuickSpringAnimation).
<code>qmake</code> makes it relatively easy to access exported private symbols.
This comes at a hefty price: those APIs are not supported and source and binary compatibility are not guaranteed.<br/>
An application could theoretically use private APIs without major problems if they are recompiled for any update of Qt.
Changes to Qt private API would otherwise likely result in application crashes.</p>
<p>The question is then: <b>should more of the Qt Quick API be publically exposed to C++ application code?</b>
</p>
<h3>Conclusion</h3>
<p>While we demonstrate how using some C++ private Qt Quick APIs can allow you to improve the creation times today, this is unsupported it’s not something that we recommend.</p>
<p>This blog post puts emphasis on creation times, but note that for general performance optimizations we recommend profiling and following the excellent <a href="http://doc.qt.io/qt-5/qtquick-performance.html">Qt Quick Performance Considerations And Suggestions</a> before considering any unsupported solution.</p>
<p>It should be clear that even though C++ is faster in this case, declarative QML will usually remain a better choice for core UI code because of its flexibility and conciseness. <a href="http://blog.qt.io/blog/2017/05/31/performance-improvements-with-qt-5-9-lts/">QML is also getting faster every release</a>, this gap will continue shrinking up to a point. As for non-UI business logic, C++ can already be used comfortably without requiring using private Qt Quick APIs.</p>
<p>Long creation times are also not a problem if it can happen while the user is not waiting, this can be accomplished with asynchronous Loaders or by pre-loading components.</p>
<p>To conclude we are asking the community: <b>Are those loading time improvements a great enough opportunity to justify improving the C++ brigde for UI code and extending the public Qt Quick API to classes like animations, QQuickRectangle and QQuickImage?</b> A set of base classes that would give applications a freedom similar to what Qt Quick Controls 2 has.</p>
<p>Contribute to the discussion by letting us know in social medias or comments below if you have experience using C++ for Qt Quick UI code, and/or could benefit from having those functionalities publicly available.</p>
]]></description></item>
<item><title>Woboq Code Browser: under the hood</title><link>https://woboq.com/blog/codebrowser-under-the-hood.html</link><guid>http://woboq.com/blog/codebrowser-under-the-hood.html</guid><pubDate>Mon, 24 Oct 2016 17:48:33 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>A few years ago, I was <a href="https://woboq.com/blog/codebrowser-introduction.html">introducing</a> the code browser
and <a href="https://code.woboq.org">code.woboq.org</a>
    </p>
    <p>Since the then, we implemented a few new features and made the
  <a href="https://github.com/woboq/woboq_codebrowser">source code available</a>, which you can 
  browse <a href="https://code.woboq.org/woboq/codebrowser/">from the code browser itself</a>.</p>
    <p>In this article, I give more technical information on how this is all done.</p>
</div>
<h2>What/Why a code browser?</h2>
<p>As a developer, I spend more time reading code than writing,  and I found reading code online a rather poor experience.
  Hence, I made a way to publish code in a way that can be read just like in a good IDE, <strong>with links, tooltips, and semantic highlighting</strong>.
  Read more about it in the <a href="https://woboq.com/blog/codebrowser-introduction.html">original blog post</a>.</p>
<h2>Architecture Overview</h2>
<p>The idea is that there is a generator that generates all the .html pages ahead of time. This is a bit like a compilation. 
  In the process we also fill up a <em>database</em> containing all the symbols and where
  they are defined or used, as well as other information such as the documentation.</p>
<h3>The database</h3>
<p>Because <em>NoSQL</em> is trendy, we use a well-known NoSQL database directly included in the kernel: the file system  ☺.
  There is a huge directory containing one file per global symbol. Each file contains all the information you see in the tooltip. 
  The type of the variable, the list of its uses and its documentation.  The HTML files has tags referencing the symbol, the JavaScript can then do 
  an AJAX request on that file in order to render the tooltip contents.
  </p>
<p>For example, the <a href="https://code.woboq.org/qt5/refs/_ZN10QQmlEngine19removeImageProviderERK7QString">file for <code>QQmlEngine::removeImageProvider</code>
    </a>, looks like this: </p>
<pre>
&lt;dec f='qtdeclarative/src/qml/qml/qqmlengine.h' l='132' type='void QQmlEngine::removeImageProvider(const QString &amp;amp; id)'/&gt;
&lt;def f='qtdeclarative/src/qml/qml/qqmlengine.cpp' l='1209' type='void QQmlEngine::removeImageProvider(const QString &amp;amp; providerId)'/&gt;
&lt;doc f='qtdeclarative/src/qml/qml/qqmlengine.cpp' l='1204'&gt;/*!
  Removes the image provider for \a providerId.

  \sa addImageProvider(), QQuickImageProvider
*/&lt;/doc&gt;
&lt;use f='qtdeclarative/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp' l='360' u='c' c='_ZN23tst_qquickimageprovider14removeProviderEv'/&gt;
&lt;use f='qtdeclarative/tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp' l='389' u='c' c='_ZN23tst_qquickimageprovider15imageProviderIdEv'/&gt;
</pre>
<a href="https://code.woboq.org/data/symbol.html?root=../qt5/&amp;ref=_ZN10QQmlEngine19removeImageProviderERK7QString">
    <img class="screenshot" src="https://woboq.com/blog/codebrowser-under-the-hood/qqmlengine-removeimageprovider.png" style="float:right; margin-left:1em"/>
</a>
<p>You can see that there is one entry for the <b>dec</b>laration, the <b>def</b>inition, the <b>doc</b>umentation, and one for each usage.
This is the information displayed in the tooltip.<br/>
We also store information about inherited classes or methods.
<br/>
See the <a href="https://code.woboq.org/data/symbol.html?root=../qt5/&amp;ref=_ZN10QQmlEngine19removeImageProviderERK7QString">symbol page</a> that shows information from the tooltip and more.
</p>
<p>This way, the whole generated browsable code is just a set of files that can be served by any simple web server.
  The whole thing is maybe three times as big as the original source code. Which still amounts to several GB when we host so much source code.
  However, it is highly compressible. To save space and ease upload,
  <a href="https://woboq.com/blog/saving-disk-space-on-your-webserver-with-squashfs.html">we use squashfs images</a>. That way
we even have atomic updates ☺</p>
<h2>Using Clang to parse C/C++</h2>
<p>Here is the interesting part: how is the generator working?</p>
<p>
    <em>
        <a href="https://clang.llvm.org">Clang</a>
    </em> is more than just a compiler, it is really a library to parse C and C++.</p>
<p>Clang provides all the tools required, all I have to do is to create an <code>clang::ASTConsumer</code>.
  Once the parser has finished its job, we can then visit the full AST of the translation unit with the <code>clang::RecursiveASTVisitor</code>.
  As explained in this <a href="http://clang.llvm.org/docs/RAVFrontendAction.html">tutorial</a>.</p>
<p>We then visit all the declarations and usage nodes. We know the source location of the node,
  so we know if we are in a file that we should generate.  In particular, we do not generate header files twice, so if
  the header file has already been parsed, we ignore that node. 
  
  Knowing the location of the node, we can register a HTML tag for it.  We give a <code>data-ref</code>
  tag with the mangled name of the symbol so the
  JavaScript will be able to show the tooltip, and we give proper classes so it can be semantically styled.
  
  We also register the use in the database.

  </p>
<h3>Macro Expansions</h3>
<img class="screenshot" src="https://woboq.com/codebrowser_screenshots/macro1.png" style="float:right; margin-left:1em"/>
<p>We also show the expansion of a macro in the macro tooltip.
  Macros does not appear as node in the AST because they are expanded before,
    in the pre-processing phase.
    We use <code>clang::PPCallback</code> to be notified each time a macro is expended.
    Unfortunately, getting the actual expansion is far from easy since the expansion never appears as
    such in memory. What happens is that the pre-processor just provides tokens to the parser.
    We have to <a href="https://code.woboq.org/woboq/codebrowser/generator/preprocessorcallback.cpp.html#_ZN20PreprocessorCallback12MacroExpandsERKN5clang5TokenERKNS0_15MacroDefinitionENS0_11SourceRangeEPKNS0_9MacroArgsE">
    pre-process again the macro and write the token strings in to tooltip</a>.
  </p>
<h3>Documentation Comments</h3>
<p>Comments are ignored by the parser so they are not part of the AST.
  We do another pass in which, for each file, in which we find comments and keywords for the
  basic syntax coloration of things that are not in the AST, and color these element
  appropriately.  We will try to associate the comments with
  the closest declaration or definition, so it can go in the database (in the tooltip).
  We also recognize some doxygen commands such as <code>\fn</code> which associate the
  comment with a different declaration.
  </p>
<h3>Qt SIGNAL and SLOT</h3>
<p>We detect a few Qt extensions. We recognize calls to <code>QObject::connect</code>, <code>QMetaObject::activate</code> and
  similar call like <code>QTimer::singleShot</code> (See the <a href="https://code.woboq.org/woboq/codebrowser/generator/qtsupport.cpp.html#_ZN9QtSupport13visitCallExprEPN5clang8CallExprE">full list of recognized functions</a>). Since <code>SIGNAL</code> and <code>SLOT</code>
  are macros that transform their argument to string, we can easily extract the string literal and parse that in order to
  find to what method it is. We know in which class to look because know the type of the QObject sub class of the receiver parameter.</p>
<h3>Usage classification</h3>
<p>When looking at the AST, we see how the variables are used. We can classify if the
   variable was simply read, or modified. We add a little letter in the
   uses in the tooltip. If you click on the little 🔗 icon in the top-right of the tooltip
   you can filter by type of usage.</p>
<img class="screenshot" src="https://woboq.com/blog/codebrowser-under-the-hood/usagesfilter.png"/>
<p>Similarly, we see when arguments are passed by references, and we annotate the source code with little <code>&amp;</code>.  We also annotate the code with little <code>⎀</code>
   when there is an implicit call to a constructor or conversion operator.</p>
<h2>Clang Tooling</h2>
<p>The clang tooling needs to interface with the build system to know the list of compilation commands. (The flags passed to the compiler
    such as the include paths, the defines, or other languages options).  
<br/>

    All the commands are in a compilation database hold in a <code>compile_commands.json</code> file. If one use cmake as a build system, it is 
    trivial to generate this list of command by passing <code>-DCMAKE_EXPORT_COMPILE_COMMANDS=ON</code>. Ninja also can export the compile_commands.
    But with others build system it is a bit more complicated.  With some build system such as qmake, we parse the output of <code>make -n</code>.
    When that is not supported, there is a script used as a proxy compiler that records the compilation commands.</p>
<p>Find out more about this in <a href="https://github.com/woboq/woboq_codebrowser#compilation-database-compile_commandsjson">the README</a>.</p>
<h2>Javascript Code</h2>
<p>Once the static HTML and the database have been generated, the rest of the logic happens client side.
The server is simply serving static files. The Javascript code runs in the browser will fetch these files
and enable all the features such as the tooltip or the search.</p>
<h3>Search for a file or function</h3>
<img class="screenshot" src="https://woboq.com/codebrowser_screenshots/searchfunction.png"/>
<p>In order to find a file, the browser will first download, via AJAX, a file containing the
list of all the files for this project. For the functions, a file containing all the functions
would be too big. We therefore split the functions in several files starting with the
first two letters of the function.  So when someone starts typing "<code>Parse</code>", the file
<code>fnSearch/pa</code> (<code>pa</code> being the first two letters) gets downloaded to find matches in there.
</p>
<h2>Conclusion</h2>
<p>This was explaining how <a href="https://code.woboq.org">code.woboq.org</a> works.
Get it <a href="https://woboq.com/codebrowser.html#evaluation">for your own code!</a>
</p>
]]></description></item>
<item><title>QReadWriteLock gets faster in Qt 5.7</title><link>https://woboq.com/blog/qreadwritelock-gets-faster-in-qt57.html</link><guid>http://woboq.com/blog/qreadwritelock-gets-faster-in-qt57.html</guid><pubDate>Wed, 10 Aug 2016 08:55:41 GMT</pubDate><description><![CDATA[


<div class="intro"><p>
In Qt 5.0 already, QMutex got revamped to be fast. In the non contended case, locking and unlocking
is basically only a simple atomic instruction and it does not allocate memory making it really light.
QReadWriteLock however did not get the same optimizations. Now in Qt 5.7, it gets on par with QMutex.
</p></div>

<h2 id='qreadwritelock'>QReadWriteLock</h2>
<p>
<a href="http://doc.qt.io/qt-5/qreadwritelock.html"><code>QReadWriteLock</code></a>'s purpose is about the same as the one of <a href="http://doc.qt.io/qt-5/qmutex.html"><code>QMutex</code></a>: to protect a critical
section. The difference is that QReadWriteLock proposes two different locking modes: read or write.
This allows several readers to access the critical section at the same time, and therefore be potentially
more efficient than a QMutex. At least that was the intention. But the problem is that, before Qt 5.7,
QReadWriteLock's implementation was not as optimized as QMutex. In fact, QReadWriteLock was internally locking and
unlocking a QMutex on every call (read or write). So QReadWriteLock was in fact slower than
QMutex, unless the read section was held for a very long time, under contention.
</p>
<p>For example, the internals of QMetaType were using a QReadWriteLock for the QMetaType database.
This makes sense because that database is accessed very often for reading (every time one creates or
operates on a QVariant) and very seldom accessed for writing (only when you need to register a new
type the first time it is used). However, the QReadWriteLock locking (for read) was so slow that it took
a significant amount of time in some QML application that use lots of QVariants, for example with Qt3D.<br/>
It was even proposed to <a href="https://codereview.qt-project.org/gitweb?p=qt/qtbase.git;a=commitdiff;h=cd63456e2c2c342fda8a2b71754884a5a35d71c6">replace QReadWriteLock
by a QMutex within QMetaType</a>. This would have saved 40% of the time of the QVariant creation. This was not necessary because I improved QReadWriteLock in Qt 5.7 to make it at least as fast as QMutex.
</p>


<h2 id='qmutex'>QMutex</h2>

<p>QMutex is itself quite efficient already.
I described the <a href="https://woboq.com/blog/internals-of-qmutex-in-qt5.html">internals of QMutex in a previous article</a>.
Here is a reminder on the important aspects on QMutex:</p>
<ul><li><code>sizeof(QMutex) == sizeof(void*)</code>, without any additional allocation.</li>
<li>The non-contended case is basically only an atomic operation for lock or unlock</li>
<li>In case we need to block, fallback to pthread or native locking primitives</li>
</ul>


<h2 id='new_qreadwritelock'>QReadWriteLock in Qt 5.7</h2>
<p>
I <a href="https://codereview.qt-project.org/140322/">optimized QReadWriteLock</a> to bring it on
par with QMutex, using the the same implementation principle.
</p>

<p>QReadWriteLock only has one member: a QAtomicPointer named <code>d_ptr</code>.
Depending on the value of <code>d_ptr</code>, the lock is in the following state:
</p>
<ul><li>When <code>d_ptr == 0x0</code> (all the bits are 0): unlocked and non-recursive. No readers or writers holding nor waiting on it.</li>
<li>When <code>d_ptr &amp; 0x1</code> (the least significant bit is set):
one or several readers are currently holding the lock. No writers are waiting and the lock is non-recursive.
The amount of readers is <code>(d_ptr >> 4) + 1</code>.</li>

<li>When <code>d_ptr == 0x2</code>:
we are locked for write and nobody is waiting.</li>
<li>In any other case, when the two least significant bits are 0 but the remaining bits contain data,
<code>d_ptr</code> points to a <code>QReadWriteLockPrivate</code> object which either means that
the lock is recursive, or that it is currently locked and threads are possibly waiting.
The QReadWriteLockPrivate has a condition variable allowing to block or wake threads.</li>
</ul>

<p>In other words, the two least significant bits encode the state. When it is a pointer
to a QReadWriteLock, those two bits will always be 0 since pointers must
be properly aligned to 32 or 64 bits addresses for the CPU to use them.</p>

<p>This table recap the state depending on the two least significant bits:</p>

<table border="1">
<tr><td></td><td>if <code>d_ptr</code> is fully 0, then the lock is <b>unlocked</b>.</td></tr>
<tr><td><code>00</code></td><td>If <code>d_ptr</code> is not fully 0, it is pointer to a <code>QReadWriteLockPrivate</code>.</td></tr>
<tr><td><code>01</code></td><td>One or several <b>readers</b> are currently holding the lock.
The amount of reader is <code>(d_ptr >> 4) + 1</code>.</td></tr>
<tr><td><code>10</code></td><td>One <b>writer</b> is holding the lock and nobody is waiting</td></tr>
</table>


<p>We therefore define a few constants to help us read the code.</p>

<pre class="code"><b>enum</b> {
    <dfn class="enum" id="StateMask" title='StateMask' data-ref="StateMask">StateMask</dfn> = <var>0x3</var>,
    <dfn class="enum" id="StateLockedForRead" title='StateLockedForRead' data-ref="StateLockedForRead">StateLockedForRead</dfn> = <var>0x1</var>,
    <dfn class="enum" id="StateLockedForWrite" title='StateLockedForWrite' data-ref="StateLockedForWrite">StateLockedForWrite</dfn> = <var>0x2</var>,
};
<em>const</em> <em>auto</em> <dfn class="tu decl def" id="_ZL18dummyLockedForRead" title='dummyLockedForRead' data-type='QReadWriteLockPrivate *const' data-ref="_ZL18dummyLockedForRead">dummyLockedForRead</dfn> = <b>reinterpret_cast</b>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase" ">QReadWriteLockPrivate</a> *&gt;(<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="enum" title='StateLockedForRead' data-ref="StateLockedForRead">StateLockedForRead</span>));
<em>const</em> <em>auto</em> <dfn class="tu decl def" id="_ZL19dummyLockedForWrite" title='dummyLockedForWrite' data-type='QReadWriteLockPrivate *const' data-ref="_ZL19dummyLockedForWrite">dummyLockedForWrite</dfn> = <b>reinterpret_cast</b>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *&gt;(<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="enum" title='StateLockedForWrite' data-ref="StateLockedForWrite">StateLockedForWrite</span>));
<b>inline</b> <em>bool</em> <dfn class="decl def" id="_Z19isUncontendedLockedPK21QReadWriteLockPrivate" title='isUncontendedLocked' data-ref="_Z19isUncontendedLockedPK21QReadWriteLockPrivate">isUncontendedLocked</dfn>(<em>const</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *<dfn class="local col1 decl" id="1d" title='d' data-type='const QReadWriteLockPrivate *' data-ref="1d">d</dfn>)
{ <b>return</b> <a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col1 ref" title='d' data-ref="1d">d</span>) &amp; <span class="enum" title='StateMask' data-ref="StateMask">StateMask</span>; }
</pre>

<p>Aside: The code assumes that the null pointer value is equal to binary 0, which is not guaranteed
by the C++ standard, but holds true on every supported platform.</p>

<h2 id='lockforread'><code>lockForRead</code></h2>

<p>The really fast case happens when there is no contention. If we can atomically swap from
0 to <code>StateLockedForRead</code>, we have the lock and there is nothing to do.
If there already are readers, we need to increase the reader count, atomically.
If a writer already holds the lock, then we need to block. In order to block, we will assign a
QReadWriteLockPrivate and wait on its condition variable.
We call <code>QReadWriteLockPrivate::allocate()</code> which will pop an unused QReadWriteLockPrivate
from a lock-free stack (or allocates a new one if the stack is empty).
Indeed, we can never free any of the QReadWriteLockPrivate as another thread might
still hold pointer to it and de-reference it. So when we release a QReadWriteLockPrivate, we put it in a lock-free stack.</p>

<p><code>lockForRead</code> actually calls <code>tryLockForRead(-1)</code>, passing -1 as the timeout
means "wait forever until we get the lock".</p>

<p>Here is the slightly edited code.
<a href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.cpp.html#_ZN14QReadWriteLock14tryLockForReadEi">
(original)</a> </p>


<pre class="code"><em>bool</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock" title='QReadWriteLock' data-ref="QReadWriteLock" data-proj="qtbase" ">QReadWriteLock</a>::<dfn class="decl def" id="_ZN14QReadWriteLock14tryLockForReadEi" title='QReadWriteLock::tryLockForRead' data-ref="_ZN14QReadWriteLock14tryLockForReadEi">tryLockForRead</dfn>(<em>int</em> <dfn class="local col2 decl" id="2timeout" title='timeout' data-type='int' data-ref="2timeout">timeout</dfn>)
{
    <i>// Fast case: non contended:</i>
    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *<dfn class="local col3 decl" id="3d" title='d' data-type='QReadWriteLockPrivate *' data-ref="3d">d</dfn>;
    <b>if</b> (<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetAcquire' data-ref="_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" data-proj="qtbase" ">testAndSetAcquire</a>(<b>nullptr</b>, <span class="tu ref" title='dummyLockedForRead' data-use='r' data-ref="_ZL18dummyLockedForRead">dummyLockedForRead</span>, <span class='refarg'><span class="local col3 ref" title='d' data-ref="3d">d</span></span>))
        <b>return</b> <b>true</b>;

    <b>while</b> (<b>true</b>) {
        <b>if</b> (<span class="local col3 ref" title='d' data-ref="3d">d</span> == <var>0</var>) {
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetAcquire' data-ref="_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" data-proj="qtbase">testAndSetAcquire</a>(<b>nullptr</b>, <span class="tu ref" title='dummyLockedForRead' data-use='r' data-ref="_ZL18dummyLockedForRead">dummyLockedForRead</span>, <span class='refarg'><span class="local col3 ref" title='d' data-ref="3d">d</span></span>))
                <b>continue</b>;
            <b>return</b> <b>true</b>;
        }

        <b>if</b> ((<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col3 ref" title='d' data-ref="3d">d</span>) &amp; <span class="enum" title='StateMask' data-ref="StateMask">StateMask</span>) == <span class="enum" title='StateLockedForRead' data-ref="StateLockedForRead">StateLockedForRead</span>) {
            <i>// locked for read, increase the counter</i>
            <em>const</em> <em>auto</em> <dfn class="local col4 decl" id="4val" title='val' data-type='QReadWriteLockPrivate *const' data-ref="4val">val</dfn> = <b>reinterpret_cast</b>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *&gt;(<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col3 ref" title='d' data-ref="3d">d</span>) + (<var>1U</var>&lt;&lt;<var>4</var>));
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetAcquire' data-ref="_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" data-proj="qtbase">testAndSetAcquire</a>(<span class="local col3 ref" title='d' data-ref="3d">d</span>, <span class="local col4 ref" title='val' data-ref="4val">val</span>, <span class='refarg'><span class="local col3 ref" title='d' data-ref="3d">d</span></span>))
                <b>continue</b>;
            <b>return</b> <b>true</b>;
        }

        <b>if</b> (<span class="local col3 ref" title='d' data-ref="3d">d</span> == <span class="tu ref" title='dummyLockedForWrite' data-use='r' data-ref="_ZL19dummyLockedForWrite">dummyLockedForWrite</span>) {
            <b>if</b> (!<span class="local col2 ref" title='timeout' data-ref="2timeout">timeout</span>)
                <b>return</b> <b>false</b>;

            <i>// locked for write, assign a d_ptr and wait.</i>
            <em>auto</em> <dfn class="local col5 decl" id="5val" title='val' data-type='QReadWriteLockPrivate *' data-ref="5val">val</dfn> = <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate8allocateEv" title='QReadWriteLockPrivate::allocate' data-ref="_ZN21QReadWriteLockPrivate8allocateEv" data-proj="qtbase">allocate</a>();
            <span class="local col5 ref" title='val' data-ref="5val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a> = <var>1</var>;
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetOrderedEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetOrdered' data-ref="_ZN19QBasicAtomicPointer17testAndSetOrderedEPT_S1_RS1_" data-proj="qtbase">testAndSetOrdered</a>(<span class="local col3 ref" title='d' data-ref="3d">d</span>, <span class="local col5 ref" title='val' data-ref="5val">val</span>, <span class='refarg'><span class="local col3 ref" title='d' data-ref="3d">d</span></span>)) {
                <span class="local col5 ref" title='val' data-ref="5val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a> = <var>0</var>;
                <span class="local col5 ref" title='val' data-ref="5val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate7releaseEv" title='QReadWriteLockPrivate::release' data-ref="_ZN21QReadWriteLockPrivate7releaseEv" data-proj="qtbase">release</a>();
                <b>continue</b>;
            }
            <span class="local col3 ref" title='d' data-ref="3d">d</span> = <span class="local col5 ref" title='val' data-ref="5val">val</span>;
        }
        <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(!isUncontendedLocked(d))) ? qt_assert(&quot;!isUncontendedLocked(d)&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,55) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase" ">Q_ASSERT</a>(!<span class="ref" title='isUncontendedLocked' data-ref="_Z19isUncontendedLockedPK21QReadWriteLockPrivate">isUncontendedLocked</span>(<span class="local col3 ref" title='d' data-ref="3d">d</span>));
        <i>// d is an actual pointer;</i>

        <b>if</b> (<span class="local col3 ref" title='d' data-ref="3d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::recursive" title='QReadWriteLockPrivate::recursive' data-ref="QReadWriteLockPrivate::recursive" data-proj="qtbase">recursive</a>)
            <b>return</b> <span class="local col3 ref" title='d' data-ref="3d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate20recursiveLockForReadEi" title='QReadWriteLockPrivate::recursiveLockForRead' data-ref="_ZN21QReadWriteLockPrivate20recursiveLockForReadEi" data-proj="qtbase">recursiveLockForRead</a>(<span class="local col2 ref" title='timeout' data-ref="2timeout">timeout</span>);

        <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#QMutexLocker" title='QMutexLocker' data-ref="QMutexLocker" data-proj="qtbase" ">QMutexLocker</a> <dfn class="local col6 decl" id="6lock" title='lock' data-type='QMutexLocker' data-ref="6lock">lock</dfn><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLockerC1EP11QBasicMutex" title='QMutexLocker::QMutexLocker' data-ref="_ZN12QMutexLockerC1EP11QBasicMutex" data-proj="qtbase">(</a>&amp;<span class="local col3 ref" title='d' data-ref="3d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::mutex" title='QReadWriteLockPrivate::mutex' data-ref="QReadWriteLockPrivate::mutex" data-proj="qtbase">mutex</a>);
        <b>if</b> (<span class="local col3 ref" title='d' data-ref="3d">d</span> != <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZNK19QBasicAtomicPointer4loadEv" title='QBasicAtomicPointer::load' data-ref="_ZNK19QBasicAtomicPointer4loadEv" data-proj="qtbase">load</a>()) {
            <i>// d_ptr has changed: this QReadWriteLock was unlocked before we had</i>
<i>            // time to lock d-&gt;mutex.</i>
<i>            // We are holding a lock to a mutex within a QReadWriteLockPrivate</i>
<i>            // that is already released (or even is already re-used). That's ok</i>
<i>            // because the QFreeList never frees them.</i>
<i>            // Just unlock d-&gt;mutex (at the end of the scope) and retry.</i>
            <span class="local col3 ref" title='d' data-ref="3d">d</span> = <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZNK19QBasicAtomicPointer11loadAcquireEv" title='QBasicAtomicPointer::loadAcquire' data-ref="_ZNK19QBasicAtomicPointer11loadAcquireEv" data-proj="qtbase">loadAcquire</a>();
            <b>continue</b>;
        }
        <b>return</b> <span class="local col3 ref" title='d' data-ref="3d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate11lockForReadEi" title='QReadWriteLockPrivate::lockForRead' data-ref="_ZN21QReadWriteLockPrivate11lockForReadEi" data-proj="qtbase">lockForRead</a>(<span class="local col2 ref" title='timeout' data-ref="2timeout">timeout</span>);
    }
}
</pre>

<h2 id='lockforwrite'><code>lockForWrite</code></h2>

<p>Exactly the same principle, as <code>lockForRead</code> but we would also block if there are
readers holding the lock.</p>
<pre class="code"><em>bool</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock" title='QReadWriteLock' data-ref="QReadWriteLock" data-proj="qtbase">QReadWriteLock</a>::<dfn class="decl def" id="_ZN14QReadWriteLock15tryLockForWriteEi" title='QReadWriteLock::tryLockForWrite' data-ref="_ZN14QReadWriteLock15tryLockForWriteEi">tryLockForWrite</dfn>(<em>int</em> <dfn class="local col7 decl" id="7timeout" title='timeout' data-type='int' data-ref="7timeout">timeout</dfn>)
{
    <i>// Fast case: non contended:</i>
    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *<dfn class="local col8 decl" id="8d" title='d' data-type='QReadWriteLockPrivate *' data-ref="8d">d</dfn>;
    <b>if</b> (<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetAcquire' data-ref="_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" data-proj="qtbase">testAndSetAcquire</a>(<b>nullptr</b>, <span class="tu ref" title='dummyLockedForWrite' data-use='r' data-ref="_ZL19dummyLockedForWrite">dummyLockedForWrite</span>, <span class='refarg'><span class="local col8 ref" title='d' data-ref="8d">d</span></span>))
        <b>return</b> <b>true</b>;

    <b>while</b> (<b>true</b>) {
        <b>if</b> (<span class="local col8 ref" title='d' data-ref="8d">d</span> == <var>0</var>) {
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetAcquire' data-ref="_ZN19QBasicAtomicPointer17testAndSetAcquireEPT_S1_RS1_" data-proj="qtbase">testAndSetAcquire</a>(<span class="local col8 ref" title='d' data-ref="8d">d</span>, <span class="tu ref" title='dummyLockedForWrite' data-use='r' data-ref="_ZL19dummyLockedForWrite">dummyLockedForWrite</span>, <span class='refarg'><span class="local col8 ref" title='d' data-ref="8d">d</span></span>))
                <b>continue</b>;
            <b>return</b> <b>true</b>;
        }

        <b>if</b> (<span class="ref" title='isUncontendedLocked' data-ref="_Z19isUncontendedLockedPK21QReadWriteLockPrivate">isUncontendedLocked</span>(<span class="local col8 ref" title='d' data-ref="8d">d</span>)) {
            <b>if</b> (!<span class="local col7 ref" title='timeout' data-ref="7timeout">timeout</span>)
                <b>return</b> <b>false</b>;

            <i>// locked for either read or write, assign a d_ptr and wait.</i>
            <em>auto</em> <dfn class="local col9 decl" id="9val" title='val' data-type='QReadWriteLockPrivate *' data-ref="9val">val</dfn> = <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate8allocateEv" title='QReadWriteLockPrivate::allocate' data-ref="_ZN21QReadWriteLockPrivate8allocateEv" data-proj="qtbase">allocate</a>();
            <b>if</b> (<span class="local col8 ref" title='d' data-ref="8d">d</span> == <span class="tu ref" title='dummyLockedForWrite' data-use='r' data-ref="_ZL19dummyLockedForWrite">dummyLockedForWrite</span>)
                <span class="local col9 ref" title='val' data-ref="9val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a> = <var>1</var>;
            <b>else</b>
                <span class="local col9 ref" title='val' data-ref="9val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::readerCount" title='QReadWriteLockPrivate::readerCount' data-ref="QReadWriteLockPrivate::readerCount" data-proj="qtbase">readerCount</a> = (<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col8 ref" title='d' data-ref="8d">d</span>) &gt;&gt; <var>4</var>) + <var>1</var>;
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetOrderedEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetOrdered' data-ref="_ZN19QBasicAtomicPointer17testAndSetOrderedEPT_S1_RS1_" data-proj="qtbase">testAndSetOrdered</a>(<span class="local col8 ref" title='d' data-ref="8d">d</span>, <span class="local col9 ref" title='val' data-ref="9val">val</span>, <span class='refarg'><span class="local col8 ref" title='d' data-ref="8d">d</span></span>)) {
                <span class="local col9 ref" title='val' data-ref="9val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a> = <span class="local col9 ref" title='val' data-ref="9val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::readerCount" title='QReadWriteLockPrivate::readerCount' data-ref="QReadWriteLockPrivate::readerCount" data-proj="qtbase">readerCount</a> = <var>0</var>;
                <span class="local col9 ref" title='val' data-ref="9val">val</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate7releaseEv" title='QReadWriteLockPrivate::release' data-ref="_ZN21QReadWriteLockPrivate7releaseEv" data-proj="qtbase">release</a>();
                <b>continue</b>;
            }
            <span class="local col8 ref" title='d' data-ref="8d">d</span> = <span class="local col9 ref" title='val' data-ref="9val">val</span>;
        }
        <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(!isUncontendedLocked(d))) ? qt_assert(&quot;!isUncontendedLocked(d)&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,110) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(!<span class="ref" title='isUncontendedLocked' data-ref="_Z19isUncontendedLockedPK21QReadWriteLockPrivate">isUncontendedLocked</span>(<span class="local col8 ref" title='d' data-ref="8d">d</span>));
        <i>// d is an actual pointer;</i>

        <b>if</b> (<span class="local col8 ref" title='d' data-ref="8d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::recursive" title='QReadWriteLockPrivate::recursive' data-ref="QReadWriteLockPrivate::recursive" data-proj="qtbase">recursive</a>)
            <b>return</b> <span class="local col8 ref" title='d' data-ref="8d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate21recursiveLockForWriteEi" title='QReadWriteLockPrivate::recursiveLockForWrite' data-ref="_ZN21QReadWriteLockPrivate21recursiveLockForWriteEi" data-proj="qtbase">recursiveLockForWrite</a>(<span class="local col7 ref" title='timeout' data-ref="7timeout">timeout</span>);

        <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#QMutexLocker" title='QMutexLocker' data-ref="QMutexLocker" data-proj="qtbase">QMutexLocker</a> <dfn class="local col0 decl" id="10lock" title='lock' data-type='QMutexLocker' data-ref="10lock">lock</dfn><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLockerC1EP11QBasicMutex" title='QMutexLocker::QMutexLocker' data-ref="_ZN12QMutexLockerC1EP11QBasicMutex" data-proj="qtbase">(</a>&amp;<span class="local col8 ref" title='d' data-ref="8d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::mutex" title='QReadWriteLockPrivate::mutex' data-ref="QReadWriteLockPrivate::mutex" data-proj="qtbase">mutex</a>);
        <b>if</b> (<span class="local col8 ref" title='d' data-ref="8d">d</span> != <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZNK19QBasicAtomicPointer4loadEv" title='QBasicAtomicPointer::load' data-ref="_ZNK19QBasicAtomicPointer4loadEv" data-proj="qtbase">load</a>()) {
            <i>// The mutex was unlocked before we had time to lock the mutex.</i>
<i>            // We are holding to a mutex within a QReadWriteLockPrivate that is already released</i>
<i>            // (or even is already re-used) but that's ok because the QFreeList never frees them.</i>
            <span class="local col8 ref" title='d' data-ref="8d">d</span> = <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZNK19QBasicAtomicPointer11loadAcquireEv" title='QBasicAtomicPointer::loadAcquire' data-ref="_ZNK19QBasicAtomicPointer11loadAcquireEv" data-proj="qtbase">loadAcquire</a>();
            <b>continue</b>;
        }
        <b>return</b> <span class="local col8 ref" title='d' data-ref="8d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate12lockForWriteEi" title='QReadWriteLockPrivate::lockForWrite' data-ref="_ZN21QReadWriteLockPrivate12lockForWriteEi" data-proj="qtbase">lockForWrite</a>(<span class="local col7 ref" title='timeout' data-ref="7timeout">timeout</span>);
    }
}
</pre>

<h2 id="unlock"><code>unlock</code></h2>

<p>The API has a single <code>unlock</code> for both read and write so we don't know if we are unlocking from reading
or writing. Fortunately, we can know that with the state encoded in the lower bits.
If we were locked for read, we need to decrease the reader count, or set the state to <code>0x0</code> if we are the last one.
If we were locked for write we need to set the state to <code>0x0</code>.
If there is a <code>QReadWriteLockPrivate</code>, we need to update the data there, and possibly wake up the blocked threads.</p>

<pre class="code"><em>void</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock" title='QReadWriteLock' data-ref="QReadWriteLock" data-proj="qtbase">QReadWriteLock</a>::<dfn class="decl def" id="_ZN14QReadWriteLock6unlockEv" title='QReadWriteLock::unlock' data-ref="_ZN14QReadWriteLock6unlockEv">unlock</dfn>()
{
    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *<dfn class="local col1 decl" id="11d" title='d' data-type='QReadWriteLockPrivate *' data-ref="11d">d</dfn> = <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZNK19QBasicAtomicPointer4loadEv" title='QBasicAtomicPointer::load' data-ref="_ZNK19QBasicAtomicPointer4loadEv" data-proj="qtbase">load</a>();
    <b>while</b> (<b>true</b>) {
        <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#731" title="((!(d)) ? qt_assert_x(&quot;QReadWriteLock::unlock()&quot;, &quot;Cannot unlock an unlocked lock&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,134) : qt_noop())" data-ref="_M/Q_ASSERT_X" data-proj="qtbase">Q_ASSERT_X</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>, <q>"QReadWriteLock::unlock()"</q>, <q>"Cannot unlock an unlocked lock"</q>);

        <i>// Fast case: no contention: (no waiters, no other readers)</i>
        <b>if</b> (<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>) &lt;= <var>2</var>) { <i>// 1 or 2 (StateLockedForRead or StateLockedForWrite)</i>
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetReleaseEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetRelease' data-ref="_ZN19QBasicAtomicPointer17testAndSetReleaseEPT_S1_RS1_" data-proj="qtbase">testAndSetRelease</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>, <b>nullptr</b>, <span class='refarg'><span class="local col1 ref" title='d' data-ref="11d">d</span></span>))
                <b>continue</b>;
            <b>return</b>;
        }

        <b>if</b> ((<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>) &amp; <span class="enum" title='StateMask' data-ref="StateMask">StateMask</span>) == <span class="enum" title='StateLockedForRead' data-ref="StateLockedForRead">StateLockedForRead</span>) {
            <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(quintptr(d) &gt; (1U&lt;&lt;4))) ? qt_assert(&quot;quintptr(d) &gt; (1U&lt;&lt;4)&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,144) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>) &gt; (<var>1U</var>&lt;&lt;<var>4</var>)); <i>//otherwise that would be the fast case</i>
            <i>// Just decrease the reader's count.</i>
            <em>auto</em> <dfn class="local col2 decl" id="12val" title='val' data-type='QReadWriteLockPrivate *' data-ref="12val">val</dfn> = <b>reinterpret_cast</b>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate" title='QReadWriteLockPrivate' data-ref="QReadWriteLockPrivate" data-proj="qtbase">QReadWriteLockPrivate</a> *&gt;(<a class="typedef" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#quintptr" title='quintptr' data-type='QIntegerForSizeof&lt;void *&gt;::Unsigned' data-ref="quintptr" data-proj="qtbase">quintptr</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>) - (<var>1U</var>&lt;&lt;<var>4</var>));
            <b>if</b> (!<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer17testAndSetReleaseEPT_S1_RS1_" title='QBasicAtomicPointer::testAndSetRelease' data-ref="_ZN19QBasicAtomicPointer17testAndSetReleaseEPT_S1_RS1_" data-proj="qtbase">testAndSetRelease</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>, <span class="local col2 ref" title='val' data-ref="12val">val</span>, <span class='refarg'><span class="local col1 ref" title='d' data-ref="11d">d</span></span>))
                <b>continue</b>;
            <b>return</b>;
        }

        <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(!isUncontendedLocked(d))) ? qt_assert(&quot;!isUncontendedLocked(d)&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,152) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(!<span class="ref" title='isUncontendedLocked' data-ref="_Z19isUncontendedLockedPK21QReadWriteLockPrivate">isUncontendedLocked</span>(<span class="local col1 ref" title='d' data-ref="11d">d</span>));

        <b>if</b> (<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::recursive" title='QReadWriteLockPrivate::recursive' data-ref="QReadWriteLockPrivate::recursive" data-proj="qtbase">recursive</a>) {
            <span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate15recursiveUnlockEv" title='QReadWriteLockPrivate::recursiveUnlock' data-ref="_ZN21QReadWriteLockPrivate15recursiveUnlockEv" data-proj="qtbase">recursiveUnlock</a>();
            <b>return</b>;
        }

        <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#QMutexLocker" title='QMutexLocker' data-ref="QMutexLocker" data-proj="qtbase">QMutexLocker</a> <dfn class="local col3 decl" id="13locker" title='locker' data-type='QMutexLocker' data-ref="13locker">locker</dfn><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLockerC1EP11QBasicMutex" title='QMutexLocker::QMutexLocker' data-ref="_ZN12QMutexLockerC1EP11QBasicMutex" data-proj="qtbase">(</a>&amp;<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::mutex" title='QReadWriteLockPrivate::mutex' data-ref="QReadWriteLockPrivate::mutex" data-proj="qtbase">mutex</a>);
        <b>if</b> (<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a>) {
            <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(d-&gt;writerCount == 1)) ? qt_assert(&quot;d-&gt;writerCount == 1&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,161) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a> == <var>1</var>);
            <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(d-&gt;readerCount == 0)) ? qt_assert(&quot;d-&gt;readerCount == 0&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,162) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::readerCount" title='QReadWriteLockPrivate::readerCount' data-ref="QReadWriteLockPrivate::readerCount" data-proj="qtbase">readerCount</a> == <var>0</var>);
            <span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::writerCount" title='QReadWriteLockPrivate::writerCount' data-ref="QReadWriteLockPrivate::writerCount" data-proj="qtbase">writerCount</a> = <var>0</var>;
        } <b>else</b> {
            <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(d-&gt;readerCount &gt; 0)) ? qt_assert(&quot;d-&gt;readerCount &gt; 0&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,165) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::readerCount" title='QReadWriteLockPrivate::readerCount' data-ref="QReadWriteLockPrivate::readerCount" data-proj="qtbase">readerCount</a> &gt; <var>0</var>);
            <span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::readerCount" title='QReadWriteLockPrivate::readerCount' data-ref="QReadWriteLockPrivate::readerCount" data-proj="qtbase">readerCount</a>--;
            <b>if</b> (<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::readerCount" title='QReadWriteLockPrivate::readerCount' data-ref="QReadWriteLockPrivate::readerCount" data-proj="qtbase">readerCount</a> &gt; <var>0</var>)
                <b>return</b>;
        }

        <b>if</b> (<span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::waitingReaders" title='QReadWriteLockPrivate::waitingReaders' data-ref="QReadWriteLockPrivate::waitingReaders" data-proj="qtbase">waitingReaders</a> || <span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#QReadWriteLockPrivate::waitingWriters" title='QReadWriteLockPrivate::waitingWriters' data-ref="QReadWriteLockPrivate::waitingWriters" data-proj="qtbase">waitingWriters</a>) {
            <span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate6unlockEv" title='QReadWriteLockPrivate::unlock' data-ref="_ZN21QReadWriteLockPrivate6unlockEv" data-proj="qtbase">unlock</a>();
        } <b>else</b> {
            <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#714" title="((!(d_ptr.load() == d)) ? qt_assert(&quot;d_ptr.load() == d&quot;,&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/qreadwritelock-gets-faster-in-qt57.data/qreadwritelock.cpp&quot;,174) : qt_noop())" data-ref="_M/Q_ASSERT" data-proj="qtbase">Q_ASSERT</a>(<a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZNK19QBasicAtomicPointer4loadEv" title='QBasicAtomicPointer::load' data-ref="_ZNK19QBasicAtomicPointer4loadEv" data-proj="qtbase">load</a>() == <span class="local col1 ref" title='d' data-ref="11d">d</span>); <i>// should not change when we still hold the mutex</i>
            <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock.h.html#QReadWriteLock::d_ptr" title='QReadWriteLock::d_ptr' data-ref="QReadWriteLock::d_ptr" data-proj="qtbase">d_ptr</a>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qbasicatomic.h.html#_ZN19QBasicAtomicPointer12storeReleaseEPT_" title='QBasicAtomicPointer::storeRelease' data-ref="_ZN19QBasicAtomicPointer12storeReleaseEPT_" data-proj="qtbase">storeRelease</a>(<b>nullptr</b>);
            <span class="local col1 ref" title='d' data-ref="11d">d</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qreadwritelock_p.h.html#_ZN21QReadWriteLockPrivate7releaseEv" title='QReadWriteLockPrivate::release' data-ref="_ZN21QReadWriteLockPrivate7releaseEv" data-proj="qtbase">release</a>();
        }
        <b>return</b>;
    }
}
</pre>

<h2 id="unlock">Benchmarks</h2>

<p>Here is the benchmark that was run: <a href="https://codereview.qt-project.org/167113/">https://codereview.qt-project.org/167113/</a>.
The benchmark was run with Qt 5.6.1, GCC 6.1.1.
What I call Qt 5.7 bellow is in fact Qt 5.6 + the QReadWriteLock patch so it only compares this patch.</p>

<h3>Uncontended</h3>

<p>This benchmark compares different types of lock by having a single thread running in a
loop 1000000 times, locking and unlocking the mutex and doing nothing else.</p>

<table>
<tr><td>QReadWriteLock (Qt 5.6)</td><td>38 ms</td><td style="color:red"   >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;</td></tr>
<tr><td>QReadWriteLock (Qt 5.7)</td><td>18 ms</td><td style="color:green" >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;</td></tr>
<tr><td>QMutex</td>                 <td>16 ms</td><td style="color:blue"  >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;</td></tr>
<tr><td>std::mutex</td>             <td>18 ms</td><td style="color:pink"  >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;</td></tr>
<tr><td>std::shared_timed_mutex</td><td>33 ms</td><td style="color:orange">&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9612;</td></tr>
</table>

<h3>Contented Reads</h3>

<p>This benchmark runs as much threads as logical cores (4 in my cases). Each thread will lock and unlock the
same mutex 1000000 times. We do a small amount of work inside and outside the lock. If no other work
was done at all and the threads were only locking and unlocking,
we would have a huge pressure on the mutex but this would not be a fair benchmark. So this benchmark
does a hash lookup inside the lock and a string allocation outside of the lock. The more work is done
inside the lock, the more we disadvantage QMutex compared to QReadWriteLock because threads would
be blocked for longer time.</p>

<table>
<tr><td>QReadWriteLock (Qt 5.6)</td><td>812 ms</td><td style="color:red"   >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9613;</td></tr>
<tr><td>QReadWriteLock (Qt 5.7)</td><td>285 ms</td><td style="color:green" >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9615;</td></tr>
<tr><td>QMutex</td>                 <td>398 ms</td><td style="color:blue"  >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;</td></tr>
<tr><td>std::mutex</td>             <td>489 ms</td><td style="color:pink"  >&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9614;</td></tr>
<tr><td>std::shared_timed_mutex</td><td>811 ms</td><td style="color:orange">&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9614;</td></tr>
</table>


<h2 id="futex">Futex Version</h2>

<p>On platforms that have <a href="https://en.wikipedia.org/wiki/Futex">futexes</a>,
QMutex does not even need a QMutexPrivate, it uses the futexes to hold the
lock. Similarly, we could do the same with QReadWriteLock.
I <a href= "https://codereview.qt-project.org/145144">made an implementation of
QReadWriteLock using futex</a> (in fact I made it first before the generic version).
But it is not in Qt 5.7 and is not yet merged in Qt, perhaps for a future version if I get the
motivation and time to get it merged.</p>

<h2 id="faster">Could we get even faster?</h2>

<p>As always, nothing is perfect and there is always still room for improvement.
A flaw of this implementation is that all the readers still need to perform an atomic write at the same memory location
(in order to increment the reader's count). This causes contention if there are many reader threads.
For cache performance, we would no want that the readers write to the same memory
location. Such implementations are possible and would make the contended case faster, but then would
take more memory and might be slower for the non-contended case.
</p>


<h2 id="conclusion">Conclusion</h2>

<p>These benchmarks shows the huge improvement in QReadWriteLock in Qt 5.7.
The Qt classes have nothing to envy to their libstdc++ implementation.
<code>std::shared_timed_mutex</code> which would be the standard equivalent of a QReadWriteLock
is surprisingly slow. (I <a href="https://sourceware.org/ml/libc-alpha/2016-07/msg00636.html">
heard rumors</a> that it might get better.)<br/>
It is optimized for the usual case of Qt with relatively low contention. It is taking a very small amount of memory and makes it a pretty decent
implementation of a read write lock. </p>
<p>In summary, you can now use QReadWriteLock as soon as there are many reads and seldom writes.
This is only about non recursive mutex. Recursive mutex are always slower and should be avoided.
Not only because they are slower, but it is also harder to reason about them.</p>




]]></description></item>
<item><title>QIcon::fromTheme uses GTK+'s icon cache in Qt 5.7</title><link>https://woboq.com/blog/qicon-reads-gtk-icon-cache-in-qt57.html</link><guid>http://woboq.com/blog/qicon-reads-gtk-icon-cache-in-qt57.html</guid><pubDate>Thu, 16 Jun 2016 10:31:27 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>
When you pass a name to 
<a href="https://code.woboq.org/qt5/qtbase/src/gui/image/qicon.cpp.html#_ZN5QIcon9fromThemeERK7QString">
            <code>QIcon::fromTheme</code>
        </a>,
Qt needs to look up in the different folders
in order to know which theme contains the given icon and at which size. This might mean a lot
disk access needs to be done only in order to find out if the file exists. Applications such as 
<a href="https://userbase.kde.org/KMail">KMail</a> can have
hundreds of icons for each of their menu actions.
<br/>In the KF5 port of KMail, <b>30% of its start-up time</b> was spent loading those icons.
</p>
    <p>
With Qt 5.7, the GTK+ icon cache will be used to speedup the
loading of icons.
</p>
</div>
<h2>Freedesktop icon themes</h2>
<p>
    <a href="https://code.woboq.org/qt5/qtbase/src/gui/image/qicon.cpp.html#_ZN5QIcon9fromThemeERK7QString">
        <code>QIcon::fromTheme</code>
    </a> loads an icon as specified by the
<a href="https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html">Freedesktop
Icon Theme Specification</a> and
<a href="https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">
Icon Naming Specification</a>. It specifies the icon themes used by Linux desktops.
In summary, an icon theme consists of many folders containing the icons in PNG or SVG format.
Each folder contains the icon for a particular size and type. The type might be one of
"mimetypes", "actions", "apps". Size are usually all the common sizes. This represents quite a lot
of directories per theme. On my computer, Gnome's default theme has 106 folders; the Oxygen theme has 166;
Breeze has 56; hicolor has 483.<br/>
A theme can also specify one or several fallback themes. Icons which cannot be found in a given theme
need to be looked up in the fallback themes until an icon is found. The last resort fallback theme
is always "hicolor".</p>
<p>Icon names can contains dashes (<code>-</code>). The dash is used to separate levels of specificity.
For example, if the name to look up is "input-mouse-usb", and that this icon does not exist in the theme,
"input-mouse" will be looked up instead, until an icon is found.</p>
<center>
    <img alt="An icon theme" src="https://woboq.com/blog/qicon-reads-gtk-icon-cache-in-qt57/icons_preview.png"/>
</center>
<p>The nature of these themes and the way icon are looked up implies that the icon engine needs to look at
many directories for the existence of files. This is especially true for filenames with many dashes, that might not
exist at all. This implies a lot of
<code>stat()</code> calls on the hard drive.</p>
<h2>Icon Theme Cache</h2>
<p>For the above reasons, desktop environments have been using caches to speed up icon loading.
In KDE4, KDE's KIconLoader used a shared memory mapped pixmap cache, where the
loaded icon data was shared across processes
(<a href="https://www.purinchu.net/wp/2010/04/25/implementing-a-shared-cache-part-1/">KPixmapCache</a>).
When an application requested an icon of a given size, the cache was queried whether this icon for this size is
available. This gave good result at the time in KDE applications. However, this can't be used by pure Qt
applications. When running the KDE's Plasma desktop, the platform theme integration plugin can use 
KIconLoader to load
icons which only works when running on Plasma. This caching is anyway not working well with
<a href="https://code.woboq.org/qt5/qtbase/src/gui/image/qicon.cpp.html#_ZN5QIcon9fromThemeERK7QString">
        <code>QIcon::fromTheme</code>
    </a>
because we need to know if a QIcon is null or not, and this forces a lookup regardless of the cache.</p>
<p>GTK+ also speeds up the icon lookup using a cache. They have a tool (<a href="https://developer.gnome.org/gtk3/stable/gtk-update-icon-cache.html">
        <code>gtk-update-icon-cache</code>
    </a>)
that generates a <code>icon-theme.cache</code> file for each theme. This file contains a hash table for fast lookup to
know if an icon is in the theme or not and at which size. 
The icon cache is system-wide, and usually generated by the distribution's package manager.</p>
<center>
    <img alt="icon-theme.cache" src="https://woboq.com/blog/qicon-reads-gtk-icon-cache-in-qt57/icon-theme-cache.png"/>
</center>
<h2>Qt can now use GTK+ cache files</h2>
<p>The question I asked myself is how to improve the performance of
	<a href="https://code.woboq.org/qt5/qtbase/src/gui/image/qicon.cpp.html#_ZN5QIcon9fromThemeERK7QString">
        <code>QIcon::fromTheme</code>
    </a>
	?
It is clear that we need to use a cache. Should we try to use the KDE pixmap cache?
I decided against the KDE pixmap cache because the cache is, in my opinion, at the wrong level.
We don't want to cache the icon data, we want to cache a way to get from the icon name to the right file.
The cache is also storing some other assets, we might get cache misses more often than we should.
</p>
<p>The GTK+ cache is solving the right problem: It is system wide and most Linux distributions
already generate it. So I thought, we should just re-use the same cache.</p>
<p>I went ahead and "reverse engineered" the GTK+ icon cache format in order to
<a href="https://codereview.qt-project.org/125379">implement it in Qt</a>. Having GTK+s'
<a href="https://code.woboq.org/gtk/gtk/gtk/updateiconcache.c.html">source code available to browse</a> clearly helped.
</p>
<p/>
<h3>Does that mean that Qt now depends on GTK+?</h3>
<p>No, the use of this cache is optional. If the cache is not found or out of date, Qt will ignore the
cache and do the full look-ups as before.</p>
<h3>How do I make sure the cache is used?</h3>
<p>Every time you install an application that adds or removes icons from one of the themes, the
cache needs to be updated. Qt looks at the modification time of the directories, if any directory is
newer than the cache, the cache will not be used. You need to run <code>gtk-update-icon-cache</code>
after installing new icons, but most distributions take care of this for you.</p>
<h3>How do I update the cache?</h3>
<p>Run this command for every theme:</p>
<pre>gtk-update-icon-cache /usr/share/icons/&lt;theme-name&gt; -i -t -f</pre>
<p>
    <code>-i</code> makes it not include the image data into the cache (Qt does not
make use of that)</p>
<h2>Conclusion</h2>
<p>Thank you for reading so far. The summary is that Qt 5.7 will automatically use the GTK+ icon caches.
<a href="https://code.woboq.org/qt5/qtbase/src/gui/image/qiconloader.cpp.html#QIconCacheGtkReader">Browse the source of QIconCacheGtkReader</a>
if you are interrested.</p>
]]></description></item>
<item><title>Verdigris: Qt without moc</title><link>https://woboq.com/blog/verdigris-qt-without-moc.html</link><guid>http://woboq.com/blog/verdigris-qt-without-moc.html</guid><pubDate>Wed, 25 May 2016 11:08:45 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>
        <a href="https://code.woboq.org/woboq/verdigris">Verdigris</a> is a header-only library that can be
used with Qt. It uses macros to create a QMetaObject that is binary compatible with Qt's own
QMetaObject without requiring moc.
In other words, you can use Verdigris macros in your Qt or QML application instead of some of the Qt
macros and then you do not need to run moc.
</p>
</div>
<img alt="A verdigris statue" src="https://woboq.com/blog/verdigris-qt-without-moc/verdigris-liberty.jpeg" style="float:right; margin:1ex"/>
<p>
    <b>TL;DR:</b>
    <a href="https://github.com/woboq/verdigris">Github repository</a> - <a href="https://code.woboq.org/woboq/verdigris/tutorial/tutorial.cpp.html">Tutorial</a>
</p>
<h2>Introduction</h2>
<p>
    <a href="http://www.copperspice.com/">CopperSpice</a> is a fork of Qt 4. Its main <i>raison d'être</i> is
to get rid of moc because they consider it bad enough
(<a href="https://woboq.com/blog/moc-myths.html">IMHO wrongly</a>).
To do so, they replaced the user-friendly Qt macro with some less friendly macros.
</p>
<p>However, CopperSpice is a whole fork of Qt, meaning they are maintaining the whole library. This
also means they are recreating an ecosystem from scratch.
If they had made it binary compatible, then they could have removed moc without the need to maintain the
full Qt library. This is what Verdigris is.
</p>
<p>Another problem of CopperSpice compared to Qt is that it generates and registers the QMetaObject
at run-time when loading the application. Meanwhile, Verdigris uses <code>constexpr</code> to <b>generate
the QMetaObject at compile time</b>. For this reason, binaries using CopperSpice are much bigger
than binaries using Qt (moc or Vedrigris), and take also more time to load because of the massive
amount of relocations.</p>
<h2>Previous work</h2>
<p>Most of the ground work is based on the code I wrote already in my previous blog post: <a href="https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html">Can Qt's moc be replaced by C++ reflection?</a>.  In that blog post,
I was trying to see if reflection could help replace moc, while keeping the convenience of the current Qt macros.
The goal was was to influence source compatibility as little as possible.</p>
<p>CopperSpice decided to use different macros that are less convenient.
The macros of Verdigris are based or improved upon the CopperSpice ones.</p>
<h2>Differences between CopperSpice and Verdigris</h2>
<style>td.bad{background-color: #faa} td.good{background-color: #afa}
.comparison_table { border-collapse:collapse }
.comparison_table code { font-size: smaller }
.comparison_table td, .comparison_table th { padding:.2ex; border: 1px solid gray;  } </style>
<table class="comparison_table">
    <tr>
        <td/>
        <th>Pure Qt</th>
        <th>Verdigris</th>
        <th>CopperSpice</th>
    </tr>
    <tr>
        <th>Requires moc</th>
        <td class="bad">Yes</td>
        <td class="good">No</td>
        <td class="good">No</td>
    </tr>
    <tr>
        <th>Usage</th>
        <td class="good">Convenient macros</td>
        <td class="bad">Ugly macros</td>
        <td class="bad">Ugly macros</td>
    </tr>
    <tr>
        <th>Qt Compatibility</th>
        <td class="good">Obviously</td>
        <td class="good">Yes</td>
        <td class="bad">No</td>
    </tr>
    <tr>
        <th>MetaObject generation</th>
        <td class="good">Compile Time <br/>(By moc)</td>
        <td class="good">Compile Time <br/>(By the compiler)</td>
        <td class="bad">Run-time<br/>(At load time)</td>
    </tr>
    <tr>
        <th>MetaObject location</th>
        <td class="good">Shared read-only memory</td>
        <td class="good">Shared read-only memory</td>
        <td class="bad">Heap</td>
    </tr>
</table>
<h3>Macros</h3>
<table class="comparison_table">
    <tr>
        <th>Qt</th>
        <th>Verdigris</th>
        <th>CopperSpice</th>
    </tr>
    <tr>
        <td>
            <code>Q_OBJECT</code>
        </td>
        <td>
            <code>W_OBJECT(MyClass)<br/>...<br/>W_OBJECT_IMPL(MyClass)</code>
        </td>
        <td>
            <code>CS_OBJECT(MyClass)</code>
        </td>
    </tr>
    <tr>
        <td>
            <code>public slots:<br/>   void mySlot(int x);</code>
        </td>
        <td>
            <code>void mySlot(int x)<span style="color:#800; font-weight: bold">;</span>
                <br/>W_SLOT(mySlot)</code>
        </td>
        <td>
            <code>CS_SLOT_1(Public, void mySlot(int x))<br/>CS_SLOT_2(mySlot)</code>
        </td>
    </tr>
    <tr>
        <td>
            <code>signals:<br/>   void mySignal(int x);</code>
        </td>
        <td>
            <code>void mySignal(int x)<br/>W_SIGNAL(mySignal,x)</code>
        </td>
        <td>
            <code>CS_SIGNAL_1(Public, void mySignal(int x))<br/>CS_SIGNAL_2(mySignal,x)</code>
        </td>
    </tr>
    <tr>
        <td>
            <code>Q_PROPERTY(int myProperty
       <br/>   WRITE setProp<br/>   READ getProp
       <br/>   NOTIFY propChanged)</code>
        </td>
        <td>
            <code>W_PROPERTY(int<span style="color:#800; font-weight: bold">,</span> myProperty
       <br/>   WRITE setProp<br/>   READ getProp
       <br/>   NOTIFY propChanged)</code>
        </td>
        <td>
            <code>CS_PROPERTY_READ(myProperty, getProp)<br/>CS_PROPERTY_WRITE(myProperty, setProp)
       <br/>CS_PROPERTY_NOTIFY(myProperty, propertyChanged)</code>
        </td>
    </tr>
    <tr>
        <td>
            <code>private slots:<br/>   myPrivateSlot(int x);</code>
        </td>
        <td>
            <code>void myPrivateSlot(int x); <br/>W_SLOT(myPrivateSlot, (int), W_Access::Private)</code>
        </td>
        <td>
            <code>CS_SLOT_1(Private, void myPrivateSlot(int x))<br/>CS_SLOT_OVERLOAD(myPrivateSlot,(int))</code>
        </td>
    </tr>
</table>
<p>
The first difference of Verdigris is the <code>
        <a href="https://code.woboq.org/woboq/verdigris/src/wobjectimpl.h.html#_M/W_OBJECT_IMPL">W_OBJECT_IMPL</a>
    </code> macro that needs to be written in the .cpp file.
This is one of the few points for which Verdigris is less convenient than CopperSpice as they do not need
this macro.
</p>
<p>
    <s>In CopperSpice, you cannot define a slot inline in the class definition. You don't have this restriction
with Verdigris.</s>(Update: I was told it is possible with CopperSpice by putting the body within the <code>CS_SLOT_1</code> macro)</p>
<p>Both CopperSpice and Verdigirs can have templated QObject class or nested QObject.
Verdigris cannot, however, have function local QObjects (because of the static member
<code>staticMetaObject</code>) and local classes cannot have static members.</p>
<p>From an implementation point of view, CopperSpice macros use <code>__LINE__</code>
to build an unique identifier,
which means that two macros cannot be put on the same lines. So you can't declare several slots in a line
or declare properties or signals/slots from a macro. (which ironically is one of the "problems" they raised about Qt4's moc).
Verdigris's macros do not have this problem.</p>
<h2>Tutorial</h2>
<p>The best way to learn about how to use Verdigris is to <a href="https://code.woboq.org/woboq/verdigris/tutorial/tutorial.cpp.html">read through the tutorial</a> (conveniently brought to you through our <a href="https://woboq.com/codebrowser.html">Code Browser</a>).</p>
<h2>Benchmarks</h2>
<p>All benchmarks were done with CopperSpice 1.2.2, Qt 5.6.0 or Qt 4.8.3, GCC 6.1</p>
<h3>KitchenSink</h3>
<p>I made the KitchenSink example from CopperSpice compile both with CopperSpice, Qt 5 with moc
or with Verdigris
(<a href="https://github.com/woboq/verdigris/tree/master/benchmarks/KitchenSink">patch</a>).
This table show the amount in minutes:seconds taken by <code>make -j1</code>
</p>
<table class="comparison_table">
    <tr>
        <th/>
        <th>Qt 5 (moc)</th>
        <th>Verdigris</th>
        <th>CopperSpice</th>
    </tr>
    <tr>
        <th>Compilation time</th>
        <td>1:57</td>
        <td>1:26</td>
        <td>16:43</td>
    </tr>
    <tr>
        <th>Binary size</th>
        <td>1.32 MB</td>
        <td>1.36 MB</td>
        <td>115 MB</td>
    </tr>
</table>
<p>I was surprised to see that Verdigris compiles faster than using moc.
The cost of compiling the generated code in a separate compilation unit is what makes it slower, and
including the generated file is a common way to speed up the compilation (which was not done in this case).
CopperSpice is probably so slow because each translation unit needs to re-generate the code that generates
the meta object for all the included objects  (including the headers from CsCore, CsGui, ...).
Verdigris, however, moves most of the slow-to-compile code in a <code>
        <a href="https://code.woboq.org/woboq/verdigris/src/wobjectimpl.h.html#_M/W_OBJECT_IMPL">W_OBJECT_IMPL</a>
    </code> macro in the .cpp code
that is only parsed for the corresponding translation unit.
Still, the tests take a very long time to compile, that's because they
have many objects with lots of special methods/properties and we are probably hitting non-linear
algorithms within the compiler.
</p>
<h3>Library loading time</h3>
<p>Any program that links to a C++ library has some overhead because of the relocations and the init section.
This benchmark simply links an <a href="https://code.woboq.org/woboq/verdigris/benchmarks/startup/main.cpp.html">almost empty program</a> with the libraries, and compute
the time it takes to run.
</p>
<table class="comparison_table">
    <tr>
        <th>CopperSpice<br/>(CsCore, CsGui)</th>
        <th>Qt 4<br/>(QtCore, QtGui)</th>
        <th>Qt 5<br/>(Qt5Core, Qt5Gui, Qt5Widgets)</th>
    </tr>
    <tr>
        <td>56ms</td>
        <td>16ms</td>
        <td>17ms</td>
    </tr>
</table>
<p>Loading CopperSpice is much slower because all the MetaObjects needs to
be created and the huge amount of relocations.<br/>
Note: Since the program is empty and has no QObject on his own, neither moc nor Verdigris were used.
Qt5 and Qt4 themselves were compiled with moc as usual.
</p>
<h3>Signals/Slots run-time performance</h3>
<p>I built the Qt benchmarks for testing connecting and emitting of Qt signals.
There is no difference between Verdigris or the normal Qt. As expected since
the QMetaObject structure is the same and the moc generated code is equivalent
to the templated code.</p>
<p>CopperSpice is faster for signal emission because they inlined everything including
<code>
        <a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZN11QMetaObject8activateEP7QObjectiiPPv">QMetaObject::activate</a>
    </code>. Something we don't do in Qt because we want to maintain binary
compatibility and inlining everything means we can't change much of the data structures used until
the next major version of Qt. This contributes largely to the code size which is two order
of magnitude more than using Qt.</p>
<h2>Implementations details</h2>
<p>As said previously, most of the constexpr code was based on what I wrote for <a href="https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html">the previous research</a>.
I had to replace <code>std::tuple</code> with another data structure because <code>std::tuple</code>
turned out to be way too slow to compile. The GNU's libstdc++ implementation of <code>std::tuple</code>
does about 16 template recursion per parameter only
to compute the noexpect clause of its copy constructor. Which is quite limiting when the default limit
of template recursion is 256 (so that means maximum 16 types in a tuple). There is also the fact that
the compiler seems to have operation of quadratic complexity depending on the amount of template parameter
or instantiation.  I therefore made my own binary tree structure that can compile
in a reasonable time.  Instead of having  <code>tuple&lt;T1, T2, T3, T4, T5, ....&gt;</code> we have
<code>Node&lt;Node&lt;Node&lt;Leaf&lt;T1&gt;,Leaf&lt;T2&gt;&gt;,Node&lt;Leaf&lt;T3&gt;,Leaf&lt;T4&gt;&gt;&gt;, ...&gt;</code>
</p>
<p>Nonetheless, the whole thing is some pretty heavy advanced template and macro tricks. While working on
it I found and reported or even fixed compiler bugs in clang <a href="http://reviews.llvm.org/D16973">[1]</a>, <a href="http://reviews.llvm.org/D20054">[2]</a>,
<a href="http://reviews.llvm.org/D20511">[3]</a>,
and GCC <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69836">[1]</a>, <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71100">[2]</a>,
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71121">[3]</a>
</p>
<h2>Conclusions</h2>
<p>In conclusion, as CopperSpice has already shown, this shows that moc is not strictly necessary
for Qt features. The trade-off is the simplicity of the macros. The alternative macros from CopperSpice
and Verdigris are less convenient, and force you <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">to repeat yourself</a>. Complex template code can also increase
compilation time even more than the overhead of moc.</p>
<p>On the other hand, we think the approach of CopperSpice was the wrong one. By forking Qt instead
of being compatible with it, they give up on the whole Qt ecosystem, and the small CopperSpice team
will never be able to keep up with the improvements that are made within Qt.
(CopperSpice is a fork of Qt 4, it is way behind what Qt 5 now has)</p>
<p>Verdigris is a header-only library consisting on two headers that can easily be imported in a project
to be used by anyone who has reasons not to use moc. You can get the files from the
<a href="https://github.com/woboq/verdigris">Github repository</a>.</p>
]]></description></item>
<item><title>Moc myths debunked</title><link>https://woboq.com/blog/moc-myths.html</link><guid>http://woboq.com/blog/moc-myths.html</guid><pubDate>Mon, 22 Feb 2016 07:58:04 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>I have often read, on various places, criticisms about Qt because of its use of moc.
As the maintainer of moc I thought it would be good to write an article debunking some of the myths.</p>
</div>
<h2>Introduction</h2>
<p>
    <code>moc</code> is a developer tool and is part of the <a href="https://qt.io">Qt library</a>.
Its role is to handle Qt's <em>extension</em> within the C++ code to offer introspection and enable 
reflection for Qt Signals and Slots, and for QML. For a more detailed explanation, read my previous article
<a href="https://woboq.com/blog/how-qt-signals-slots-work.html">How Qt Signals and Slots work</a>.</p>
<p>The use of moc is often one of the criticisms given to Qt.
It even led to forks of Qt, such as <a href="http://www.copperspice.com/">CopperSpice</a>.
However, most of the so-called drawbacks are not completely founded.
</p>
<h2>Myths</h2>
<h3>Moc rewrites your code before passing it to the compiler</h3>
<p>This is often misunderstood, moc does not modify or rewrite your code. It simply parses part
of your code to generate additional C++ files which are then usually compiled independently.<br/>
This does not make a big difference overall, but is still a technical misconception.</p>
<p>The moc is just generating some boilerplate code that would be fastidious to write otherwise.
If you were masochist, you would write all the introspection tables and implementation of signals
by hand. It is so much more convenient to have this auto generated.</p>
<h3>When writing Qt code, you are not writing real C++ <a href="#note_1">¹</a>
</h3>
<p>I have read this many times, but this is simply false.
The macros understood by moc to annotate the code are simply standard C++ macros defined in a header.
They should be understood by any tool that can understand C++.
When you write <code>Q_OBJECT</code>, it is a standard C++ macro that <a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_M/Q_OBJECT">expands to some
function declarations</a>.
When you write <code>signals:</code> it is just a macro that <a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_M/signals">expands to</a>
    <code>public:</code>. Many other Qt macros expand to nothing.
The moc will then locate these macros and generate the code of the signal emitter functions,
together with some additional introspection tables.</p>
<p>The fact that your code is also read by another tool than the compiler does not make it less
C++. I've never heard that you are not using vanilla C++ if you use tools like gettext or doxygen,
which will also parse your code to extract some information.</p>
<h3>Moc makes the build process much more complicated <a href="#note_2">²</a>
</h3>
<p>If you are using any mainstream build system, such as CMake or qmake, they will have a native integration of Qt.
Even with a custom build system, we are just talking about invoking one additional command onto your header files.
All the build systems allow this because many projects have some sort of generated code as part of the build.
(Things like yacc/bison, <a href="https://www.gnu.org/software/gperf/">gperf</a>, llvm has <a href="http://llvm.org/docs/TableGen/">TableGen</a>)</p>
<h3>It makes the debugging experience harder</h3>
<p>Since the moc generated code is pure C++, debuggers or other tools have no problems with it.
We try to keep the generated code without warnings or any issues that would trigger static or
dynamic code analyzers.
<br/>
You will sometimes see backtraces containing frames within the moc generated code. In some
rare case you can have errors within the moc generated code, but it is usually straightforward to find their cause.
The moc generated code is human readable for most part. It will also probably be easier to debug
than the infamous compiler error messages you can get while using advanced template code.</p>
<h3>Removing moc improves run time performance <a href="#note_3">³</a>
</h3>
<p>This is a quote from the CopperSpice home page, and is probably their biggest lie.
The moc generated code is carefully crafted to avoid dynamic allocation and reduce relocations.
<br/>
All the moc generated tables go in const arrays that are stored in the shareable read-only data segment.
CopperSpice, on the other hand, registers the QMetaObject data (information about signals, slots
and properties) at run time.</p>
<p>
    <a href="http://milianw.de/">Milian Wolff</a> did some measurements to compare Qt and CopperSpice for his
<a href="https://youtu.be/RXTfC-35Nx8?t=42m26s">CppCon2015 talk</a>.
Here is a screenshot from one of his slides (smaller is better):
</p>
<img src="https://woboq.com/blog/moc-myths/efficiency.png"/>
<p>It is also worth mentioning that Qt code with moc compiles faster than CopperSpice code.</p>
<h2>Outdated Myths</h2>
<p>Some criticisms used to be true, but are long outdated.</p>
<h3>A macro cannot be used to declare a signal, a slot, the base class of an object, or ...
<a href="#note_4">⁴</a>
</h3>
<p>Before Qt5, moc did not expand macros. But since Qt 5.0 moc fully expands macros,
and this is no longer an issue at all.</p>
<h3>Enums and typedefs must be fully qualified for signal and slot parameters</h3>
<p>This is only an issue if you want to use the string-based connection syntax (as this is implemented with a
string comparison).
With the <a href="https://woboq.com/blog/new-signals-slots-syntax-in-qt5.html">Qt5 function pointer syntax</a>,
this is not an issue.
</p>
<h3>Q_PROPERTY does not allow commas in its type <a href="#note_5">⁵</a>
</h3>
<p>
    <code>Q_PROPERTY</code> is a macro with one argument that expands to nothing and is only understood
by moc. But since it is a macro, the comma in  <code>QMap&lt;Foo, Bar&gt;</code> separating
macro arguments is causing a compilation error. When I <a href="https://www.reddit.com/r/programming/comments/3969n6/copperspice_a_modern_c_fork_of_qt/cs0xn3s">saw</a> that CopperSpice used this as an argument
against Qt, I spent five minutes to <a href="http://code.qt.io/cgit/qt/qtbase.git/commit/?id=7f85fb4654f0d6f9058336af53148d81fc700497">fix it</a> using C++11 variadic macros.</p>
<h2>Other criticisms</h2>
<h3>Template, nested, or multiple inherited classes cannot be QObjects</h3>
<p>While true, those are just missing features of QObject, which could be implemented
in moc if we wanted them. The Qt project does not think these features are important.</p>
<p>For example, I <a href="https://codereview.qt-project.org/49864/">implemented support for
templated QObjects in moc</a>, but this was not merged because it did not raise enough interest within the Qt project.</p>
<p>As a side note, <a href="https://github.com/woboq/moc-ng">moc-ng</a> supports template and nested classes.</p>
<p>Multiple inheritance is also something that is in itself controversial. Often considered bad design, it has
been left out of many languages. You can have multiple inheritance with Qt as long as QObject comes first
as base class. This small restriction allows us to make useful optimization. Ever wondered why
<code>qobject_cast</code> is so much faster than <code>dynamic_cast</code>?</p>
<h2>Conclusion</h2>
<p>I believe moc is not a problem.
The API and usability of the Qt meta object macro helps. Compare them to CopperSpice's to see the excessive
boilerplate and user unfriendly macros (not even talking about the loss in performance).
The Qt signals and slots syntax which exists since the 90s is among the things that made Qt so
successful.</p>
<p>You might also be interested to learn about some research projects around moc, like <a href="https://github.com/woboq/moc-ng">moc-ng</a>: a re-implementation of moc using the clang libraries; or this blog
<a href="https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html">research if moc can be replaced by C++ reflection.</a>
    <br/>
    <b>Update:</b> And also <a href="https://woboq.com/blog/verdigris-qt-without-moc.html">Verdigris</a>, a library with macros
to create a QMetaObject without moc.</p>
<div style="font-size:smaller">
    <h4>Footnotes</h4>
    <p>
        <span id="note_1">¹</span>
        <a href="http://stackoverflow.com/questions/1368451/is-qt-classified-as-a-c-library-if-not-a-library-how-would-you-classify-qt">StackOverflow question</a>
        <br/>
        <span id="note_2">²</span>
        <a href="http://programmers.stackexchange.com/questions/88685/why-arent-more-desktop-apps-written-with-qt/88689#88689">StackOverflow answer</a>
        <br/>
        <span id="note_3">³</span>
        <a href="http://www.copperspice.com/">CopperSpice home page</a>
        <br/>
        <span id="note_4">⁴</span>
        <a href="http://www.copperspice.com/docs/cs_overview/moc_limits.html">CopperSpice documentation</a>
        <br/>
        <span id="note_5">⁵</span>
        <a href="http://www.copperspice.com/docs/cs_overview/moc_remove.html">CopperSpice documentation</a>
        <br/>
    </p>
</div>
]]></description></item>
<item><title>How Qt Signals and Slots Work - Part 3 - Queued and Inter Thread Connections</title><link>https://woboq.com/blog/how-qt-signals-slots-work-part3-queuedconnection.html</link><guid>http://woboq.com/blog/how-qt-signals-slots-work-part3-queuedconnection.html</guid><pubDate>Thu, 04 Feb 2016 10:18:17 GMT</pubDate><description><![CDATA[


<div class="intro">
<p>This blog is part of a series of blogs explaining the internals of signals and slots.</p>
<ul><li><a href="https://woboq.com/blog/how-qt-signals-slots-work.html">Part 1 - How Qt Signals and Slots Work</a></li>
    <li><a href="https://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html">Part 2 - Qt 5 new syntax </a></li>
    <li><a href="https://woboq.com/blog/qmetatype-knows-your-types.html">Interlude - QMetatype knows your types</a></li>
    </ul>
</div>

<p>In this article, we will explore the mechanisms powering the Qt queued connections.</p>

<h2>Summary from Part 1</h2>

<p>In the <a href="https://woboq.com/blog/how-qt-signals-slots-work.html">first part</a>, we saw that signals
are just simple functions, whose body is generated by <a href="http://doc.qt.io/qt-5/moc.html">moc</a>. They are just calling <code>QMetaObject::activate</code>, with an array of pointers to arguments on the stack.
Here is the code of a signal, as generated by moc: (from part 1)</p>

<pre class="code"><i>// SIGNAL 0</i>
<em>void</em> <span class="type" title='Counter' data-ref="Counter" >Counter</span>::<dfn class="decl def" id="_ZN7Counter12valueChangedEi" title='Counter::valueChanged' data-ref="_ZN7Counter12valueChangedEi" >valueChanged</dfn>(<em>int</em> <dfn class="local col8 decl" id="18_t1" title='_t1' data-type='int' data-ref="18_t1" >_t1</dfn>)
{
    <em>void</em> *<dfn class="local col9 decl" id="19_a" title='_a' data-type='void *[2]' data-ref="19_a" >_a</dfn>[] = { <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qcompilerdetection.h.html#983" title="nullptr" data-ref="_M/Q_NULLPTR" data-proj="qtbase">Q_NULLPTR</a>, <b>const_cast</b>&lt;<em>void</em>*&gt;(<b>reinterpret_cast</b>&lt;<em>const</em> <em>void</em>*&gt;(&amp;<a class="local col8 ref" href="#18_t1" title='_t1' data-ref="18_t1" ><span class="local col8 ref" title='_t1' data-ref="18_t1" >_t1</span></a>)) };
    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase" >QMetaObject</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZN11QMetaObject8activateEP7QObjectPKS_iPPv" title='QMetaObject::activate' data-ref="_ZN11QMetaObject8activateEP7QObjectPKS_iPPv" data-proj="qtbase" id="_ZN11QMetaObject8activateEP7QObjectPKS_iPPv" >activate</a>(<b>this</b>, &amp;<span class="member" title='Counter::staticMetaObject' data-ref="_ZN7Counter16staticMetaObjectE" id="_ZN7Counter16staticMetaObjectE" >staticMetaObject</span>, <var>0</var>, <span class="local col9 ref" title='_a' data-ref="19_a" >_a</span>);
}
</pre>


<p><a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZN11QMetaObject8activateEP7QObjectiiPPv"><code>QMetaObject::activate</code></a>
will then look in internal data structures to find out what are the slots connected to that signal.
As seen in part 1, for each slot, the following code will be executed:</p>

<pre class="code"><i>// Determine if this connection should be sent immediately or</i>
<i>// put into the event queue</i>
<b>if</b> ((<span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::connectionType" title='QObjectPrivate::Connection::connectionType' data-ref="QObjectPrivate::Connection::connectionType" data-proj="qtbase" id="QObjectPrivate::Connection::connectionType" >connectionType</a> == <span class="namespace">Qt::</span><a class="enum" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qnamespace.h.html#Qt::ConnectionType::AutoConnection" title='Qt::ConnectionType::AutoConnection' data-ref="Qt::ConnectionType::AutoConnection" data-proj="qtbase" " id="Qt::ConnectionType::AutoConnection" >AutoConnection</a> &amp;&amp; !<span class="local col8 ref" title='receiverInSameThread' data-ref="8receiverInSameThread" >receiverInSameThread</span>)
        || (<span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::connectionType" title='QObjectPrivate::Connection::connectionType' data-ref="QObjectPrivate::Connection::connectionType" data-proj="qtbase" id="QObjectPrivate::Connection::connectionType" >connectionType</a> == <span class="namespace">Qt::</span><a class="enum" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qnamespace.h.html#Qt::ConnectionType::QueuedConnection" title='Qt::ConnectionType::QueuedConnection' data-ref="Qt::ConnectionType::QueuedConnection" data-proj="qtbase" id="Qt::ConnectionType::QueuedConnection" >QueuedConnection</a>)) {
    <span class="ref" title='queued_activate' data-ref="_ZL15queued_activateP7QObjectiPN14QObjectPrivate10ConnectionEPPvR12QMutexLocker" >queued_activate</span>(<span class="local col1 ref" title='sender' data-ref="1sender" >sender</span>, <span class="local col5 ref" title='signal_index' data-ref="5signal_index" >signal_index</span>, <span class="local col7 ref" title='c' data-ref="7c" >c</span>, <span class="local col4 ref" title='argv' data-ref="4argv" >argv</span>, <span class="local col9 ref" title='locker' data-ref="9locker" >locker</span>);
    <b>continue</b>;
} <b>else</b> <b>if</b> (<span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::connectionType" title='QObjectPrivate::Connection::connectionType' data-ref="QObjectPrivate::Connection::connectionType" data-proj="qtbase" id="QObjectPrivate::Connection::connectionType" >connectionType</a> == <span class="namespace">Qt::</span><a class="enum" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qnamespace.h.html#Qt::ConnectionType::BlockingQueuedConnection" title='Qt::ConnectionType::BlockingQueuedConnection' data-ref="Qt::ConnectionType::BlockingQueuedConnection" data-proj="qtbase" id="Qt::ConnectionType::BlockingQueuedConnection" >BlockingQueuedConnection</a>) {
    <i>/* ... Skipped ... */</i>
    <b>continue</b>;
}
<i>/* ... DirectConnection: call the slot as seen in Part 1 */</i>
</pre>

<p>So in this blog post we will see what exactly happens in <code>queued_activate</code>
and other parts that were skipped for the <code>BlockingQueuedConnection</code></p>


<h2>Qt Event Loop</h2>

<p>A <code>QueuedConnection</code> will post an event to the event loop to eventually be handled.</p>

<p>When posting an event (in <a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.cpp.html#_ZN16QCoreApplication9postEventEP7QObjectP6QEventi">
<code>QCoreApplication::postEvent</code></a>),
the event will be pushed in a per-thread queue
(<a href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qthread_p.h.html#QThreadData::postEventList"><code>QThreadData::postEventList</code></a>).
The event queued is protected by a mutex, so there is no race conditions when threads
push events to another thread's event queue.</p>
<p>Once the event has been added to the queue, and if the receiver is living in another thread,
we notify the event dispatcher of that thread by calling <code>QAbstractEventDispatcher::wakeUp</code>.
This will wake up the dispatcher if it was sleeping while waiting for more events.
If the receiver is in the same thread, the event will be processed later, as the event loop iterates.</p>

<p>The event will be deleted right after being processed in the thread that processes it. </p>

<p>An event posted using a QueuedConnection is a <code>QMetaCallEvent</code>. When processed, that event will call the slot the same way we call them for direct connections.
All the information (slot to call, parameter values, ...) are stored inside the event.</p>

<h2>Copying the parameters</h2>
 <p>The <code>argv</code> coming from the signal is an array of pointers to the arguments.
 The problem is that these pointers point to the stack of the signal where the arguments are.
 Once the signal returns, they will not be valid anymore.
 So we'll have to copy the parameter values of the function on the heap.
 In order to do that, we just ask QMetaType.

 We have seen in the <a href="https://woboq.com/blog/qmetatype-knows-your-types.html">QMetaType article</a>
 that <code>QMetaType::create</code> has the ability to copy any type knowing it's
 QMetaType ID and a pointer to the type.</p>

 <p>To know the QMetaType ID of a particular parameter, we will look in the QMetaObject, which
 contains the name of all the types. We will then be able to look up the particular type in
 the QMetaType database.</p>

<h2>queued_activate</h2>

<p>We can now put it all together and read through the code of
<a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZL15queued_activateP7QObjectiPN14QObjectPrivate10ConnectionEPPvR12QMutexLocker">queued_activate</a>, which is called by <code>QMetaObject::activate</code> to prepare a <code>Qt::QueuedConnection</code> slot call.
The code showed here has been slightly simplified and commented:</p>

<pre class="code"><em>static</em> <em>void</em> <dfn class="tu decl def" id="_ZL15queued_activateP7QObjectiPN14QObjectPrivate10ConnectionEPPvR12QMutexLocker" title='queued_activate' data-type='void queued_activate(QObject * sender, int signal, QObjectPrivate::Connection * c, void ** argv, QMutexLocker &amp; locker)' data-ref="_ZL15queued_activateP7QObjectiPN14QObjectPrivate10ConnectionEPPvR12QMutexLocker" >queued_activate</dfn>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#QObject" title='QObject' data-ref="QObject" data-proj="qtbase" >QObject</a> *<dfn class="local col2 decl" id="12sender" title='sender' data-type='QObject *' data-ref="12sender" >sender</dfn>, <em>int</em> <dfn class="local col3 decl" id="13signal" title='signal' data-type='int' data-ref="13signal" >signal</dfn>,
                            <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate" title='QObjectPrivate' data-ref="QObjectPrivate" data-proj="qtbase" >QObjectPrivate</a>::<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection" title='QObjectPrivate::Connection' data-ref="QObjectPrivate::Connection" data-proj="qtbase" >Connection</a> *<dfn class="local col4 decl" id="14c" title='c' data-type='QObjectPrivate::Connection *' data-ref="14c" >c</dfn>, <em>void</em> **<dfn class="local col5 decl" id="15argv" title='argv' data-type='void **' data-ref="15argv" >argv</dfn>,
                            <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#QMutexLocker" title='QMutexLocker' data-ref="QMutexLocker" data-proj="qtbase" >QMutexLocker</a> &amp;<dfn class="local col6 decl" id="16locker" title='locker' data-type='QMutexLocker &amp;' data-ref="16locker" >locker</dfn>)
{
  <em>const</em> <em>int</em> *<dfn class="local col7 decl" id="17argumentTypes" title='argumentTypes' data-type='const int *' data-ref="17argumentTypes" >argumentTypes</dfn> = <span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::argumentTypes" title='QObjectPrivate::Connection::argumentTypes' data-ref="QObjectPrivate::Connection::argumentTypes" data-proj="qtbase" id="QObjectPrivate::Connection::argumentTypes" >argumentTypes</a>;
  <i>// c-&gt;argumentTypes is an array of int containing the argument types.</i>
<i>  // It might have been initialized in the connection statement when using the</i>
<i>  // new syntax, but usually it is `nullptr` until the first queued activation</i>
<i>  // of that connection.</i>
<i></i>
<i>  // DIRECT_CONNECTION_ONLY is a dummy int which means that there was an error</i>
<i>  // fetching the type ID of the arguments.</i>

  <b>if</b> (!<span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span>) {
    <i>// Ask the QMetaObject for the parameter names, and use the QMetaType</i>
<i>    // system to look up type IDs</i>
    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#QMetaMethod" title='QMetaMethod' data-ref="QMetaMethod" data-proj="qtbase" " >QMetaMethod</a> <dfn class="local col8 decl" id="18m" title='m' data-type='QMetaMethod' data-ref="18m" >m</dfn> = <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject_p.h.html#QMetaObjectPrivate" title='QMetaObjectPrivate' data-ref="QMetaObjectPrivate" data-proj="qtbase" >QMetaObjectPrivate</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject_p.h.html#_ZN18QMetaObjectPrivate6signalEPK11QMetaObjecti" title='QMetaObjectPrivate::signal' data-ref="_ZN18QMetaObjectPrivate6signalEPK11QMetaObjecti" data-proj="qtbase" " id="_ZN18QMetaObjectPrivate6signalEPK11QMetaObjecti" >signal</a>(<span class="local col2 ref" title='sender' data-ref="12sender" >sender</span>-&gt;<a class="virtual ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#114" title='QObject::metaObject' data-ref="_ZNK7QObject10metaObjectEv" data-proj="qtbase" id="_ZNK7QObject10metaObjectEv" >metaObject</a>(), <span class="local col3 ref" title='signal' data-ref="13signal" >signal</span>);
    <span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span> = <a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZL21queuedConnectionTypesRK5QListI10QByteArrayE" title='queuedConnectionTypes' data-ref="_ZL21queuedConnectionTypesRK5QListI10QByteArrayE" data-proj="qtbase" " id="_ZL21queuedConnectionTypesRK5QListI10QByteArrayE" >queuedConnectionTypes</a>(<span class="local col8 ref" title='m' data-ref="18m" >m</span>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#_ZNK11QMetaMethod14parameterTypesEv" title='QMetaMethod::parameterTypes' data-ref="_ZNK11QMetaMethod14parameterTypesEv" data-proj="qtbase" id="_ZNK11QMetaMethod14parameterTypesEv" >parameterTypes</a>());
    <b>if</b> (!<span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span>) <i>// Cannot queue arguments</i>
      <span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span> = &amp;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZL22DIRECT_CONNECTION_ONLY" title='DIRECT_CONNECTION_ONLY' data-ref="_ZL22DIRECT_CONNECTION_ONLY" data-proj="qtbase" id="_ZL22DIRECT_CONNECTION_ONLY" >DIRECT_CONNECTION_ONLY</a>;
    <span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::argumentTypes" title='QObjectPrivate::Connection::argumentTypes' data-ref="QObjectPrivate::Connection::argumentTypes" data-proj="qtbase" id="QObjectPrivate::Connection::argumentTypes" >argumentTypes</a> <a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qatomic.h.html#_ZN14QAtomicPointeraSERK14QAtomicPointerIT_E" title='QAtomicPointer::operator=' data-ref="_ZN14QAtomicPointeraSERK14QAtomicPointerIT_E" data-proj="qtbase" " id="_ZN14QAtomicPointeraSERK14QAtomicPointerIT_E" >=</a> <span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span>; <i>/* ... skipped: atomic update ... */</i>
  }
  <b>if</b> (<span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span> == &amp;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZL22DIRECT_CONNECTION_ONLY" title='DIRECT_CONNECTION_ONLY' data-ref="_ZL22DIRECT_CONNECTION_ONLY" data-proj="qtbase" id="_ZL22DIRECT_CONNECTION_ONLY" >DIRECT_CONNECTION_ONLY</a>) <i>// Cannot activate</i>
      <b>return</b>;
  <em>int</em> <dfn class="local col9 decl" id="19nargs" title='nargs' data-type='int' data-ref="19nargs" >nargs</dfn> = <var>1</var>; <i>// Include the return type</i>
  <b>while</b> (<span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span>[<span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>-<var>1</var>])
      ++<span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>;
  <i>// Copy the argumentTypes array since the event is going to take ownership</i>
  <em>int</em> *<dfn class="local col0 decl" id="20types" title='types' data-type='int *' data-ref="20types" >types</dfn> = (<em>int</em> *) <a class="ref" href="https://code.woboq.org/qt5/include/stdlib.h.html#malloc" title='malloc' data-ref="malloc" data-proj="include" " id="malloc" >malloc</a>(<span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>*<b>sizeof</b>(<em>int</em>));
  <em>void</em> **<dfn class="local col1 decl" id="21args" title='args' data-type='void **' data-ref="21args" >args</dfn> = (<em>void</em> **) <a class="ref" href="https://code.woboq.org/qt5/include/stdlib.h.html#malloc" title='malloc' data-ref="malloc" data-proj="include" id="malloc" >malloc</a>(<span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>*<b>sizeof</b>(<em>void</em> *));

  <i>// Ignore the return value as it makes no sense in a queued connection</i>
  <span class="local col0 ref" title='types' data-ref="20types" >types</span>[<var>0</var>] = <var>0</var>; <i>// Return type</i>
  <span class="local col1 ref" title='args' data-ref="21args" >args</span>[<var>0</var>] = <var>0</var>; <i>// Return value</i>

  <b>if</b> (<span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span> &gt; <var>1</var>) {
    <b>for</b> (<em>int</em> <dfn class="local col2 decl" id="22n" title='n' data-type='int' data-ref="22n" >n</dfn> = <var>1</var>; <span class="local col2 ref" title='n' data-ref="22n" >n</span> &lt; <span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>; ++<span class="local col2 ref" title='n' data-ref="22n" >n</span>)
      <span class="local col0 ref" title='types' data-ref="20types" >types</span>[<span class="local col2 ref" title='n' data-ref="22n" >n</span>] = <span class="local col7 ref" title='argumentTypes' data-ref="17argumentTypes" >argumentTypes</span>[<span class="local col2 ref" title='n' data-ref="22n" >n</span>-<var>1</var>];

    <i>// We must unlock the object's signal mutex while calling the copy</i>
<i>    // constructors of the arguments as they might re-enter and cause a deadlock</i>
    <span class="local col6 ref" title='locker' data-ref="16locker" >locker</span>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLocker6unlockEv" title='QMutexLocker::unlock' data-ref="_ZN12QMutexLocker6unlockEv" data-proj="qtbase" id="_ZN12QMutexLocker6unlockEv" >unlock</a>();
    <b>for</b> (<em>int</em> <dfn class="local col3 decl" id="23n" title='n' data-type='int' data-ref="23n" >n</dfn> = <var>1</var>; <span class="local col3 ref" title='n' data-ref="23n" >n</span> &lt; <span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>; ++<span class="local col3 ref" title='n' data-ref="23n" >n</span>)
      <span class="local col1 ref" title='args' data-ref="21args" >args</span>[<span class="local col3 ref" title='n' data-ref="23n" >n</span>] = <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetatype.h.html#QMetaType" title='QMetaType' data-ref="QMetaType" data-proj="qtbase" >QMetaType</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetatype.h.html#_ZN9QMetaType6createEiPKv" title='QMetaType::create' data-ref="_ZN9QMetaType6createEiPKv" data-proj="qtbase" " id="_ZN9QMetaType6createEiPKv" >create</a>(<span class="local col0 ref" title='types' data-ref="20types" >types</span>[<span class="local col3 ref" title='n' data-ref="23n" >n</span>], <span class="local col5 ref" title='argv' data-ref="15argv" >argv</span>[<span class="local col3 ref" title='n' data-ref="23n" >n</span>]);
    <span class="local col6 ref" title='locker' data-ref="16locker" >locker</span>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLocker6relockEv" title='QMutexLocker::relock' data-ref="_ZN12QMutexLocker6relockEv" data-proj="qtbase" id="_ZN12QMutexLocker6relockEv" >relock</a>();

    <b>if</b> (!<span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::receiver" title='QObjectPrivate::Connection::receiver' data-ref="QObjectPrivate::Connection::receiver" data-proj="qtbase" id="QObjectPrivate::Connection::receiver" >receiver</a>) {
      <i>// We have been disconnected while the mutex was unlocked</i>
      <i>/* ... skipped cleanup ... */</i>
      <b>return</b>;
    }
  }

  <i>// Post an event</i>
  <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a> *<dfn class="local col4 decl" id="24ev" title='ev' data-type='QMetaCallEvent *' data-ref="24ev" >ev</dfn> = <span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::isSlotObject" title='QObjectPrivate::Connection::isSlotObject' data-ref="QObjectPrivate::Connection::isSlotObject" data-proj="qtbase" id="QObjectPrivate::Connection::isSlotObject" >isSlotObject</a> ?
    <b>new</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZN14QMetaCallEventC1EPN9QtPrivate15QSlotObjectBaseEPK7QObjectiiPiPPvP10QSemaphore" title='QMetaCallEvent::QMetaCallEvent' data-ref="_ZN14QMetaCallEventC1EPN9QtPrivate15QSlotObjectBaseEPK7QObjectiiPiPPvP10QSemaphore" data-proj="qtbase" id="_ZN14QMetaCallEventC1EPN9QtPrivate15QSlotObjectBaseEPK7QObjectiiPiPPvP10QSemaphore" >(</a><span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::(anonymous)::slotObj" title='QObjectPrivate::Connection::(anonymous union)::slotObj' data-ref="QObjectPrivate::Connection::(anonymous)::slotObj" data-proj="qtbase" id="QObjectPrivate::Connection::(anonymous)::slotObj" >slotObj</a>, <span class="local col2 ref" title='sender' data-ref="12sender" >sender</span>, <span class="local col3 ref" title='signal' data-ref="13signal" >signal</span>, <span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>, <span class="local col0 ref" title='types' data-ref="20types" >types</span>, <span class="local col1 ref" title='args' data-ref="21args" >args</span>) :
    <b>new</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZN14QMetaCallEventC1EttPFvP7QObjectN11QMetaObject4CallEiPPvEPKS0_iiPiS5_P10QSemaphore" title='QMetaCallEvent::QMetaCallEvent' data-ref="_ZN14QMetaCallEventC1EttPFvP7QObjectN11QMetaObject4CallEiPPvEPKS0_iiPiS5_P10QSemaphore" data-proj="qtbase" id="_ZN14QMetaCallEventC1EttPFvP7QObjectN11QMetaObject4CallEiPPvEPKS0_iiPiS5_P10QSemaphore" >(</a><span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::method_offset" title='QObjectPrivate::Connection::method_offset' data-ref="QObjectPrivate::Connection::method_offset" data-proj="qtbase" id="QObjectPrivate::Connection::method_offset" >method_offset</a>, <span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::method_relative" title='QObjectPrivate::Connection::method_relative' data-ref="QObjectPrivate::Connection::method_relative" data-proj="qtbase" id="QObjectPrivate::Connection::method_relative" >method_relative</a>, <span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::(anonymous)::callFunction" title='QObjectPrivate::Connection::(anonymous union)::callFunction' data-ref="QObjectPrivate::Connection::(anonymous)::callFunction" data-proj="qtbase" id="QObjectPrivate::Connection::(anonymous)::callFunction" >callFunction</a>,
                       <span class="local col2 ref" title='sender' data-ref="12sender" >sender</span>, <span class="local col3 ref" title='signal' data-ref="13signal" >signal</span>, <span class="local col9 ref" title='nargs' data-ref="19nargs" >nargs</span>, <span class="local col0 ref" title='types' data-ref="20types" >types</span>, <span class="local col1 ref" title='args' data-ref="21args" >args</span>);
  <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.h.html#QCoreApplication" title='QCoreApplication' data-ref="QCoreApplication" data-proj="qtbase" >QCoreApplication</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.h.html#_ZN16QCoreApplication9postEventEP7QObjectP6QEventi" title='QCoreApplication::postEvent' data-ref="_ZN16QCoreApplication9postEventEP7QObjectP6QEventi" data-proj="qtbase" id="_ZN16QCoreApplication9postEventEP7QObjectP6QEventi" >postEvent</a>(<span class="local col4 ref" title='c' data-ref="14c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::receiver" title='QObjectPrivate::Connection::receiver' data-ref="QObjectPrivate::Connection::receiver" data-proj="qtbase" id="QObjectPrivate::Connection::receiver" >receiver</a>, <span class="local col4 ref" title='ev' data-ref="24ev" >ev</span>);
}
</pre>

<p>Upon reception of this event, <code>QObject::event</code> will set the sender and call <code>QMetaCallEvent::placeMetaCall</code>. That later function will dispatch just the same way as
<code>QMetaObject::activate</code> would do it for direct connections, as seen in Part 1
</p>

<pre class="code">  <b>case</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreevent.h.html#QEvent" title='QEvent' data-ref="QEvent" data-proj="qtbase" >QEvent</a>::<a class="enum" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreevent.h.html#QEvent::Type::MetaCall" title='QEvent::Type::MetaCall' data-ref="QEvent::Type::MetaCall" data-proj="qtbase" >MetaCall</a>:
  {
    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a> *<dfn class="local col6 decl" id="26mce" title='mce' data-type='QMetaCallEvent *' data-ref="26mce" >mce</dfn> = <b>static_cast</b>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a>*&gt;(<span class="local col5 ref" title='e' data-ref="25e" >e</span>);

    <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#QConnectionSenderSwitcher" title='QConnectionSenderSwitcher' data-ref="QConnectionSenderSwitcher" data-proj="qtbase" >QConnectionSenderSwitcher</a> <dfn class="local col7 decl" id="27sw" title='sw' data-type='QConnectionSenderSwitcher' data-ref="27sw" >sw</dfn><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZN25QConnectionSenderSwitcherC1EP7QObjectS1_i" title='QConnectionSenderSwitcher::QConnectionSenderSwitcher' data-ref="_ZN25QConnectionSenderSwitcherC1EP7QObjectS1_i" data-proj="qtbase" id="_ZN25QConnectionSenderSwitcherC1EP7QObjectS1_i" >(</a><b>this</b>, <b>const_cast</b>&lt;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#QObject" title='QObject' data-ref="QObject" data-proj="qtbase" >QObject</a>*&gt;(<span class="local col6 ref" title='mce' data-ref="26mce" >mce</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZNK14QMetaCallEvent6senderEv" title='QMetaCallEvent::sender' data-ref="_ZNK14QMetaCallEvent6senderEv" data-proj="qtbase" id="_ZNK14QMetaCallEvent6senderEv" >sender</a>()),
                                 <span class="local col6 ref" title='mce' data-ref="26mce" >mce</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZNK14QMetaCallEvent8signalIdEv" title='QMetaCallEvent::signalId' data-ref="_ZNK14QMetaCallEvent8signalIdEv" data-proj="qtbase" id="_ZNK14QMetaCallEvent8signalIdEv" >signalId</a>());

    <span class="local col6 ref" title='mce' data-ref="26mce" >mce</span>-&gt;<a class="virtual ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZN14QMetaCallEvent13placeMetaCallEP7QObject" title='QMetaCallEvent::placeMetaCall' data-ref="_ZN14QMetaCallEvent13placeMetaCallEP7QObject" data-proj="qtbase" id="_ZN14QMetaCallEvent13placeMetaCallEP7QObject" >placeMetaCall</a>(<b>this</b>);
    <b>break</b>;
  }
</pre>


<h2>BlockingQueuedConnection</h2>

<p><code>BlockingQueuedConnection</code> is a mix between <code>DirectConnection</code> and <code>QueuedConnection</code>. Like with a
<code>DirectConnection</code>, the arguments can stay on the stack since the stack is on the thread that
is blocked. No need to copy the arguments.
Like with a <code>QueuedConnection</code>, an event is posted to the other thread's event loop. The event also contains
a pointer to a <code>QSemaphore</code>. The thread that delivers the event will release the
semaphore right after the slot has been called. Meanwhile, the thread that called the signal will acquire
the semaphore in order to wait until the event is processed.
</p>


<pre class="code">} <b>else</b> <b>if</b> (<span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::connectionType" title='QObjectPrivate::Connection::connectionType' data-ref="QObjectPrivate::Connection::connectionType" data-proj="qtbase" id="QObjectPrivate::Connection::connectionType" >connectionType</a> == <span class="namespace">Qt::</span><a class="enum" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qnamespace.h.html#Qt::ConnectionType::BlockingQueuedConnection" title='Qt::ConnectionType::BlockingQueuedConnection' data-ref="Qt::ConnectionType::BlockingQueuedConnection" data-proj="qtbase" id="Qt::ConnectionType::BlockingQueuedConnection" >BlockingQueuedConnection</a>) {
  <span class="local col9 ref" title='locker' data-ref="9locker" >locker</span>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLocker6unlockEv" title='QMutexLocker::unlock' data-ref="_ZN12QMutexLocker6unlockEv" data-proj="qtbase" id="_ZN12QMutexLocker6unlockEv" >unlock</a>(); <i>// unlock the QObject's signal mutex.</i>
  <b>if</b> (<span class="local col8 ref" title='receiverInSameThread' data-ref="8receiverInSameThread" >receiverInSameThread</span>) {
    <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qlogging.h.html#160" title="QMessageLogger(&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/how-qt-signals-slots-work-part3-queuedconnection.data/qobject.cpp&quot;, 33, __PRETTY_FUNCTION__).warning" data-ref="_M/qWarning" data-proj="qtbase" ">qWarning</a>(<q>"Qt: Dead lock detected while activating a BlockingQueuedConnection: "</q>
             <q>"Sender is %s(%p), receiver is %s(%p)"</q>,
             <span class="local col1 ref" title='sender' data-ref="1sender" >sender</span>-&gt;<a class="virtual ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#114" title='QObject::metaObject' data-ref="_ZNK7QObject10metaObjectEv" data-proj="qtbase" id="_ZNK7QObject10metaObjectEv" >metaObject</a>()-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject9classNameEv" title='QMetaObject::className' data-ref="_ZNK11QMetaObject9classNameEv" data-proj="qtbase" " id="_ZNK11QMetaObject9classNameEv" >className</a>(), <span class="local col1 ref" title='sender' data-ref="1sender" >sender</span>,
             <span class="local col6 ref" title='receiver' data-ref="6receiver" >receiver</span>-&gt;<a class="virtual ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#114" title='QObject::metaObject' data-ref="_ZNK7QObject10metaObjectEv" data-proj="qtbase" id="_ZNK7QObject10metaObjectEv" >metaObject</a>()-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject9classNameEv" title='QMetaObject::className' data-ref="_ZNK11QMetaObject9classNameEv" data-proj="qtbase" id="_ZNK11QMetaObject9classNameEv" >className</a>(), <span class="local col6 ref" title='receiver' data-ref="6receiver" >receiver</span>);
  }
  <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qsemaphore.h.html#QSemaphore" title='QSemaphore' data-ref="QSemaphore" data-proj="qtbase" " >QSemaphore</a> <dfn class="local col0 decl" id="10semaphore" title='semaphore' data-type='QSemaphore' data-ref="10semaphore" >semaphore</dfn>;
  <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a> *<dfn class="local col1 decl" id="11ev" title='ev' data-type='QMetaCallEvent *' data-ref="11ev" >ev</dfn> = <span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::isSlotObject" title='QObjectPrivate::Connection::isSlotObject' data-ref="QObjectPrivate::Connection::isSlotObject" data-proj="qtbase" id="QObjectPrivate::Connection::isSlotObject" >isSlotObject</a> ?
    <b>new</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZN14QMetaCallEventC1EPN9QtPrivate15QSlotObjectBaseEPK7QObjectiiPiPPvP10QSemaphore" title='QMetaCallEvent::QMetaCallEvent' data-ref="_ZN14QMetaCallEventC1EPN9QtPrivate15QSlotObjectBaseEPK7QObjectiiPiPPvP10QSemaphore" data-proj="qtbase" id="_ZN14QMetaCallEventC1EPN9QtPrivate15QSlotObjectBaseEPK7QObjectiiPiPPvP10QSemaphore" >(</a><span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::(anonymous)::slotObj" title='QObjectPrivate::Connection::(anonymous union)::slotObj' data-ref="QObjectPrivate::Connection::(anonymous)::slotObj" data-proj="qtbase" id="QObjectPrivate::Connection::(anonymous)::slotObj" >slotObj</a>, <span class="local col1 ref" title='sender' data-ref="1sender" >sender</span>, <span class="local col5 ref" title='signal_index' data-ref="5signal_index" >signal_index</span>, <var>0</var>, <var>0</var>, <span class="local col4 ref" title='argv' data-ref="4argv" >argv</span>, &amp;<span class="local col0 ref" title='semaphore' data-ref="10semaphore" >semaphore</span>) :
    <b>new</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QMetaCallEvent" title='QMetaCallEvent' data-ref="QMetaCallEvent" data-proj="qtbase" >QMetaCallEvent</a><a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#_ZN14QMetaCallEventC1EttPFvP7QObjectN11QMetaObject4CallEiPPvEPKS0_iiPiS5_P10QSemaphore" title='QMetaCallEvent::QMetaCallEvent' data-ref="_ZN14QMetaCallEventC1EttPFvP7QObjectN11QMetaObject4CallEiPPvEPKS0_iiPiS5_P10QSemaphore" data-proj="qtbase" id="_ZN14QMetaCallEventC1EttPFvP7QObjectN11QMetaObject4CallEiPPvEPKS0_iiPiS5_P10QSemaphore" >(</a><span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::method_offset" title='QObjectPrivate::Connection::method_offset' data-ref="QObjectPrivate::Connection::method_offset" data-proj="qtbase" id="QObjectPrivate::Connection::method_offset" >method_offset</a>, <span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::method_relative" title='QObjectPrivate::Connection::method_relative' data-ref="QObjectPrivate::Connection::method_relative" data-proj="qtbase" id="QObjectPrivate::Connection::method_relative" >method_relative</a>, <span class="local col7 ref" title='c' data-ref="7c" >c</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject_p.h.html#QObjectPrivate::Connection::(anonymous)::callFunction" title='QObjectPrivate::Connection::(anonymous union)::callFunction' data-ref="QObjectPrivate::Connection::(anonymous)::callFunction" data-proj="qtbase" id="QObjectPrivate::Connection::(anonymous)::callFunction" >callFunction</a>,
                       <span class="local col1 ref" title='sender' data-ref="1sender" >sender</span>, <span class="local col5 ref" title='signal_index' data-ref="5signal_index" >signal_index</span>, <var>0</var>, <var>0</var>, <span class="local col4 ref" title='argv' data-ref="4argv" >argv</span> , &amp;<span class="local col0 ref" title='semaphore' data-ref="10semaphore" >semaphore</span>);
  <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.h.html#QCoreApplication" title='QCoreApplication' data-ref="QCoreApplication" data-proj="qtbase" >QCoreApplication</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qcoreapplication.h.html#_ZN16QCoreApplication9postEventEP7QObjectP6QEventi" title='QCoreApplication::postEvent' data-ref="_ZN16QCoreApplication9postEventEP7QObjectP6QEventi" data-proj="qtbase" " id="_ZN16QCoreApplication9postEventEP7QObjectP6QEventi" >postEvent</a>(<span class="local col6 ref" title='receiver' data-ref="6receiver" >receiver</span>, <span class="local col1 ref" title='ev' data-ref="11ev" >ev</span>);
  <span class="local col0 ref" title='semaphore' data-ref="10semaphore" >semaphore</span>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qsemaphore.h.html#_ZN10QSemaphore7acquireEi" title='QSemaphore::acquire' data-ref="_ZN10QSemaphore7acquireEi" data-proj="qtbase" id="_ZN10QSemaphore7acquireEi" >acquire</a>();
  <span class="local col9 ref" title='locker' data-ref="9locker" >locker</span>.<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qmutex.h.html#_ZN12QMutexLocker6relockEv" title='QMutexLocker::relock' data-ref="_ZN12QMutexLocker6relockEv" data-proj="qtbase" id="_ZN12QMutexLocker6relockEv" >relock</a>();
  <b>continue</b>;
}
</pre>

<p>It is the destructor of QMetaCallEvent which will release the semaphore. This is good because
the event will be deleted right after it is delivered (i.e. the slot has been called) but also when
the event is not delivered (e.g. because the receiving object was deleted).</p>

<p>A <code>BlockingQueuedConnection</code> can be useful to do thread communication when you want to invoke a
function in another thread and wait for the answer before it is finished. However, it must be done
with care.
</p>

<h3>The dangers of BlockingQueuedConnection</h3>

<p>You must be careful in order to avoid deadlocks.</p>

<p>Obviously, if you connect two objects using <code>BlockingQueuedConnection</code> living on the same thread,
you will deadlock immediately. You are sending an event to the sender's own thread and then are locking the
thread waiting for the event to be processed. Since the thread is blocked, the event will never be
processed and the thread will be blocked forever.  Qt detects this at run time and prints a warning,
but does not attempt to fix the problem for you.
It has been suggested that Qt could then just do a normal <code>DirectConnection</code> if both objects are in
the same thread. But we choose not to because <code>BlockingQueuedConnection</code> is something that can only be
used if you know what you are doing: You must know from which thread to what other thread the
event will be sent.</p>

<p>The real danger is that you must keep your design such that if in your application, you do a
<code>BlockingQueuedConnection</code> from thread A to thread B, thread B must never wait for thread A, or you will
have a deadlock again.</p>
<p>When emitting the signal or calling <code>QMetaObject::invokeMethod()</code>, you must not have any mutex locked
that thread B might also try locking.</p>
<p>A problem will typically appear when you need to terminate a thread using a <code>BlockingQueuedConnection</code>, for example in this
pseudo code:</p>

<pre class="code"><em>void</em> <span class="type" title='MyOperation' data-ref="MyOperation" >MyOperation</span>::<dfn class="tu decl def" id="_ZN11MyOperation4stopEv" title='MyOperation::stop' data-type='void MyOperation::stop()' data-ref="_ZN11MyOperation4stopEv" >stop</dfn>()
{
    <span class="tu member" title='MyOperation::m_thread' data-use='m' data-ref="MyOperation::m_thread" >m_thread</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qthread.h.html#_ZN7QThread4quitEv" title='QThread::quit' data-ref="_ZN7QThread4quitEv" data-proj="qtbase" id="_ZN7QThread4quitEv" >quit</a>();
    <span class="tu member" title='MyOperation::m_thread' data-use='m' data-ref="MyOperation::m_thread" >m_thread</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qthread.h.html#_ZN7QThread4waitEm" title='QThread::wait' data-ref="_ZN7QThread4waitEm" data-proj="qtbase" id="_ZN7QThread4waitEm" >wait</a>(); <i>// Waits for the callee thread, might deadlock</i>
    <span class="tu member" title='MyOperation::cleanup' data-use='c' data-ref="_ZN11MyOperation7cleanupEv" >cleanup</span>();
}

<i  data-doc="_ZN11MyOperation15slotGetSomeDataERK3Key">// Connected via a BlockingQueuedConnection</i>
<span class="type" title='Stuff' data-ref="Stuff" >Stuff</span> <span class="type" title='MyOperation' data-ref="MyOperation" >MyOperation</span>::<dfn class="tu decl def" id="_ZN11MyOperation15slotGetSomeDataERK3Key" title='MyOperation::slotGetSomeData' data-type='Stuff MyOperation::slotGetSomeData(const Key &amp; k)' data-ref="_ZN11MyOperation15slotGetSomeDataERK3Key" >slotGetSomeData</dfn>(<em>const</em> <span class="type" title='Key' data-ref="Key" >Key</span> &amp;<dfn class="local col3 decl" id="3k" title='k' data-type='const Key &amp;' data-ref="3k" >k</dfn>)
{
    <b>return</b> <span class="tu member" title='MyOperation::m_data' data-use='m' data-ref="MyOperation::m_data" >m_data</span>-&gt;<span class="tu ref" title='MyOperation::Data::get' data-use='c' data-ref="_ZN11MyOperation4Data3getERK3Key" >get</span>(<span class="local col3 ref" title='k' data-ref="3k" >k</span>);
}
</pre>



<p>You cannot just call wait here because the child thread might have already emitted, or is about to emit
the signal that will wait for the parent thread, which won't go back to its event loop.  All the thread cleanup information transfer must only happen with
events posted between threads, without using <code>wait()</code>. A better way to do it would be:</p>


<pre class="code"><em>void</em> <span class="type" title='MyOperation' data-ref="MyOperation" >MyOperation</span>::<span class='error' title="redefinition of &apos;stop&apos;"><dfn class="tu decl def" id="_ZN11MyOperation4stopEv" title='MyOperation::stop' data-type='void MyOperation::stop()' data-ref="_ZN11MyOperation4stopEv" >stop</dfn></span>()
{
    <a class="member" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#_ZN7QObject7connectEPKN9QtPrivate15FunctionPointerIT_E6ObjectES2_PKNS1_IT0_E6ObjectES7_N2Qt14ConnectionTypeE" title='QObject::connect' data-ref="_ZN7QObject7connectEPKN9QtPrivate15FunctionPointerIT_E6ObjectES2_PKNS1_IT0_E6ObjectES7_N2Qt14ConnectionTypeE" data-proj="qtbase" id="_ZN7QObject7connectEPKN9QtPrivate15FunctionPointerIT_E6ObjectES2_PKNS1_IT0_E6ObjectES7_N2Qt14ConnectionTypeE" >connect</a>(<span class="tu member" title='MyOperation::m_thread' data-use='r' data-ref="MyOperation::m_thread" >m_thread</span>, &amp;<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qthread.h.html#QThread" title='QThread' data-ref="QThread" data-proj="qtbase" >QThread</a>::<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qthread.h.html#_ZN7QThread8finishedENS_14QPrivateSignalE" title='QThread::finished' data-ref="_ZN7QThread8finishedENS_14QPrivateSignalE" data-proj="qtbase" id="_ZN7QThread8finishedENS_14QPrivateSignalE" >finished</a>, <b>this</b>, &amp;<span class="type" title='MyOperation' data-ref="MyOperation" >MyOperation</span>::<span class="tu member" title='MyOperation::cleanup' data-use='a' data-ref="_ZN11MyOperation7cleanupEv" >cleanup</span>);
    <span class="tu member" title='MyOperation::m_thread' data-use='m' data-ref="MyOperation::m_thread" >m_thread</span>-&gt;<a class="ref" href="https://code.woboq.org/qt5/qtbase/src/corelib/thread/qthread.h.html#_ZN7QThread4quitEv" title='QThread::quit' data-ref="_ZN7QThread4quitEv" data-proj="qtbase" id="_ZN7QThread4quitEv" >quit</a>();
    <i>/* (note that we connected before calling quit to avoid a race) */</i>
}
</pre>



<p>The downside is that <code>MyOperation::cleanup()</code> is now called asynchronously, which may complicate the design.
</p>

<h2>Conclusion</h2>

<p>This article should conclude the series. I hope these articles have demystified signals and slots,
and that knowing a bit how this works under the hood will help you make better use of them in your
applications.</p>


]]></description></item>
<item><title>QDockWidget improvements in Qt 5.6</title><link>https://woboq.com/blog/qdockwidget-changes-in-56.html</link><guid>http://woboq.com/blog/qdockwidget-changes-in-56.html</guid><pubDate>Fri, 18 Dec 2015 13:12:31 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>
We made some improvements to QDockWidget for Qt 5.6. You can now re-order your QDockWidget's tabs with the mouse.
There is also a new mode you can set on your QMainWindow so that you can drag and drop full groups of
tabbed QDockWidgets. Furthermore there is a new API which allows you to programatically resize the QDockWidgets.
</p>
</div>
<p>Images (or in this case, animations) are worth a 1000 words:</p>
<h3>Re-order the tabbed QDockWidgets:</h3>
<img src="https://woboq.com/blog/qdockwidget-changes-in-56/rearrangetabs.gif"/>
<p>This change applies to all the application using QDockWidget without any modification of their code.</p>
<h3>New QMainwindow mode to drag tab by group</h3>
<p>This is not by default because it changes the behaviour, so application developer may want to
enable <a href="https://doc-snapshots.qt.io/qt5-dev/qmainwindow.html#DockOption-enum">
        <code>QMainWindow::GroupedDragging</code>
    </a> in their code:</p>
<pre class="brush: cpp">
MyMainWindow::MyMainWindow(/*...*/) : QMainWindow(/*...*/)
{
    /*...*/
    setDockOptions(dockOptions() | QMainWindow::GroupedDragging);
}
</pre>
<p>Without this flag, the user can only drag the QDockWidget's one by one.
In this new mode,
the user is able to drag the whole group of tabbed QDockWidget together by dragging the title. Individual QDockWidget can still be dragged by dragging the tab out of its tab bar.</p>
<p>This animation shows the example in <a href="https://code.woboq.org/qt5/qtbase/examples/widgets/mainwindows/mainwindow/">qtbase/examples/widgets/mainwindows/mainwindow</a>:</p>
<img src="https://woboq.com/blog/qdockwidget-changes-in-56/groupeddragging.gif"/>
<p>This changes the behaviour slightly as the QDockWidget may be reparented to an internal floating
tab window. So if your application assumed that QDockWidget's parent was always the main window, it
needs to be changed.</p>
<h3>Programatically resize your dock widgets</h3>
<p>
If you want to give a default layout that looks nice for your application using many
QDockWidget, you can use <code>QMainWindow::resizeDocks</code> to achieve that goal.
</p>
<h2>Conclusion</h2>
<p>You can try these changes in the <a href="https://blog.qt.io/blog/2015/12/18/qt-5-6-beta-released/">Qt 5.6 beta</a>
</p>
<p>We made those changes because it was requested by one of our customers.
You can <a href="https://woboq.com/software-services.html">hire Woboq</a> to fix your own Qt bugs or implement new features inside Qt.
<a href="mailto:info@woboq.com">Send us an email</a> with
the bug number or a description of your feature, and we will reply with a quote.

</p>
<p>QtWidgets still have their place on desktop and many applications are still using QDockWidgets.</p>
]]></description></item>
<item><title>New in Qt 5.5: Q_ENUM and the C++ tricks behind it</title><link>https://woboq.com/blog/q_enum.html</link><guid>http://woboq.com/blog/q_enum.html</guid><pubDate>Thu, 02 Jul 2015 16:51:48 GMT</pubDate><description><![CDATA[
<div class = "intro">
<p>Qt 5.5 was just released and with it comes a new <a href="https://doc.qt.io/qt-5/qobject.html#Q_ENUM"><code>Q_ENUM</code></a> macro, a better alternative to the now deprecated Q_ENUMS (with S).</p>
<p>In this blog post, I will discuss this new Qt 5.5 feature; What it does, and how I implemented it.
If you are not interested by the implementation details, skip to the conclusion to see what you can do in Qt 5.5 with <code>Q_ENUM</code>.
</p>
</div>

<h2>The problem</h2>
<p>
In order to better understand the problem it solves, let us look at this typical sample code using Q_ENUMS
as it already could have been written with Qt 4.0.
</p>

<pre class="code"><b>class</b> <dfn class="type def" id="FooBar" title='FooBar' data-ref="FooBar">FooBar</dfn> : <b>public</b> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.h.html#QObject" title='QObject' data-ref="QObject" data-proj="qtbase" ">QObject</a> {
  <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#174" title="public: static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private: __attribute__((visibility(&quot;hidden&quot;))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); struct QPrivateSignal {};" data-ref="_M/Q_OBJECT" data-proj="qtbase" ">Q_OBJECT</a>
  <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#119" title="" data-ref="_M/Q_ENUMS" data-proj="qtbase">Q_ENUMS</a>(Action)
<b>public</b>:
  <b>enum</b> <dfn class="type def" id="FooBar::Action" title='FooBar::Action' data-ref="FooBar::Action">Action</dfn> { <dfn class="enum" id="FooBar::Action::Open" title='FooBar::Action::Open' data-ref="FooBar::Action::Open">Open</dfn>, <dfn class="enum" id="FooBar::Action::Save" title='FooBar::Action::Save' data-ref="FooBar::Action::Save">Save</dfn>, <dfn class="enum" id="FooBar::Action::New" title='FooBar::Action::New' data-ref="FooBar::Action::New">New</dfn>, <dfn class="enum" id="FooBar::Action::Copy" title='FooBar::Action::Copy' data-ref="FooBar::Action::Copy">Copy</dfn>, <dfn class="enum" id="FooBar::Action::Cut" title='FooBar::Action::Cut' data-ref="FooBar::Action::Cut">Cut</dfn>, <dfn class="enum" id="FooBar::Action::Paste" title='FooBar::Action::Paste' data-ref="FooBar::Action::Paste">Paste</dfn>, <dfn class="enum" id="FooBar::Action::Undo" title='FooBar::Action::Undo' data-ref="FooBar::Action::Undo">Undo</dfn>, <dfn class="enum" id="FooBar::Action::Redo" title='FooBar::Action::Redo' data-ref="FooBar::Action::Redo">Redo</dfn>, <dfn class="enum" id="FooBar::Action::Delete" title='FooBar::Action::Delete' data-ref="FooBar::Action::Delete">Delete</dfn> };

  <em>void</em> <dfn class="tu decl def fn" id="_ZN6FooBar10myFunctionENS_6ActionE" title='FooBar::myFunction' data-type='void FooBar::myFunction(FooBar::Action a)' data-ref="_ZN6FooBar10myFunctionENS_6ActionE">myFunction</dfn>(<span class="type" title='FooBar::Action' data-ref="FooBar::Action">Action</span> <dfn class="local col1 decl" id="1a" title='a' data-type='FooBar::Action' data-ref="1a">a</dfn>) {
    <a class="macro" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qlogging.h.html#158" title="QMessageLogger(&quot;/home/olivier/woboq/web/woboqwebsite/data/blogs/q_enum.data/blog.cc&quot;, 16, __PRETTY_FUNCTION__).debug" data-ref="_M/qDebug" data-proj="qtbase" ">qDebug</a>() <a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#_ZN6QDebuglsEPKc" title='QDebug::operator&lt;&lt;' data-ref="_ZN6QDebuglsEPKc" data-proj="qtbase">&lt;&lt;</a> <q>"Action is: "</q> <a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#_ZN6QDebuglsEi" title='QDebug::operator&lt;&lt;' data-ref="_ZN6QDebuglsEi" data-proj="qtbase" ">&lt;&lt;</a> <span class="local col1 ref" title='a' data-ref="1a">a</span>;
    <i>//...</i>
  }
};
</pre>

<p>
But here, the <code>qDebug</code> will look like this:<br/>
<code>Action is: 8</code><br/>
It would be much better if I could see the text instead such as:<br/>
<code>Action is: Delete</code></p>

<p><code>Q_ENUMS</code> tells <code>moc</code> to register the names of the enum value inside its QMetaObject
so that it can be used from Qt Designer, from QtScript or from QML.
However it is not working yet with <code>qDebug</code>.</p>

<p>One could use the information in the <code>QMetaObject</code> while overloading the <code>operator&lt;&lt;</code>
for QDebug and use QMetaObject's API: </p>

<pre class="code"><a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#QDebug" title='QDebug' data-ref="QDebug" data-proj="qtbase">QDebug</a> <dfn class="decl def fn" id="_Zls6QDebugN6FooBar6ActionE" title='operator&lt;&lt;' data-ref="_Zls6QDebugN6FooBar6ActionE"><b>operator</b>&lt;&lt;</dfn>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#QDebug" title='QDebug' data-ref="QDebug" data-proj="qtbase">QDebug</a> <dfn class="local col2 decl" id="2dbg" title='dbg' data-type='QDebug' data-ref="2dbg">dbg</dfn>, <span class="type" title='FooBar' data-ref="FooBar">FooBar</span>::<span class="type" title='FooBar::Action' data-ref="FooBar::Action">Action</span> <dfn class="local col3 decl" id="3action" title='action' data-type='FooBar::Action' data-ref="3action">action</dfn>)
{
  <em>static</em> <em>int</em> <dfn class="local col4 decl" id="4enumIdx" title='enumIdx' data-type='int' data-ref="4enumIdx">enumIdx</dfn> = <span class="type" title='FooBar' data-ref="FooBar">FooBar</span>::<span class="tu ref" title='FooBar::staticMetaObject' data-use='m' data-ref="FooBar::staticMetaObject">staticMetaObject</span>.<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject17indexOfEnumeratorEPKc" title='QMetaObject::indexOfEnumerator' data-ref="_ZNK11QMetaObject17indexOfEnumeratorEPKc" data-proj="qtbase">indexOfEnumerator</a>(<q>"Action"</q>);
  <b>return</b> <a class="ref fn fake" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#_ZN6QDebugC1ERKS_" title='QDebug::QDebug' data-ref="_ZN6QDebugC1ERKS_" data-proj="qtbase"></a><span class="local col2 ref" title='dbg' data-ref="2dbg">dbg</span> <a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#_ZN6QDebuglsEPKc" title='QDebug::operator&lt;&lt;' data-ref="_ZN6QDebuglsEPKc" data-proj="qtbase">&lt;&lt;</a> <span class="type" title='FooBar' data-ref="FooBar">FooBar</span>::<span class="tu ref" title='FooBar::staticMetaObject' data-use='m' data-ref="FooBar::staticMetaObject">staticMetaObject</span>.<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject10enumeratorEi" title='QMetaObject::enumerator' data-ref="_ZNK11QMetaObject10enumeratorEi" data-proj="qtbase">enumerator</a>(<span class="local col4 ref" title='enumIdx' data-ref="4enumIdx">enumIdx</span>).<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#_ZNK9QMetaEnum10valueToKeyEi" title='QMetaEnum::valueToKey' data-ref="_ZNK9QMetaEnum10valueToKeyEi" data-proj="qtbase" ">valueToKey</a>(<span class="local col3 ref" title='action' data-ref="3action">action</span>);
}
</pre>

<p>That has been working fine since Qt 4.0, but you have to manually write this operator and it is
a lot of code that is somehow error prone. Most of Qt's own enumerations did not even have such operator.</p>

<h2>The Solution</h2>

<p>I wanted this to be automatic. The problem is that we had no way to get the QMetaObject of the enclosed
QObject (or Q_GADGET) associated with a given enumeration.
We also need the name of the enumeration to be passed as an argument to <code>QMetaObject::indexOfEnumerator</code>.<br/>

Let us suppose we have some magic functions that would do exactly that. (We will see later how to make them):</p>

<pre class="brush: cpp"> 
QMetaObject *qt_getEnumMetaObject(ENUM);
const char *qt_getEnumName(ENUM);
</pre>

<p>We could then do:</p>

<pre class="code"><b>template</b> &lt;<b>typename</b> T&gt;
<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#QDebug" title='QDebug' data-ref="QDebug" data-proj="qtbase">QDebug</a> <dfn class="decl def fn" id="_Zls6QDebugT_" title='operator&lt;&lt;' data-ref="_Zls6QDebugT_"><b>operator</b>&lt;&lt;</dfn>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#QDebug" title='QDebug' data-ref="QDebug" data-proj="qtbase">QDebug</a> <dfn class="local col5 decl" id="5dbg" title='dbg' data-type='QDebug' data-ref="5dbg">dbg</dfn>, T <dfn class="local col6 decl" id="6enumValue" title='enumValue' data-type='T' data-ref="6enumValue">enumValue</dfn>)
{
    <em>const</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase">QMetaObject</a> *<dfn class="local col7 decl" id="7mo" title='mo' data-type='const QMetaObject *' data-ref="7mo">mo</dfn> = qt_getEnumMetaObject(<span class="local col6 ref" title='enumValue' data-ref="6enumValue">enumValue</span>);
    <em>int</em> <dfn class="local col8 decl" id="8enumIdx" title='enumIdx' data-type='int' data-ref="8enumIdx">enumIdx</dfn> = <span class="local col7 ref" title='mo' data-ref="7mo">mo</span>-&gt;<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject17indexOfEnumeratorEPKc" title='QMetaObject::indexOfEnumerator' data-ref="_ZNK11QMetaObject17indexOfEnumeratorEPKc" data-proj="qtbase">indexOfEnumerator</a>(qt_getEnumName(<span class="local col6 ref" title='enumValue' data-ref="6enumValue">enumValue</span>));
    <b>return</b> <span class="local col5 ref" title='dbg' data-ref="5dbg">dbg</span> &lt;&lt; <span class="local col7 ref" title='mo' data-ref="7mo">mo</span>-&gt;<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject10enumeratorEi" title='QMetaObject::enumerator' data-ref="_ZNK11QMetaObject10enumeratorEi" data-proj="qtbase">enumerator</a>(<span class="local col8 ref" title='enumIdx' data-ref="8enumIdx">enumIdx</span>).<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#_ZNK9QMetaEnum10valueToKeyEi" title='QMetaEnum::valueToKey' data-ref="_ZNK9QMetaEnum10valueToKeyEi" data-proj="qtbase">valueToKey</a>(<span class="local col6 ref" title='enumValue' data-ref="6enumValue">enumValue</span>);
}
</pre>

<p><a href="http://en.cppreference.com/w/cpp/language/adl">Argument dependent lookup (ADL)</a> will find the right overload for
<code>qt_getEnumMetaObject</code> and <code>qt_getEnumName</code>, and this function will work.
The problem is that this template will match any type, even the ones that are not enumerations or that are not registered with <code>Q_ENUM</code> for which <code>qt_getEnumMetaObject(enum)</code> would not compile.
We have to use <a href="http://en.cppreference.com/w/cpp/language/sfinae">SFINAE</a> (substitution failure is not an error)
to enable this operator only if <code>qt_getEnumMetaObject(enum)</code> compiles:</p>

<pre class="code"><b>template</b> &lt;<b>typename</b> T&gt;
<b>typename</b> <span class="namespace">QtPrivate::</span><a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/global/qglobal.h.html#QtPrivate::QEnableIf" title='QtPrivate::QEnableIf' data-ref="QtPrivate::QEnableIf" data-proj="qtbase" ">QEnableIf</a>&lt;<span class="namespace">QtPrivate::</span><a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetatype.h.html#QtPrivate::IsQEnumHelper" title='QtPrivate::IsQEnumHelper' data-ref="QtPrivate::IsQEnumHelper" data-proj="qtbase" ">IsQEnumHelper</a>&lt;T&gt;::Value , <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#QDebug" title='QDebug' data-ref="QDebug" data-proj="qtbase">QDebug</a>&gt;::Type
<dfn class="decl def fn" id="_Zls6QDebugT_" title='operator&lt;&lt;' data-ref="_Zls6QDebugT_"><b>operator</b>&lt;&lt;</dfn>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#QDebug" title='QDebug' data-ref="QDebug" data-proj="qtbase">QDebug</a> <dfn class="local col9 decl" id="9dbg" title='dbg' data-type='QDebug' data-ref="9dbg">dbg</dfn>, T <dfn class="local col0 decl" id="10enumValue" title='enumValue' data-type='T' data-ref="10enumValue">enumValue</dfn>)
{
    <em>const</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase">QMetaObject</a> *<dfn class="local col1 decl" id="11mo" title='mo' data-type='const QMetaObject *' data-ref="11mo">mo</dfn> = qt_getEnumMetaObject(<span class="local col0 ref" title='enumValue' data-ref="10enumValue">enumValue</span>);
    <em>int</em> <dfn class="local col2 decl" id="12enumIdx" title='enumIdx' data-type='int' data-ref="12enumIdx">enumIdx</dfn> = <span class="local col1 ref" title='mo' data-ref="11mo">mo</span>-&gt;<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject17indexOfEnumeratorEPKc" title='QMetaObject::indexOfEnumerator' data-ref="_ZNK11QMetaObject17indexOfEnumeratorEPKc" data-proj="qtbase">indexOfEnumerator</a>(qt_getEnumName(<span class="local col0 ref" title='enumValue' data-ref="10enumValue">enumValue</span>));
    <b>return</b> <span class="local col9 ref" title='dbg' data-ref="9dbg">dbg</span> &lt;&lt; <span class="local col1 ref" title='mo' data-ref="11mo">mo</span>-&gt;<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject10enumeratorEi" title='QMetaObject::enumerator' data-ref="_ZNK11QMetaObject10enumeratorEi" data-proj="qtbase">enumerator</a>(<span class="local col2 ref" title='enumIdx' data-ref="12enumIdx">enumIdx</span>).<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#_ZNK9QMetaEnum10valueToKeyEi" title='QMetaEnum::valueToKey' data-ref="_ZNK9QMetaEnum10valueToKeyEi" data-proj="qtbase">valueToKey</a>(<span class="local col0 ref" title='enumValue' data-ref="10enumValue">enumValue</span>);
}
</pre>

<p>
QEnableIf is the same as <a href="http://en.cppreference.com/w/cpp/types/enable_if">std::enable_if</a>
and <a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetatype.h.html#QtPrivate::IsQEnumHelper">IsQEnumHelper</a> is implemented this way:
</p>

<pre class="code"><b>namespace</b> <span class="namespace">QtPrivate</span> {
<b>template</b>&lt;<b>typename</b> T&gt; <em>char</em> <dfn class="tu decl fn" id="_ZN12_GLOBAL__N_19QtPrivate20qt_getEnumMetaObjectERKT_" title='(anonymous namespace)::QtPrivate::qt_getEnumMetaObject' data-type='char (anonymous namespace)::QtPrivate::qt_getEnumMetaObject(const T &amp; )' data-ref="_ZN12_GLOBAL__N_19QtPrivate20qt_getEnumMetaObjectERKT_">qt_getEnumMetaObject</dfn>(<em>const</em> T&amp;);

<b>template</b>&lt;<b>typename</b> T&gt;
<b>struct</b> <dfn class="tu type def" id="(anonymousnamespace)::QtPrivate::IsQEnumHelper" title='(anonymous namespace)::QtPrivate::IsQEnumHelper' data-ref="(anonymousnamespace)::QtPrivate::IsQEnumHelper">IsQEnumHelper</dfn> {
  <em>static</em> <em>const</em> T &amp;<dfn class="tu decl fn" id="_ZN12_GLOBAL__N_19QtPrivate13IsQEnumHelper7declvalEv" title='(anonymous namespace)::QtPrivate::IsQEnumHelper::declval' data-type='static const T &amp; (anonymous namespace)::QtPrivate::IsQEnumHelper::declval()' data-ref="_ZN12_GLOBAL__N_19QtPrivate13IsQEnumHelper7declvalEv">declval</dfn>();
  <i>// If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject()</i>
<i>  // declared in the Q_ENUM macro will be chosen by ADL, and the return type</i>
<i>  // will be QMetaObject*.</i>
<i>  // Otherwise the chosen overload will be the catch all template function</i>
<i>  // qt_getEnumMetaObject(T) which returns 'char'</i>
  <b>enum</b> {
    <dfn class="tu enum" id="(anonymousnamespace)::QtPrivate::IsQEnumHelper::Value" title='(anonymous namespace)::QtPrivate::IsQEnumHelper::Value' data-type='0' data-ref="(anonymousnamespace)::QtPrivate::IsQEnumHelper::Value">Value</dfn> = <b>sizeof</b>(qt_getEnumMetaObject(<span class="tu ref fn" title='(anonymous namespace)::QtPrivate::IsQEnumHelper::declval' data-use='c' data-ref="_ZN12_GLOBAL__N_19QtPrivate13IsQEnumHelper7declvalEv">declval</span>())) == <b>sizeof</b>(<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase">QMetaObject</a>*)
  };
};
}
</pre>

<p>
So now it all boils down to how to implement the <code>Q_ENUM</code> macro to declare this <code>qt_getEnumMetaObject</code>.
<br />
We need to implement the function <code>qt_getEnumMetaObject</code> in the same namespace as the class. Yet, the macro is used within the class. How can we implement the function in the class? Perhaps using some static function or some template magic? No! We are going to use a <code>friend</code> function. Indeed, it is possible to define a function in a friend declaration. As an illustration:</p>

<pre class="code"><b>namespace</b> <span class="namespace">ABC</span> {
  <b>class</b> <dfn class="type def" id="ABC::FooBar" title='ABC::FooBar' data-ref="ABC::FooBar">FooBar</dfn> {
    <b>friend</b> <em>int</em> <dfn class="decl def fn" id="_ZN3ABC3fooEv" title='ABC::foo' data-ref="_ZN3ABC3fooEv">foo</dfn>() { <b>return</b> <var>456</var>; }
  };
}
</pre>

<p><code>foo</code> is in the namespace <code>ABC</code> (or the global namespace if <code>FooBar</code> was not in a namespace).


But the interesting fact is that in the body of that function, the lookup is done within the class's scope:</p>

<pre class="code"><b>class</b> <dfn class="tu type def" id="(anonymousnamespace)::FooBar" title='(anonymous namespace)::FooBar' data-ref="(anonymousnamespace)::FooBar">FooBar</dfn> {
  <b>friend</b> <em>const</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase">QMetaObject</a> *<dfn class="tu decl def fn" id="_ZN12_GLOBAL__N_119getFooBarMetaObjectEv" title='(anonymous namespace)::getFooBarMetaObject' data-type='const QMetaObject * (anonymous namespace)::getFooBarMetaObject()' data-ref="_ZN12_GLOBAL__N_119getFooBarMetaObjectEv">getFooBarMetaObject</dfn>() { <b>return</b> &amp;<span class="tu ref" title='(anonymous namespace)::FooBar::staticMetaObject' data-use='a' data-ref="(anonymousnamespace)::FooBar::staticMetaObject">staticMetaObject</span>; }

  <em>static</em> <em>const</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase">QMetaObject</a> <dfn class="tu decl" id="(anonymousnamespace)::FooBar::staticMetaObject" title='(anonymous namespace)::FooBar::staticMetaObject' data-type='const QMetaObject' data-ref="(anonymousnamespace)::FooBar::staticMetaObject">staticMetaObject</dfn>;
};
</pre>

<p>
This uses the <code>staticMetaObject</code> of the class (as declared in the Q_OBJECT macro).
The function can just be called by <code>getFooBarMetaObject();</code>
(without the <code>FooBar::</code> that would be required if it was a static function instead of a friend).<br/>

With that we can now construct the <code>Q_ENUM</code> macro:</p>

<pre class="brush: cpp"> 
#define Q_ENUM(ENUM) \
    friend constexpr const QMetaObject *qt_getEnumMetaObject(ENUM) noexcept { return &amp;staticMetaObject; } \
    friend constexpr const char *qt_getEnumName(ENUM) noexcept { return #ENUM; }
</pre>

<p>Each instance of this macro will create a new overload of the functions for the given enum type.
However, this needs the ENUM type to be declared when we declare the function.
Therefore we need to put the Q_ENUM macro after the enum declaration.
This also permits only one enum per macro while Q_ENUMS could have several.</p>

<p>(moc will still interpret the <code>Q_ENUM</code> macro like the old <code>Q_ENUMS</code> macro
and generate the same data.)</p>

<p>Using this, I also introduced a new static function <a href="https://doc.qt.io/qt-5/qmetaenum.html#fromType"><code>QMetaEnum::fromType&lt;T&gt;()</code></a> which let you easily get a
QMetaEnum for a given type. This is how it is implemented:</p>

<pre class="code"><b>template</b>&lt;<b>typename</b> T&gt;
<a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#QMetaEnum" title='QMetaEnum' data-ref="QMetaEnum" data-proj="qtbase">QMetaEnum</a> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#QMetaEnum" title='QMetaEnum' data-ref="QMetaEnum" data-proj="qtbase">QMetaEnum</a>::<dfn class="decl def fn" id="_ZN9QMetaEnum8fromTypeEv" title='QMetaEnum::fromType' data-ref="_ZN9QMetaEnum8fromTypeEv">fromType</dfn>()
{
  <em>const</em> <a class="type" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#QMetaObject" title='QMetaObject' data-ref="QMetaObject" data-proj="qtbase">QMetaObject</a> *<dfn class="local col3 decl" id="13metaObject" title='metaObject' data-type='const QMetaObject *' data-ref="13metaObject">metaObject</dfn> = qt_getEnumMetaObject(T());
  <em>const</em> <em>char</em> *<dfn class="local col4 decl" id="14name" title='name' data-type='const char *' data-ref="14name">name</dfn> = qt_getEnumName(T());
  <b>return</b> <span class="local col3 ref" title='metaObject' data-ref="13metaObject">metaObject</span>-&gt;<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject10enumeratorEi" title='QMetaObject::enumerator' data-ref="_ZNK11QMetaObject10enumeratorEi" data-proj="qtbase">enumerator</a>(<span class="local col3 ref" title='metaObject' data-ref="13metaObject">metaObject</span>-&gt;<a class="ref fn" href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobjectdefs.h.html#_ZNK11QMetaObject17indexOfEnumeratorEPKc" title='QMetaObject::indexOfEnumerator' data-ref="_ZNK11QMetaObject17indexOfEnumeratorEPKc" data-proj="qtbase">indexOfEnumerator</a>(<span class="local col4 ref" title='name' data-ref="14name">name</span>));
}
</pre>

<p>
We can also integrate it with <code>QMetaType</code> to register this type automatically and register the
correspding meta object to the metatype system.
From that, we can use this information in <code>QVariant</code> to convert from a string or to a string.
</p>


<p>(Note: The code snippets shown were slightly simplified for the purpose of the blog.
Check the real implementation of <a href="https://code.woboq.org/qt5/qtbase/src/corelib/io/qdebug.h.html#_Z26qt_QMetaEnum_debugOperatorR6QDebugiPK11QMetaObjectPKc">the debug <code>operator&lt;&lt;</code></a>,
or <a href="https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qmetaobject.h.html#_ZN9QMetaEnum8fromTypeEv"><code>QMetaEnum::fromType</code></a>, or <a href="https://code.woboq.org/qt5/qtbase/src/testlib/qtestcase.h.html#_ZN5QTest8Internal8toStringET_"><code>QTest::toString</code></a>.</p>


<h2>Conclusion</h2>

<p><code>Q_ENUM</code> is like the old <code>Q_ENUMS</code> but with those differences:</p>

<ul>
<li>It needs to be placed after the enum in the source code.</li>
<li>Only one enum can be put in the macro.</li>
<li>It enables <a href="https://doc.qt.io/qt-5/qmetaenum.html#fromType"><code>QMetaEnum::fromType&lt;T&gt;()</code></a>.</li>
<li>These enums are automatically declared as a QMetaTypes (no need to add them in <code>Q_DECLARE_METATYPE</code> anymore).</li>
<li>enums passed to qDebug will print the name of the value rather than the number.</li>
<li>When put in a QVariant, <code>toString</code> gives the value name.</li>
<li>The value name is printed by <a href="https://doc.qt.io/qt-5/qtest.html#QCOMPARE">QCOMPARE</a> (from Qt 5.6).</li>
</ul>

<p>You can read more articles about Qt internals <a href="https://woboq.com/blog/">on our blog</a>.</p>
 
]]></description></item>
<item><title>GPU drawing using ShaderEffects in QtQuick</title><link>https://woboq.com/blog/gpu-drawing-using-shadereffects-in-qtquick.html</link><guid>http://woboq.com/blog/gpu-drawing-using-shadereffects-in-qtquick.html</guid><pubDate>Mon, 11 May 2015 13:35:10 GMT</pubDate><description><![CDATA[<div class="intro">
    <p>A <a href="https://doc.qt.io/qt-5/qml-qtquick-shadereffect.html">ShaderEffect</a> is a QML item that takes a GLSL shader program allowing applications to render using the GPU directly. Using only property values as input <a href="animations-using-the-qtquick-canvas.html">as with the Canvas in our previous article</a>, we will show how a ShaderEffect can be used to generate a different kind visual content, with even better performances. We will also see how we can use the fluidity it provides in user interface designs, again taking Google's Material Design as a concrete example.</p>
</div>
<h2>Quick introduction</h2>
<h3>The fragment (pixel) shader</h3>
<p>This can be a difficult topic, but all you need to know for now is that correctly typed QML properties end up in your shader's <code>uniform</code> variables of the same name and that the <a href="https://doc.qt.io/qt-5/qml-qtquick-shadereffect.html#vertexShader-prop">default vertex shader</a> will output (0, 0) into the <code>qt_TexCoord0</code>
    <code>varying</code> variable for the top-left corner and (1, 1) at the bottom-right. Since different values of the vertex shader outputs will be interpolated into the fragment shader program inputs, each fragment will receive a different <code>qt_TexCoord0</code> value, ranging from (0, 0) to (1, 1). The fragment shader will rasterize our rectangular geometry by running once for every viewport pixel it intersects and the output value of <code>gl_FragColor</code> will then be blended onto the window according to its alpha value.</p>
<p>This article won't be talking about the vertex shader, the default one will do fine in our situation. I also encourage you to eventually read available tutorials out there about shaders and the OpenGL pipeline if you want to write your own.</p>
<h3>A basic example</h3>
<img class="screenshot" src="https://woboq.com/blog/gpu-drawing-using-shadereffects-in-qtquick/simple.gif"/>
<pre class="brush: qml">
import QtQuick 2.0
ShaderEffect {
    width: 512; height: 128
    property color animatedColor
    SequentialAnimation on animatedColor {
        loops: Animation.Infinite
        ColorAnimation { from: "#0000ff"; to: "#00ffff"; duration: 500 }
        ColorAnimation { from: "#00ffff"; to: "#00ff00"; duration: 500 }
        ColorAnimation { from: "#00ff00"; to: "#00ffff"; duration: 500 }
        ColorAnimation { from: "#00ffff"; to: "#0000ff"; duration: 500 }
    }

    blending: false
    fragmentShader: "
        varying mediump vec2 qt_TexCoord0;
        uniform lowp float qt_Opacity;
        uniform lowp vec4 animatedColor;

        void main() {
            // Set the RGBA channels of animatedColor as our fragment output
            gl_FragColor = animatedColor * qt_Opacity;

            // qt_TexCoord0 is (0, 0) at the top-left corner, (1, 1) at the
            // bottom-right, and interpolated for pixels in-between.
            if (qt_TexCoord0.x &lt; 0.25) {
                // Set the green channel to 0.0, only for the left 25% of the item
                gl_FragColor.g = 0.0;
            }
        }
    "
}
</pre>
<p>This animates an <code>animatedColor</code> property through a regular QML animation. Any change to that property, through an animation or not, will <a href="https://code.woboq.org/qt5/qtdeclarative/src/quick/items/qquickshadereffect.cpp.html#_ZN18QQuickShaderEffect15propertyChangedEi">automatically trigger an update of the ShaderEffect</a>. Our fragment shader code then directly sets that color in its <code>gl_FragColor</code> output, for all fragments. To show something slightly more evolved than a plain rectangle, we clear the green component of some fragments based on their <code>x</code> position within the rectangle, leaving only the blue component to be animated in that area.</p>
<h3>Parallel processing and reduced shared states</h3>
<p>One of the reasons that graphics hardware can offer so much rendering power is that it offers no way to share or accumulate states between individual fragment draws. Uniform values are shared between all triangles included in a GL draw call. Every per-fragment state first has to go through the vertex shader.</p>
<p>In the case of the ShaderEffect, this means that we are limited to <code>qt_TexCoord0</code> to differentiate pixels. The drawing logic can only be based on that input using <b>mathematic formulas</b> or <b>texture sampling</b> of an Image or a ShaderEffectSource.</p>
<h2>Using it for something useful</h2>
<p>Even though this sounds like trying to render something on a graphing calculator, some can achieve incredibly good looking effects with those limited inputs. Have a look at <a href="https://www.shadertoy.com">Shadertoy</a> to see what others are doing with equivalent APIs within WebGL.</p>
<h3>Design and implementation</h3>
<p>Knowing what we can do with it allows us to figure out ways of using this in GUIs to give smooth and responsive feedback to user interactions. Using Android's Material Design as a great example, let's try to implement a variant of their <a href="http://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-user-input">touch feedback visual effect</a>.</p>
<p>
This is how the implementation looks like. The rendering is more complicated but the concepts is essentially similar to the simple example above. The fragment shader will first set the fragment to the hard-coded <code>backgroundColor</code>, calculate if the current fragment is within our moving circle according to the <code>normTouchPos</code> and animated <code>spread</code> uniforms and finally apply the ShaderEffect's <a href="https://doc.qt.io/qt-5/qml-qtquick-item.html#opacity-prop">opacity</a> through the built-in <code>qt_Opacity</code> uniform:</p>
<img class="screenshot" src="https://woboq.com/blog/gpu-drawing-using-shadereffects-in-qtquick/waveoverlay.gif"/>
<pre class="brush: qml">
import QtQuick 2.2
ShaderEffect {
    id: shaderEffect
    width: 512; height: 128

    // Properties that will get bound to a uniform with the same name in the shader
    property color backgroundColor: "#10000000"
    property color spreadColor: "#20000000"
    property point normTouchPos
    property real widthToHeightRatio: height / width
    // Our animated uniform property
    property real spread: 0
    opacity: 0

    ParallelAnimation {
        id: touchStartAnimation
        UniformAnimator {
            uniform: "spread"; target: shaderEffect
            from: 0; to: 1
            duration: 1000; easing.type: Easing.InQuad
        }
        OpacityAnimator {
            target: shaderEffect
            from: 0; to: 1
            duration: 50; easing.type: Easing.InQuad
        }
    }

    ParallelAnimation {
        id: touchEndAnimation
        UniformAnimator {
            uniform: "spread"; target: shaderEffect
            from: spread; to: 1
            duration: 1000; easing.type: Easing.OutQuad
        }
        OpacityAnimator {
            target: shaderEffect
            from: 1; to: 0
            duration: 1000; easing.type: Easing.OutQuad
        }
    }

    fragmentShader: "
        varying mediump vec2 qt_TexCoord0;
        uniform lowp float qt_Opacity;
        uniform lowp vec4 backgroundColor;
        uniform lowp vec4 spreadColor;
        uniform mediump vec2 normTouchPos;
        uniform mediump float widthToHeightRatio;
        uniform mediump float spread;

        void main() {
            // Pin the touched position of the circle by moving the center as
            // the radius grows. Both left and right ends of the circle should
            // touch the item edges simultaneously.
            mediump float radius = (0.5 + abs(0.5 - normTouchPos.x)) * 1.0 * spread;
            mediump vec2 circleCenter =
                normTouchPos + (vec2(0.5) - normTouchPos) * radius * 2.0;

            // Calculate everything according to the x-axis assuming that
            // the overlay is horizontal or square. Keep the aspect for the
            // y-axis since we're dealing with 0..1 coordinates.
            mediump float circleX = (qt_TexCoord0.x - circleCenter.x);
            mediump float circleY = (qt_TexCoord0.y - circleCenter.y) * widthToHeightRatio;

            // Use step to apply the color only if x2*y2 &lt; r2.
            lowp vec4 tapOverlay =
                spreadColor * step(circleX*circleX + circleY*circleY, radius*radius);
            gl_FragColor = (backgroundColor + tapOverlay) * qt_Opacity;
        }
    "

    function touchStart(x, y) {
        normTouchPos = Qt.point(x / width, y / height)
        touchEndAnimation.stop()
        touchStartAnimation.start()
    }
    function touchEnd() {
        touchStartAnimation.stop()
        touchEndAnimation.start()
    }

    // For this demo's purpose, in practice we'll use a MouseArea
    Timer { id: touchEndTimer; interval: 125; onTriggered: touchEnd() }
    Timer {
        running: true; repeat: true
        onTriggered: {
            touchStart(width*0.8, height*0.66)
            touchEndTimer.start()
        }
    }
}
</pre>
<h3>Explicit animation control through start() and stop()</h3>
<p>One particularity is that we are controlling Animations manually on input events instead of using states. This gives us more flexibility in order to stop animations immediately when changing states.</p>
<h3>The mighty Animators</h3>
<p>Some might have noticed the use of <a href="https://doc.qt.io/qt-5/qml-qtquick-uniformanimator.html">UniformAnimator</a> and <a href="https://doc.qt.io/qt-5/qml-qtquick-opacityanimator.html">OpacityAnimator</a> instead of a general <a href="https://doc.qt.io/qt-5/qml-qtquick-numberanimation.html">NumberAnimation</a>. The major difference between <a href="https://doc.qt.io/qt-5/qml-qtquick-animator.html">Animator</a> and <a href="https://doc.qt.io/qt-5/qml-qtquick-propertyanimation.html">PropertyAnimation</a> derived types is that animators won't report intermediate property values to QML, only once the animation is over.</p>
<p>Property bindings or long IO operations on the main thread won't be able to get in the way of the render thread to compute the next frame of the animation.</p>
<p>When using ShaderEffects, a UniformAnimator will provide the quickest rendering loop you can get. Once your declaratively prepared animation is initialized by the main thread and sent over to the QtQuick render thread to be processed, the render thread will take care of computing the next animation value in C++ and trigger an update of the scene, telling the GPU to use that new value through OpenGL.</p>
<p>Apart from the possibility of a few delayed animation frames caused by the thread synchronization, Animators will take the same input and behave just like other Animations.</p>
<h2>Resource costs and performance</h2>
<p>ShaderEffects are often depicted with their resource hungry brother, the <a href="https://doc.qt.io/qt-5/qml-qtquick-shadereffectsource.html">ShaderEffectSource</a>, but when a ShaderEffect is used alone to generate visual content like we're doing here, it has very little overhead.

Unlike the Canvas, ShaderEffect instances also don't each own an expensive framebuffer object. It can be instantiated in higher quantities without having to worry about their cost. <a href="https://code.woboq.org/qt5/qtdeclarative/src/quick/items/qquickshadereffectnode_p.h.html#QQuickShaderEffectMaterialKey">All instance of a QML Component having the same shader source string</a> will use the same shader program. All instances sharing the <a href="https://code.woboq.org/qt5/qtdeclarative/src/quick/items/qquickshadereffectnode.cpp.html#_ZNK26QQuickShaderEffectMaterial7compareEPK11QSGMaterial">same uniform values</a> will usually be <a href="https://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph-renderer.html#batching">batched</a> in the same draw call. Otherwise the cost of a ShaderEffect instance is the little memory used by its vertices and the processing that they require on the GPU. The complexity of the shader itself is the bottleneck that you might hit.</p>
<h3>Selectively enable blending</h3>
<p>
    <a href="https://doc.qt.io/qt-5/qml-qtquick-shadereffect.html#blending-prop">Blending</a> requires extra work from the GPU, <a href="https://code.woboq.org/qt5/qtdeclarative/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp.html#_ZN16QSGBatchRenderer8Renderer19prepareAlphaBatchesEv">prevents batching of overlapping items</a>. It also means that the GPU needs to render the fragments of the Items hidden behind, which it could otherwise just ignore using depth testing.</p>
<p>It is enabled by default to make it work out of the box and it's up to you to disable it if you know that your shader will always output fully opaque colors. Note that a <code>qt_Opacity &lt; 1.0</code>
    <a href="https://code.woboq.org/qt5/qtdeclarative/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp.html#_ZN16QSGBatchRenderer8Renderer16buildRenderListsEP7QSGNode">will trigger blending automatically</a>, regardless of this property. The simple example above disables it but our translucent touch feedback effect needs to leave it enabled.</p>
<h2>Should I use it?</h2>
<p>The ShaderEffect is simple and efficient, but in practice you might find that it's not always possible to do what you want with the default mesh and limited API available through QML.</p>
<p>Also note that a using ShaderEffects requires OpenGL. <a href="http://www.mesa3d.org/llvmpipe.html">Mesa llvmpipe</a> supports them, an OpenGL ES2 shader will ensure compatibility with ANGLE on Windows, but you will need fallback QML code if you want to deploy your application with the <a href="https://doc.qt.io/QtQuick2DRenderer/">QtQuick 2D Renderer</a>.</p>
<p>If you need that kind of performance you might already want to go a step further, <a href="https://doc.qt.io/qt-5/qquickitem.html#updatePaintNode">subclass QQuickItem</a> and use your shader program directly through the <a href="https://doc.qt.io/qt-5/qsgsimplematerialshader.html">public scene graph API</a>. It will involve writing more C++ boilerplate code, but in return you get direct access to parts of the OpenGL API. However, even with that goal in mind, the ShaderEffect will initially allow you to write a shader prototype in no time, giving you the possibility to reuse the shader if you need a more sophisticated wrapper later on.</p>
<h2>Try it out</h2>
<p>Those animated GIFs aren't anywhere near 60 FPS, so feel free to copy this code into a qml file (or clone <a href="https://github.com/woboq/canvas_shadereffect_animations">this repository</a>) and load it in qmlscene if you would like to experience it properly. Let us know what you think.</p>
]]></description></item>
</channel></rss>