Morten Johan Sørvig
Qt
 in Qt
 on Monday, August 31, 2009 @ 12:20

Mac OS X Snow Leopard was released on friday, Qt 4.6 is on its way - The 4.6 branch has been created at gitorious.org. What’s new?

First of all we’re rolling the OS Support window: support for 10.3 Panther has been removed and support for 10.6 Snow Leopard has been added. This means that Qt 4.6 on Mac OS X will support three versions of the operating system(10.4 - 10.6), four different architectures (ppc/ppc64/i386/x86_64) and two toolkits (Carbon/Cocoa). About half of the OS/arch/toolkit combinations are valid, see developing-on-mac.html for all the details.

Removing 10.3 (Panther) support
With Qt 4.5 we removed support for gcc 3.3, making Qt deploy-only on Panther. We’re now removing run-time support as well. This allows us to remove a bit of code (Qt 4.5 contains around 60 10.3-spesific code paths), and also frees up developer, support and QA resources to focus on the newer platforms. In addition, our 10.3 testing machine here at the Oslo office is showing its age and is ready for retirement.

Adding 10.6 (Snow Leopard) support
From a developer viewpoint the biggest change in this release is more 64-bitness. Most(all?) of the bundled apps are 64-bit, and the gcc compiler produces x86_64 binaries by default. Qt follows suit and is also 64-bit by default when building for Cocoa (Select this with the -cocoa flag at the configure line or use the -arch x86_64 flag). Apple has also updated to gcc 4.2, which renders the macx-g++42 mkspec obsolete. Compiling for ppc64 is no longer supported by the gcc tool chain. Other than that developing on 10.6 is much the same, and we can all enjoy the new Exchange support in Mail.

Planning Ahead

Maintaining two ports is not sustainable in the long run, so the Carbon port is eventually going to be dropped. It is however our only means of supporting Tiger and legacy Qt3-based code, which suggests that we should keep it around for at least little bit longer. PPC support is not a big issue, the build infrastructure for it is there and the PPC-only bugs are few and far between. That being said, at some point in the future we’ll probably end up supporting x86_64/Cocoa only. Unless something new we can port to appears in the mean time :)

So, here’s the conclusion with a tentative plan:

  • this release (4.6) - Drop 10.3 support, add 10.6 support. Qt/Cocoa is 64-bit by default when compiling 10.6.
  • next release - The Cocoa port becomes the default for the Qt source and binary packages
  • next +1 release - Drop Carbon, 10.4 (Tiger) support and Qt3Support.
  • kamlie
    Qt
    Posted by kamlie
     in Qt
     on Monday, August 31, 2009 @ 10:58

    While the S60 port was going on, it became clear to us that there was something that Qt needed: A proper API for dealing with input panels (also called virtual keyboards). For the S60 platform the motivation was obvious, since most touch phones use some sort of on-screen keyboard. But we also wanted to make the API in such a way that it could be used by developers on other platforms, which is useful for kiosks or desktop machines with touch screens.

    The API itself is an extension to the QInputContext class, which already deals with input methods, and is actually really simple: Two new events that tell you when to open the panel and when to close it, RequestSoftwareInputPanel and CloseSoftwareInputPanel. All Qt’s input widgets support these events and will send them when appropriate. As for how to deliver events from the panel to the widget? Well, that’s already there in the form of QInputMethodEvents.

    What the input panel developer then needs to do is to make a class which subclasses QInputContext, and in the filterEvent() function you look for the events which tell you show or hide your input widget. If you want to have extra control over what type of input can be used (so the input panel can show only numbers, for example), check out the new inputMethodHints property of QWidget. This property is fully editable in Qt Designer, and some widgets already use it automatically, such as QSpinBox which sets it to numbers only.

    Check out the example in Git under examples/tools/inputpanel! It’s also documented at http://doc.trolltech.com/4.6-snapshot/tools-inputpanel.html.

    QtMobility
    QtMobility
    Posted by QtMobility
     in QtMobility
     on Monday, August 31, 2009 @ 04:42

    As part of the Qt Mobility project, we are introducing a Location API to provide components for distributing and receiving location-related data.

    What is location data? It’s the data provided by technologies like GPS, Mobile Cell Identification and WLAN positioning that allows you to pinpoint your exact location on the surface of the Earth (or pretty close to it, anyway). It’s the data that lets you drive with in-car navigation, track your running routes via SportsTracker, find your friends with Google Latitude and play location-based games like Pac-Manhattan and GeoCaching. With the advances in positioning hardware and network-based positioning methods, location services have become increasingly popular and are now commonly found on mobile and embedded devices.

    In the Location API, we provide an architecture for distributing location data to multiple clients and a simple way for clients to request and receive location data. There are also components for coordinate calculations, reading NMEA data and distributing satellite data. The API is focused on providing the essential components for location data sharing and does not involve more advanced location services like geocoding and mapping capabilities.

    Here’s the basic structure of the API. The light blue boxes indicate components that can be used to implement custom location engines.

    Location API diagram

    On mobile platforms with built-in location capabilities such as GPS, we plan to provide access to these default capabilities through the Location API. On platforms that have no built-in location services, developers can write custom location data sources using the Location API.

    Check out the source at http://qt.gitorious.org/qt-mobility/location which includes an example for writing custom data sources. You’ll also find an example that parses NMEA data and displays the parsed coordinates using Google Maps and QtWebKit. Here’s a screenshot of the latter example:

    Location demo screenshot

    We plan to add other components such as landmarks storage in future releases, so watch this space. As always, feedback is welcome at qtmobility at trolltech.com.

    Comments Off
    Thomas Zander
    KDE
    KOffice
    Posted by Thomas Zander
     in KDE, KOffice
     on Friday, August 28, 2009 @ 17:18

    Its been some months since we released KOffice2.0.0, the first official release for the new platform KOffice2.
    For common and certainly for advanced office users we made clear that 2.0 is missing features for them. What then, you may ask, is 2.1 going to change for them?
    Well, here is what we are working on and what has been integrated into what will become the 2.1 release in a month or two.

    Tables
    Releasing a word processor without tables was pretty daring, and for 2.1 we did a lot of work to correct this. As part of the GSoC project we got Elvis Stansvik working on this for the whole summer. As this is part of KWord, I was the mentor and near the end we also got help from Casper Boemann. The end result is that KWord can show a huge set of tables based documents correctly. Its important to point out that this is ongoing work; creating new table cells or modifying the shape and look of a table is currently not possible.

    Change Tracking
    While editing a text document you can always undo your changes and get back to the way your document looked before. But what if you want to show the actual changes made right inside the current document? Or even better, being able to see what your colleague changed in the document over the weekend. This is what change tracking offers and this has been integrated just last week and it looks like we’ll have most of the expected features available in 2.1 thanks to the work of Pierre Stirnweiss. The most exciting part is that this lays the foundations for projects like collaborative editing.

    Improved image handling
    This has been detailed in another post already, so I’ll keep it short. For 2.1 the images handling has been made faster and we now are much smarter with memory usage so its possible to have image-heavy documents showing just fine even on memory constrained systems and devices.

    Continued improvement in OpenDocument Format (ODF) support
    ODF is still a huge specification and during the 2.1 time-frame there have been various teams working on testing and improving KOffice to become both better at writing correct and full ODF as well as reading other applications ODF documents. As ODF is a way to inter-operate between different application suites so its obvious that the way to get better ODF support is to collaborate on this front with others.
    KOffice has been working at the front-lines with the industry big names for some time now. A recent example is the plugfest in The Netherlands last summer and the upcoming plugfest in Italy where KOffice is well represented.
    An exciting initiative is the officeshots which renders an ODF document in all available office applications and shows the output. KOffice has been working with the OpenDoc Society to provide hardware and software support and make sure KOffice interoperability can be verified by everyone.

    KFormula major improvements.
    The formula editing component in KOffice has seen many upgrades since the 2.0 release. This means that all KOffice applications can now display and directly edit formulas. The GSoC project by Jeremias Epperlein has seen improvements specifically in rendering the formulas much more pleasing to the eye and the editing of a formula is well integrated into KOffice and quite easy to use.

    Windows
    At the tagging of the beta1 all of KOffice compiled without problems on visual studio 2008 which significantly lowers the barrier to developer and end user adoption of KOffice. We are still looking for enthusiastic packagers and naturally developers on this platform to help improve the experience for end users.

    MSOffice support
    Still quite important for many is the ability to open MSOffice documents correctly and the major painpoints are one by one being addressed. Major things like importing text correctly, importing tables and importing images in presentations have been added for 2.1.

    Harald Fernengel
    Qt
     in Qt
     on Tuesday, August 25, 2009 @ 21:17

    Instead of answering all the comments about QScopedPointer, I decided it’s easier to post a follow-up post :) Thanks to Thiago’s blog, the differences between the various smart and not so smart pointers should hopefully be clearer now.

    Using QScopedPointer instead of std::auto_ptr or boost’s scoped pointer has nothing to do with not-invented-here syndrome. Very early during our API discussions we realized that delete-on-end-of-scope was not enough, we also needed custom cleanup handlers. Take QBrush as example - extra magic is required when deleting the private object. The other pointer classes did not offer that functionality, so they were ruled out.

    Why did we make the custom deleters a template argument, and not simply a function pointer member in the class? This has two reasons. Firstly, we didn’t want any penalty from using QScopedPointer over manual new/delete. Setting an extra pointer, and calling it in the destructor would have introduced an extra overhead. Secondly, due to our binary compatibility policy, the size of QScopedPointer must be sizeof(void*), so adding another member variable was not possible.

    Custom cleaners can be very useful - you can basically use QScopedPointer for any cleanup when leaving scope, for example to close a handle, decrease some reference count, call a custom free function and so on.

    Still not in love with QScopedPointer? Let’s look at the following, then:

    class ForwardDeclared;
    extern ForwardDeclared *myFunc();
    
    …
    std::auto_ptr<ForwardDeclared> ptr(myFunc());
    

    It compiles, but you’ll get a nasty surprise at runtime - since the class is only forward declared, its destructor will not be called on deletion! QScopedPointer has extra protection, forcing a compilation error in the case above.

    To make sure that you can write if (myScopedPointer) …, we had to introduce an operator bool() - but that would also enable writing int x = myScopedPointer;, due to the implicit boolean to integer conversion. Thankfully, we found that issue during an API review, so the latter case will now not compile.

    Still not deeply in love with QScopedPointer? Good news - it’s all template code, all inline, so there’s no penalty to Qt’s library size or runtime behavior if you choose to ignore our little gem :)

    Alexandra
    News
    Posted by Alexandra
     in News
     on Tuesday, August 25, 2009 @ 17:36

    Our friends in Brazil have released PySide, Python bindings for Qt.

    PySide is a project that is run by INdT and sponsored by Nokia that provides Python bindings for Qt under the LGPL. These bindings are currently in pre-release form and only support Linux/X11, however the PySide team is hoping the community would be interested in helping to make the bindings cross-platform. The team is happily awaiting your feedack and contributions.

    Head over to PySide.org and learn more.

    Ariya Hidayat
    WebKit
    Graphics Dojo
    Posted by Ariya Hidayat
     in WebKit, Graphics Dojo
     on Tuesday, August 25, 2009 @ 15:00

    Influenced by Holger and Simon, I decided to use S5 for my presentation at the Desktop Summit in Gran Canaria few weeks ago. It’s purely based on web technologies, it works in modern web browsers. More information is available at the official website, including demos, even with different styles and effects. Thanks to the use of web technologies, you can even create the slides online.


    For the fun of it, instead of just using a web browser (so boring!), I wrote a simple QtWebKit-based tool to run the slide shows, dubbed s5runner. The code is checked in already to the Graphics Dojo repository. Beside just launching the slide shows in a QWebView, the 200-lines C++ code adds a few more goodies (although arguably, all these extra stuff can be implemented in pure HTML/CSS/JavaScript instead). Run the program and open the included slides.html (in the example sub-directory), or just enjoy the following 2-minute screencast:

    A countdown timer (currently hard-coded to 30 minutes) is installed at the bottom right corner. The screen can be blanked temporarily to black or white, useful when you want to steal the focus of the audience from the slides. Going full-screen (and back again) is also easy, this is important if you’d like to show some live demos during the talk. The slides look ugly due to the aging or faulty projector? Use the night-mode, something you have seen in the previous OpenStreetMap example.

    When doing a talk about programming, it is often unavoidable to show code snippet. Thanks to Chili, the jQuery code highlighter plugin (there are other alternatives to pick:
    prettify, syntaxhighlighter, and many others), you will get the highlighting feature with zero effort. It’s quite useful as the code fragment (which you likely show only for a few seconds) becomes more understandable. My favorite is however the live-editing feature, just press F3 to start editing the slide while you are showing it at the same time.

    If you like this presentation tool, feel free to extend it. For example, you can have more presentation effects, like pulsating or shaking, by using script.aculo.us-based Presentacular. This example tool only supports basic editing, but I have shown a WYSIWYG HTML Editor before, so you can augment its editing features to support e.g. inserting images from the disk, changing character and paragraph styles, and so on. And of course, support for PDF export (with one slide per page) will be just very nice. A PowerPoint-killer, anyone?

    Thiago Macieira
    Qt
    Posted by Thiago Macieira
     in Qt
     on Tuesday, August 25, 2009 @ 06:56

    On Friday, along with the Qt for Symbian integration, we got a new smart pointer class in Qt, called QScopedPointer. Harald, one of the class’s author, blogged about it, which prompted a lot of comments asking why we have those classes and what’s the difference between the ones we have.

    Before we can find out why we have those classes, we need to know the classes we have. So, count with me, in chronological order:

    1. QPointer (4.0)
    2. QSharedDataPointer (4.0)
    3. QExplicitlySharedDataPointer (4.3/4.4)
    4. QtPatternist::AutoPtr (internal class, 4.4)
    5. QSharedPointer (4.5)
    6. QWeakPointer (4.5)
    7. QGuard (internal class, 4.6)
    8. QScopedPointer (4.6)

    Note: QExplicitlySharedDataPointer was introduced in 4.3, but the API was made public and documented in 4.4

    That many, huh?

    Each and every case has its use and they all (except one) are still valid today.

    Shared pointer versus shared data

    First, let’s get one thing straight: there’s a difference between sharing pointers and sharing data. When you share pointers, the value of the pointer and its lifetime is protected by the smart pointer class. In other words, the pointer is the invariant. However, the object that the pointer is pointing to is completely outside its control. We don’t know if the object is copiable or not, if it’s assignable or not.

    Now, sharing of data involves the smart pointer class knowing something about the data being shared. In fact, the whole point is that the data is being shared and we don’t care how. The fact that pointers are being used to share the data is irrelevant at this point. For example, you don’t really care how Qt tool classes are implicitly shared, do you? What matters to you is that they are shared (thus reducing memory consumption) and that they work as if they weren’t.

    Strong versus weak pointer referencing

    The difference between a strong and a weak reference is whether the existence of the smart pointer class on a given pointer guarantees that the object will not get deleted. In other words, if you have this smart pointer, are you sure that this will always remain valid (provided, of course, everyone is playing by the same rules)?

    Some of the pointer classes above don’t guarantee that. If they don’t guarantee that the object remains valid, their main purpose in life is to tell you whether the object has been deleted already or not. Some classes may provide an additional feature that allows you to promote a weak pointer to a strong one, thus guaranteeing that it won’t get deleted anymore.

    The Qt smart pointer classes

    1. QPointer

    QPointer is a weak pointer class and it shares the pointer value, not the data. It only operates on QObject and QObject-derived classes. This class was added in Qt 4.0 and is the direct upgrade of Qt 3’s QGuardedPtr (and Qt 2’s QGuardedPtr). Like its predecessors, QPointer suffers from broken constness support and shows its age.

    Its sole purpose in life is to tell you whether the QObject has been deleted already or not. But, unlike Qt 2 and Qt 3, the QObject of Qt 4 can live in several threads. That means QPointer has one serious flaw: it lets you know whether the object has been deleted, but it makes no guarantee about the next line! For example, the following code could be in trouble:

        QPointer<QObject> o = getObject();
    
        // […]
        if (!o.isNull())
            o->setProperty(“objectName”, “Object”);
    

    Even if isNull() returns false, there’s no guarantee that the object won’t get deleted by the next line.

    Therefore, QPointer can only be used to access the object if you can guarantee, by external means, that the object won’t get deleted. For example, QWidget and its descendents can only be created, manipulated and deleted in the GUI thread. If your code is running on the GUI thread or has that thread blocked, then QPointer usage is safe.

    2. QSharedDataPointer

    Now this is a nice little class. It’s actually by far the most important of the smart pointer classes in Qt for its ingeniuty: it provides implicit sharing, with thread-safe copy-on-write. It requires that your class have a member called ref, which offers a function called ref() for increasing the reference count, and another called deref() that decreases that reference count and returns false when it drops to zero. If you derive your class from QSharedData, you get exactly that. Moreover, the size of a QSharedDataPointer object is exactly the size of a pointer. That means you can replace normal pointers with it in your code without breaking Binary Compatibility.

    This class is the basis of all Qt value-type, implicit-shared, thread-safe copy-on-write recent classes, like QNetworkProxy. The only reason why it isn’t used in the base classes like QByteArray, QString and QList is that those classes were developed before this class was made. There’s nothing technically stopping the retrofitting of those classes with QSharedDataPointer.

    So QSharedDataPointer is a strong smart pointer class, sharing data.

    3. QExplicitlySharedDataPointer

    This class is exactly like QSharedDataPointer (so it’s a a strong smart pointer class, sharing data), with the only difference that it never implicitly causes the detach. With QSharedDataPointer, any non-const access will cause the data to be copied. With QExplicitlySharedDataPointer, you have to call detach() for that to happen. This allows you to implement explicitly-shared data classes — which Qt doesn’t have anymore, but Qt 3 did in QMemArray (so it’s present in Qt4’s Qt3Support Q3MemArray).

    But it also allows you to have finer-grained control of the detaching operation. In fact, if the Qt Tool classes were to be retrofitted with a smart pointer class, they’d be using QExplicitlySharedDataPointer instead. Using this class allows the code to delay the detaching until the very last moment, ensuring that no unnecessary memory access happens.

    4. QtPatternist::AutoPtr

    This is an internal class used by the QtXmlPatterns module. It’s basically your stock, dumb pointer wrapper. So it implements a strong pointer. It doesn’t share it, though.

    The reason this class exists in the first place is that the QtXmlPatterns module makes extensive use of exceptions internally. To survive exceptions being thrown without leaking memory, a pointer wrapper is indicated. QtXmlPatterns also uses reference-counted classes, for which AutoPtr is not indicated — in that case, it uses QExplicitlySharedDataPointer.

    5. QSharedPointer

    This class was created as a response to QtPatternist::AutoPtr. When I started writing it, I intended for it to be ready for Qt 4.4 and replace the use of the internal class that Frans had written and what I perceived as a misuse of QExplicitlySharedDataPointer. QtXmlPatterns was using QExplicitlySharedDataPointer not for sharing data, but for sharing pointers. The objects it was sharing were not copiable. A later investigation, however, revealed that QtScript, Phonon, and Solid were using it for the same purpose. (In fact, QtScript introduced QExplicitlySharedDataPointer for that purpose in 4.3)

    So QSharedPointer was shelved for 4.4, but was reborn in 4.5. It implements a strong smart pointer class, sharing the pointer. It has all the features you may want in a modern pointer class: it is polymorphic, it supports static, const, and dynamic casts, it implements atomic reference-counting and thread-safe semantics, it supports custom deleters. But note that, when I say it implements thread-safe semantics, it’s only for the pointer itself: remember it shares the pointer, not the data.

    It comes with a cost, though: to support polymorphism correctly, the size of QSharedPointer is actually twice the size of a normal pointer. This means you cannot maintain binary compatibility while replacing a normal pointer with it in public parts of your API. You can use it internally in your code, though.

    6. QWeakPointer

    This is the companion class of QSharedPointer. If that implements a strong control of the pointer, QWeakPointer is a weak smart pointer class, sharing the pointer. It works in tandem with QSharedPointer: QWeakPointer can only be created from a QSharedPointer and they let you know when a QSharedPointer has been deleted.

    They can be promoted to QSharedPointer, though, in a thread-safe manner. So it allows us to rewrite the code above to be safer:

        QWeakPointer<Data> weak(getSharedPointer());
    
        // […]
        QSharedPointer<Data> ptr = weak;
        if (!ptr.isNull())
            ptr->doSomething();
    

    In this case, the promotion of a QWeakPointer to a QSharedPointer will either succeed or it won’t. But that’s a thread-safe decision: if it does succeed, then the resulting object is guaranteed not to get deleted, while you hold the ptr reference (again, as long as everyone plays by the same rules).

    With 4.6, I added a nifty new feature to QWeakPointer: its ability to track QObjects as well, without passing through a QSharedPointer. It can be used to determine whether a QObject-derived object has been deleted already or not. So it implements a weak pointer class sharing the pointer value for QObject-derived classes. Sounds familiar? Yes, that’s the idea: you can replace the old, slow QPointer with a faster, modern alternative. Just be careful that the size of QWeakPointer is not the same size of QPointer.

    7. QGuard

    This is another internal class. It was added to replace QPointer because that is very slow (it uses a global, mutex-protected QHash, which must be accessed by every QObject destructor). It’s actually what prompted me to write the QWeakPointer QObject-tracking feature. But it’s in a state of flux: we don’t know whether we’re going to keep or even use this class. Anyway, it’s internal, so you really don’t care about it.

    8. QScopedPointer

    This is the new kid in the block: it implements a non-shared strong pointer wrapper. It was created because of our attempt at handling the Symbian platform’s exceptions in our container classes: we needed a way to free resources without writing try/catch everywhere. A scoped pointer provides a very nice way to do RAII. In fact, QScopedPointer is actually a full replacement for QtXmlPattern’s QtPatternist::AutoPtr. Both implement the same functionality, so the internal one can be dropped.

    Some people commented in Harald’s blog that we could’ve used QSharedPointer. Actually, we couldn’t: QSharedPointer has the size of two pointers, but we’re replacing Qt code that has the size of one pointer, so we needed a class that fits into that space. That’s also the reason why QScopedPointer has a custom deleter as a template parameter, as opposed to a parameter to the constructor (like QSharedPointer does): it has no space in those 4 or 8 bytes to store the custom deleter.

    What’s more, QSharedPointer implements atomic reference-counting. Never mind the fact that it’s atomic: the reference counting is absolutely unnecessary for the cases that QScopedPointer is trying to solve.

    Why not C++0x? Why not TR1? Why not Boost?

    Some people in Harald’s blog suggested we should use std::shared_ptr (C++0x) or std::tr1::shared_ptr (TR1). I’m sorry, but those people didn’t see very far: we can’t use C++0x. It’s not even approved and there are only two compilers that implement initial support for it (GCC since 4.3 and MSVC 2010, which is in beta). It’s not even funny to suggest using C++0x for Qt at this point. You can use it for your own code, but we can’t use it in Qt.

    TR1 has been implemented by more compilers. Unfortunately, not enough. We have to deal with compilers that haven’t implemented C++98 fully yet — or people who don’t bother to change their compiler settings. For example, the latest version of the Sun Studio compiler on Solaris (Sun Studio 12, with CC 5.10) still comes with the RogueWave implementation of pre-C++98 STL. If you read Sun’s article comparing RW stdlib to stlport4, you’ll see why they still keep the 11-year-old library as default. But the point is that they do, which means we have to deal with it. (Fortunately, other compiler vendors provide newer STL implementations, even though their compilers are sometimes far too picky)

    That means the only smart pointer from STL we can use in Qt is std::auto_ptr. And even then there are issues (RW stdlib doesn’t implement member templates).

    That leaves Boost. And there are some nice things in Boost: boost::shared_ptr, boost::intrusive_ptr, boost::scoped_ptr, etc. In fact, there are a lot of nice things in Boost. Very often I see things there that I’d like to have in Qt. Of course, that means I can just add said feature to Qt as well. There’s nothing stopping me, aside from, well, my day job :-)

    One of the main problems with boost is that it provides an “un-Qt-ish” API — to say the least; I prefer calling it “horrible API”, but that’s a statement of opinion, not fact. Even if Boost’s API is intuitive to some people, it represents a departure from Qt’s API. That means those people using Qt and Boost need to learn Boost’s way of doing things as well, their naming of functions, etc.

    At the very least, we’d have to wrap Boost’s API around with a Qt shell. But if we go further, we see that Qt loses control of an important piece of its technology. We then have to deal with whatever problems they have, at their schedules. Also, it adds a dependency to Qt, one we can’t justify because they don’t promise binary compatibility (cursory search over the web; please correct me if I’m wrong). Binary compatibility is the other of the main problems.

    So, no, Boost is not an option either.

    Conclusion

    So Qt has too many smart pointer classes. Or does it?

    In fact, Qt has only these pointer classes if you exclude the internal classes and you deprecate QPointer:

    Class Description
    QSharedDataPointer / QExplicitlySharedDataPointer Implements sharing of data (not of pointers), implicitly and explicitly, respectively
    QSharedPointer Implements reference-counted strong sharing of pointers
    QWeakPointer Implements reference-counted weak sharing of pointers
    QScopedPointer / QScopedArrayPointer Implements non-reference-counted strong pointer wrapper (QSharedPointer’s little brother)

    Update 1: QExplicitlySharedDataPointer can be used to implement reference-counted sharing of pointers when the target class includes the reference counter (similar to boost::intrusive_ptr)

    Update 2: QScopedPointer is really based on the API of boost::scoped_ptr (but is not a copy); QSharedPointer and QWeakPointer were developed from the scratch.

    André
    Qt
    Posted by André
     in Qt
     on Monday, August 24, 2009 @ 10:40

    I wanted to do a certain bit of benchmarking for quite a while - years actually - but triggered by one of those friendly discussions on the ##c++ channel on FreeNode I finally figured I should sit down and actually do it. I was expecting some interesting results, but the not at the scale that we will see below.

    If you ask the resident channel bot on ##c++ how to tokenize a std::string you’ll get offered the following (slightly compacted) code snippet:

      #include <sstream>
      #include <vector>
      #include <string>
    
      std::string str("abc:def");
      std::istringstream split(str);
      std::vector<std ::string> tokens;
      for (std::string each; std::getline(split, each, ':'); tokens.push_back(each));
    

    Obviously, that’s the “Without Qt” version: Clean Standard C++, as straight-forward as it can get. The contender “With Qt” is:

      #include <QString>
      #include <QStringList> 
    
      QString str("abc:def");
      QStringList tokens = str.split(':');
    

    From the source alone we can collect a few numbers:

    Property   Without Qt   With Qt   Ratio
    Code to type   3 lines   1 line   3.0
      147 char   35 chars   4.2
    Code usable as sub-expression   no   yes
    Size of compilation unit [1]   22215 lines   7590 lines   2.9
    Compile time [2]   1.64s   1.02s   1.6

    To compare performance I use a benchmark that I just checked into the Qt source base, under tests/benchmark/qstringlist. It basically consists of running the above mentioned snippets on a string “unit:unit:unit:….” with 10, 100, 1000, and 10000 “unit” chunks and record callgrind’s “instruction loads per iteration” as follows:

    Chunk count   Without Qt   With Qt   Ratio
    10 chunks     18,455   9,827   1.9
    100 chunks     134,578   71,008   1.9
    1000 chunks     1,244,425   641,174   1.9
    10000 chunks     13,161,115   7,053,633   1.9

    In this case, bigger numbers mean more time needed to execute. Interesting, isn’t it?

    After reading Thiago’s latest posts I got the impression that people like conclusions. The verbose version of a conclusion might be something along the lines of

    Using Qt’s functions to split a string you need about a third of the effort to write code, and get a 47% performance boost at runtime.

    Or shorter (Qt way): “Code less, create more”.

    André

    [1] Counted with “g++ -E -DQT_NO_STL -I$QTDIR/include/QtCore -I$QTDIR/include qt.cpp | wc” using g++ Ubuntu 4.3.3-5ubuntu4.

    [2] Fastest result of “real” time, out of 20 runs each. “user” times in both scenarios smaller, with similar ratio.

    Harald Fernengel
    Qt
    KDE
     in Qt, KDE
     on Friday, August 21, 2009 @ 16:51

    Qt usually takes the boring memory allocation and deallocation from you, either through its implicitly shared containers, or with QObject’s parent child relationship model. But every once in a while, we need to allocate something on the heap, and then the stress starts - where do we delete it, and how do we make sure to not leak the memory?

    To fix this problem, QScopedPointer was born. It will delete the object it is pointing to automatically when it goes out of scope:

    void foo()
    {
        QScopedPointer<int> i(new int(42));
        …
        if (someCondition)
            return; // our integer on the heap will either be deleted here…
        …
    } // … or here

    A new exit condition in our function will not make it leak the integer that we allocated.

    So how do we access the object that we are pointing to? QScopedPointer implements operator* and operator->, so you it can be accessed just like any other pointer:

        QScopedPointer<int> i(new int(42));
        *i = 43;

    Some operators are missing by design, for example the assignment operator:

        QScopedPointer<int> i(new int(42));
        i = new int(43); // will not compile
        i.reset(new int(43)); // correct

    We figured that “reset” looks scary enough to make the reader realize that the old object is deleted, and the QScopedPointer is now pointing to the new object.

    Another operator that is missing by design is the operator T*() that would allow accessing the pointer directly. This prevents accidents like:

    int *foo()
    {
        QScopedPointer<int> i(new int(42));
        …
        return i; // thankfully, this does not compile.
    }

    Do you see the mistake? The moment we return, our object will be deleted, because the scoped pointer goes out of scope. We would return a dangling pointer, potentially leading to a nasty crash. However, we can tell QScopedPointer that its job is done and that we take ownership of the heap object by calling take(). Our function might look like this:

    int *foo()
    {
        QScopedPointer<int> i(new int(42));
        …
        if (someError)
            return 0; // our integer is deleted here
        return i.take(); // from now on, our heap object is on its own.
    }

    But what about memory allocated with malloc, or the operator new[] for arrays? For those cases, we introduced a second template parameter to QScopedPointer that defines the cleanup:

    QScopedPointer<int, QScopedPointerPodDeleter> pod(static_cast<int *>(malloc(sizeof int)));

    QScopedPointerPodDeleter (pod stands for “plain old data”) will call free on the object if our QScopedPointer goes out of scope.

    For convenience, there is a QScopedArrayPointer that defaults to deleting the object it is pointing to with the delete[] operator. It also features operator[] for convenience, so we can write:

    void foo()
    {
        QScopedArrayPointer<int> i(new int[10]);
        i[2] = 42;
        …
        return; // our integer array is now deleted using delete[]
    }

    Note that if you have a reference counted object, you can use QExplicitlySharedDataPointer to ensure that an object is deleted correctly when its reference count goes to 0.

    QScopedPointer and QExplicitlySharedDataPointer are already used all over the place in the Qt for S60 branch and will soon hit Qt’s master branch. And the best part is that with the introduction of these smart pointers, we could remove lots of boring code and make Qt more readable without adding overhead - since all functions are inlined, the resulting binary using QScopedPointer is identical to the manual new/delete approach.

    Happy developing :)



    © 2008 Nokia Corporation and/or its subsidiaries. Nokia, Qt and their respective logos are trademarks of Nokia Corporation in Finland and/or other countries worldwide.
    All other trademarks are property of their respective owners.