Static functions

Bo Thorsen bo at sonofthor.dk
Mon Jan 12 13:56:45 GMT 2004


Hi all,

I just convinced myself it was time to remind everyone of this old 
feature: Static functions. I know lots of you already know about this 
feature, but I've seen too many places where it isn't used, so I thought 
I'd give a heads up on it.

The reason for using these is optimization - especially when it comes to 
libraries. And since almost all of KDE is made up of libraries, this 
really is important.

First application: Helper methods:

There are too many places in KDE where we have helper functions like this:

bool doSomething(...) {
   ...
}

If you search the object file or the library after compilation (for 
example with readelf -s thefile.o) you will see the symbol in the symbol 
table of the file. And the places that use these file will have a 
reference to this symbol. This means when the runtime linker loads the 
library, it needs to spend time matching the call to doSomething with the 
place of the code. If you instead do this:

static bool doSomething(...) {
   ...
}

the symbol is no longer in the object file, and all uses are linked at 
compile time, so you no longer spend time in the linker.

Another good thing here is that you won't pollute the local namespace 
inside the library, but that point is moot in KDE, since --enable-final 
makes it impossible to have two identical methods anyway.

Another application of this: Private methods.

In KMail:kmgroupware.* I had a static attribute called 
mKOrganizerIfaceStub. This was used by various internal methods to call 
KOrganizer, and there was a connectToKOrganizer method that set up the 
stub, and a DCOP slot that listened to the user shutting down KOrganizer.

That means I had this:

class KMGroupware : public QObject {
private slots:
  void unregisteredFromDCOP( const QCString& );

private:
  void iCalRequest( const QString& receiver, const QString& iCal,
                    const QString& choice );
  void iCalCancel( const QString& iCal );
  void iCalReply( const QString& iCal );

  static bool connectToKOrganizer();

  static KOrganizerIface_stub* mKOrganizerIfaceStub;
};

(all irrelevant parts not shown.) In kmgroupware.cpp I then had the 
implementation of all these class items. This is - arguably - a nice 
object oriented approach, since the helper functions are private methods 
here. It's unfortunately also bad for the runtime linker, since all these 
symbols must be relocated at runtime.

The iCal* methods only used the stub, but they were still object methods 
because of leftover code from kroupware_branch (all this is from a 
refactoring process I did today).

I changed the interface to be this:

class KMGroupware : public QObject {
private slots:
  void unregisteredFromDCOP( const QCString& );
};

and in the .cpp file I now have:

static KOrganizerIface_stub* mKOrganizerIfaceStub;
static bool connectToKOrganizer() {
  ...
}

and so on.

This means the code is basically unchanged, but the header file is less 
cluttered and the number of relocations goes down, giving a shorter load 
time of the library/application/part.

This is not in any way an advanced feature, and it doesn't make that big a 
difference. It's just that there are absolutely no reasons *not* to use 
this.

I hope this was interesting or helpful.

Bo.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: signature
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20040112/8ffd610c/attachment.sig>


More information about the kde-core-devel mailing list