For the past 2 weeks, I’ve been wrestling with a fix for task 208487. At first glance, it seems pretty far-fetched (at least it did to me): an application that has 2 billion running timers and runs out of timer ids. But then I went and looked at the code (that I wrote!) and the real problem slapped me in the face: any application can only ever start 2 billion timers in total (which is different from having 2 billion concurrent timers). We never recycle timer ids. That means that the following code will quit working after 24.85 days. If we change the timeout to be zero instead, the runtime is reduced to hours instead of days.
class Object : public QObject
{
Q_OBJECT
public:
Object() : QObject() { QTimer::singleShot(1, this, SLOT(timeout())); }
public slots:
void timeout() { QTimer::singleShot(1, this, SLOT(timeout())); }
};
After quickly rejecting the question “Should I fix this?” (of course I should!), I promptly got my hands dirty looking for a solution. Fixing this proved to be harder than I originally anticipated…
Read the rest of this entry »
The news about Nokia’s intentions to acquire Trolltech is very exciting and sobering at the same time. I would characterize my own opinions and thoughts as “cautiously optimistic.” As Trolls, we are still digesting the idea, discussing it amongst ourselves, and processing the incoming information from our own management team as well as the information from Nokia.
I hope that our community, both commercial and open-source alike, don’t get too distraught about a seemingly quiet Trolltech team. We, like you, just found out about this yesterday morning and need time to absorb what this means for us, for you, for everyone. After everything sinks in, we will come out with more information in the near future, and we appreciate your patience until then.
Rest assured, Nokia has the best intentions in making this move. More information will be available soon., however the message from Nokia is clear: development, sales, open-source and community support, etc. will continue as usual. Lee Williams, Senior VP, R&D at Nokia, told us Monday that Nokia wants us to teach them how to do cross-platform and open-source development on the desktop (and not just on mobile phones). This is a bit of a special acquisition because both Trolltech, in its current organizational form, and Nokia will be working together on what the future will bring.
A couple of years ago (3, to be exact), my girlfriend and I bought a house about 45 minutes outside of Oslo. The little village is just far enough and small enough to not get cable TV. So, that means we have to have satellite. I consider myself a lucky geek, because my tuner runs Linux.
Read the rest of this entry »
I just integrated a series of changes that adds support for doing multi-threaded text layout and printing. So it is now safe to use QFont and QFontMetrics outside the GUI thread. This means QPainter::drawText() works too (when painting on QImage, QPrinter, and QPicture). We’ve also done changes to QTextDocument that allow it to be cloned and passed off to a thread, so that all the layouting and printing happens without blocking the GUI.
For those interested, you can checkout tonight’s 4.4 snapshot. In tools/assistant/mainwindow.cpp, you’ll see code like this:
void PrintThread::start(QTextDocument *document)
{
_document = document->clone();
_document->moveToThread(this);
QThread::start();
}
void PrintThread::run()
{
_document->print(printer());
delete _document;
_document = 0;
}
void MainWindow::on_actionFilePrint_triggered()
{
if (!QFontDatabase::supportsThreadedFontRendering()) {
QPrinter printer(QPrinter::HighResolution);
printer.setFullPage(true);
QPrintDialog dlg(&printer, this);
if (dlg.exec() == QDialog::Accepted) {
qApp->setOverrideCursor(Qt::WaitCursor);
tabs->currentBrowser()->document()->print(&printer);
qApp->restoreOverrideCursor();
}
return;
}
PrintThread *thread = new PrintThread(this);
QPrintDialog dlg(thread->printer(), this);
if (dlg.exec() == QDialog::Accepted) {
connect(thread, SIGNAL(finished()), SLOT(printingFinished()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
qApp->setOverrideCursor(Qt::BusyCursor);
thread->start(tabs->currentBrowser()->document());
} else {
delete thread;
}
}
void MainWindow::printingFinished()
{
qApp->restoreOverrideCursor();
}
The Thread Support in Qt documentation has also been updated to show what is supported (Note, at the time of writing, the snapshot documentation has not been updated, check back later if you don’t have a 4.4 snapshot after 27 Sep 2007).
And just to be clear, painting onto a QPixmap or a QWidget outside the GUI is not supported at all. We are looking at ways of making the GL paint engine safe for painting on to FrameBufferObjects and/or Pbuffers, which may or may not make it into 4.4.
Yesterday, I closed task 168853, the “provide a cross-platform atomic API” task. After several rounds of API review (and literally hundreds of completely Qt rebuilds on every test machine), I added QAtomicInt and QAtomicPointer to the 4.4 snapshots. These classes provide atomic operations for integers and pointers, respectively. At the moment, each class supports atomic test-and-set, fetch-and-store, and fetch-and-add. QAtomicInt also supports atomic reference counting with the ref() and deref() functions.
In addition to the actual atomic API, QAtomicInt and QAtomicPointer also provide an API to check whether the hardware supports a particular operation natively, and if the implementation is wait-free. For example, there’s the monstrous Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NATIVELY_SUPPORTED and Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE macros for compile-time checking, and QAtomicInt::isReferenceCountingNative() and QAtomicInt::isReferenceCountingWaitFree() for run-time checking. Note that run-time checking is really only needed if Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE is defined. This gives us, for example, the possibility of building a generic ARM binary that runs on today’s Xscale processors (ARMv5) or an ARMv6 processor (which adds load-linked/store-conditional instructions to support multi-processor/multi-core devices).
So, go get the 4.4 snapshot and give it try. Any and all feedback is welcome 
In a previous blog, I talked about wanting to make QThread::run() call QThread::exec() by default.
I didn’t manage to get it in for 4.3, but I did make the change today for 4.4. Testing with every compiler I could get my hands on indicates that it’s a binary compatible change, so unless proven otherwise, this will go into the 4.4 release (and no, I don’t know when 4.4 be released :D).
This change makes the original example in the previous blog as straight forward as I can get it. Have a look for yourself and see what you think…
A couple of weeks ago, I started trying to find out if a pure virtual function can be made impure without breaking binary compatibility. “Why?” you ask? Because I want to make QThread::run() call QThread::exec() by default. We all know that threading is difficult to do, mostly because of the need to lock data, synchronize threads (with a QWaitCondition or QSemaphore, for example). However, it doesn’t have to be.
Read the rest of this entry »
I just realized that I didn’t actually explain how to interpret the results of the benchmark I mentioned in my previous post. So, here it is…
Read the rest of this entry »
So, I just returned from DevDays2006 in Munich, and I figured I would finish this blog posting, since I mentioned in my presentations.
Starting with Qt 4.0, all implicitly shared classes in Qt use atomic reference counting to ensure the integrity of the data being shared. This removes a burden from the application programmer: the need to force deep-copies when passing data to another thread. The end result is that my life gets a whole lot easier (no more support questions from people who forgot to make a deep-copy) and your life gets a whole lot easier (since you don’t have to worry about making deep-copies). Great! Wonderful!! Right?
Read the rest of this entry »
I really need to get into the habit of this blog thing. Anyway, I needed a small break from what I was doing before I head up to the cafeteriafor lunch.
I somehow managed to volunteer for giving 3 presentations during Trolltech Developer Days 2006. I’m mostly done with the multi-threading presentation; I just have to add some code examples. Once I’m done with the Qt in depth presentation, I’ll add a little “bonus” material to the multi-threading presentation (so that I have something to talk about if we get some extra time). The hardest one to write is going to be the application development on Linux for Windows developers presentation. I’ve been using xemacs for so long, that I’ll have to teach myself how to use some of the other editors.
So, I’ve got lots to do, but I’m really looking forward to DevDays this year. I didn’t go last year, which I regret. Guess that’s why I over-compenstated this year 